1 /* 2 * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.javadoc.internal.doclets.formats.html; 27 28 import jdk.javadoc.internal.doclets.formats.html.markup.Table; 29 import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader; 30 31 import java.util.*; 32 33 import javax.lang.model.element.PackageElement; 34 import javax.lang.model.element.TypeElement; 35 36 import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; 37 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants; 38 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; 39 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; 40 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; 41 import jdk.javadoc.internal.doclets.formats.html.markup.Navigation; 42 import jdk.javadoc.internal.doclets.formats.html.markup.Navigation.PageMode; 43 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; 44 import jdk.javadoc.internal.doclets.toolkit.Content; 45 import jdk.javadoc.internal.doclets.toolkit.util.ClassUseMapper; 46 import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException; 47 import jdk.javadoc.internal.doclets.toolkit.util.DocPath; 48 import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; 49 50 /** 51 * Generate package usage information. 52 * 53 * <p><b>This is NOT part of any supported API. 54 * If you write code that depends on this, you do so at your own risk. 55 * This code and its internal interfaces are subject to change or 56 * deletion without notice.</b> 57 * 58 * @author Robert G. Field 59 * @author Bhavesh Patel (Modified) 60 */ 61 public class PackageUseWriter extends SubWriterHolderWriter { 62 63 final PackageElement packageElement; 64 final SortedMap<String, Set<TypeElement>> usingPackageToUsedClasses = new TreeMap<>(); 65 protected HtmlTree mainTree = HtmlTree.MAIN(); 66 final String packageUseTableSummary; 67 private final Navigation navBar; 68 69 /** 70 * Constructor. 71 * 72 * @param configuration the configuration 73 * @param mapper a mapper to provide details of where elements are used 74 * @param filename the file to be generated 75 * @param pkgElement the package element to be documented 76 */ PackageUseWriter(HtmlConfiguration configuration, ClassUseMapper mapper, DocPath filename, PackageElement pkgElement)77 public PackageUseWriter(HtmlConfiguration configuration, 78 ClassUseMapper mapper, DocPath filename, 79 PackageElement pkgElement) { 80 super(configuration, configuration.docPaths.forPackage(pkgElement).resolve(filename)); 81 this.packageElement = pkgElement; 82 83 // by examining all classes in this package, find what packages 84 // use these classes - produce a map between using package and 85 // used classes. 86 for (TypeElement usedClass : utils.getEnclosedTypeElements(pkgElement)) { 87 Set<TypeElement> usingClasses = mapper.classToClass.get(usedClass); 88 if (usingClasses != null) { 89 for (TypeElement usingClass : usingClasses) { 90 PackageElement usingPackage = utils.containingPackage(usingClass); 91 Set<TypeElement> usedClasses = usingPackageToUsedClasses 92 .get(utils.getPackageName(usingPackage)); 93 if (usedClasses == null) { 94 usedClasses = new TreeSet<>(utils.makeGeneralPurposeComparator()); 95 usingPackageToUsedClasses.put(utils.getPackageName(usingPackage), 96 usedClasses); 97 } 98 usedClasses.add(usedClass); 99 } 100 } 101 } 102 103 packageUseTableSummary = resources.getText("doclet.Use_Table_Summary", 104 resources.getText("doclet.packages")); 105 this.navBar = new Navigation(packageElement, configuration, fixedNavDiv, PageMode.USE, path); 106 } 107 108 /** 109 * Generate a class page. 110 * 111 * @param configuration the current configuration of the doclet. 112 * @param mapper the mapping of the class usage. 113 * @param pkgElement the package being documented. 114 * @throws DocFileIOException if there is a problem generating the package use page 115 */ generate(HtmlConfiguration configuration, ClassUseMapper mapper, PackageElement pkgElement)116 public static void generate(HtmlConfiguration configuration, 117 ClassUseMapper mapper, PackageElement pkgElement) 118 throws DocFileIOException { 119 DocPath filename = DocPaths.PACKAGE_USE; 120 PackageUseWriter pkgusegen = new PackageUseWriter(configuration, mapper, filename, pkgElement); 121 pkgusegen.generatePackageUseFile(); 122 } 123 124 /** 125 * Generate the package use list. 126 * @throws DocFileIOException if there is a problem generating the package use page 127 */ generatePackageUseFile()128 protected void generatePackageUseFile() throws DocFileIOException { 129 HtmlTree body = getPackageUseHeader(); 130 HtmlTree div = new HtmlTree(HtmlTag.DIV); 131 div.setStyle(HtmlStyle.contentContainer); 132 if (usingPackageToUsedClasses.isEmpty()) { 133 div.addContent(contents.getContent("doclet.ClassUse_No.usage.of.0", utils.getPackageName(packageElement))); 134 } else { 135 addPackageUse(div); 136 } 137 if (configuration.allowTag(HtmlTag.MAIN)) { 138 mainTree.addContent(div); 139 body.addContent(mainTree); 140 } else { 141 body.addContent(div); 142 } 143 HtmlTree tree = (configuration.allowTag(HtmlTag.FOOTER)) 144 ? HtmlTree.FOOTER() 145 : body; 146 navBar.setUserFooter(getUserHeaderFooter(false)); 147 tree.addContent(navBar.getContent(false)); 148 addBottom(tree); 149 if (configuration.allowTag(HtmlTag.FOOTER)) { 150 body.addContent(tree); 151 } 152 printHtmlDocument(null, true, body); 153 } 154 155 /** 156 * Add the package use information. 157 * 158 * @param contentTree the content tree to which the package use information will be added 159 */ addPackageUse(Content contentTree)160 protected void addPackageUse(Content contentTree) { 161 HtmlTree ul = new HtmlTree(HtmlTag.UL); 162 ul.setStyle(HtmlStyle.blockList); 163 if (configuration.packages.size() > 1) { 164 addPackageList(ul); 165 } 166 addClassList(ul); 167 contentTree.addContent(ul); 168 } 169 170 /** 171 * Add the list of packages that use the given package. 172 * 173 * @param contentTree the content tree to which the package list will be added 174 */ addPackageList(Content contentTree)175 protected void addPackageList(Content contentTree) { 176 Content caption = contents.getContent( 177 "doclet.ClassUse_Packages.that.use.0", 178 getPackageLink(packageElement, utils.getPackageName(packageElement))); 179 Table table = new Table(configuration.htmlVersion, HtmlStyle.useSummary) 180 .setSummary(packageUseTableSummary) 181 .setCaption(caption) 182 .setHeader(getPackageTableHeader()) 183 .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colLast); 184 for (String pkgname: usingPackageToUsedClasses.keySet()) { 185 PackageElement pkg = utils.elementUtils.getPackageElement(pkgname); 186 Content packageLink = links.createLink(utils.getPackageName(pkg), 187 new StringContent(utils.getPackageName(pkg))); 188 Content summary = new ContentBuilder(); 189 if (pkg != null && !pkg.isUnnamed()) { 190 addSummaryComment(pkg, summary); 191 } else { 192 summary.addContent(Contents.SPACE); 193 } 194 table.addRow(packageLink, summary); 195 } 196 Content li = HtmlTree.LI(HtmlStyle.blockList, table.toContent()); 197 contentTree.addContent(li); 198 } 199 200 /** 201 * Add the list of classes that use the given package. 202 * 203 * @param contentTree the content tree to which the class list will be added 204 */ addClassList(Content contentTree)205 protected void addClassList(Content contentTree) { 206 TableHeader classTableHeader = new TableHeader( 207 contents.classLabel, contents.descriptionLabel); 208 for (String packageName : usingPackageToUsedClasses.keySet()) { 209 PackageElement usingPackage = utils.elementUtils.getPackageElement(packageName); 210 HtmlTree li = new HtmlTree(HtmlTag.LI); 211 li.setStyle(HtmlStyle.blockList); 212 if (usingPackage != null) { 213 li.addContent(links.createAnchor(utils.getPackageName(usingPackage))); 214 } 215 String tableSummary = resources.getText("doclet.Use_Table_Summary", 216 resources.getText("doclet.classes")); 217 Content caption = contents.getContent( 218 "doclet.ClassUse_Classes.in.0.used.by.1", 219 getPackageLink(packageElement, utils.getPackageName(packageElement)), 220 getPackageLink(usingPackage, utils.getPackageName(usingPackage))); 221 Table table = new Table(configuration.htmlVersion, HtmlStyle.useSummary) 222 .setSummary(tableSummary) 223 .setCaption(caption) 224 .setHeader(classTableHeader) 225 .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colLast); 226 for (TypeElement te : usingPackageToUsedClasses.get(packageName)) { 227 DocPath dp = pathString(te, 228 DocPaths.CLASS_USE.resolve(docPaths.forName(te))); 229 Content stringContent = new StringContent(utils.getSimpleName(te)); 230 Content typeContent = links.createLink(dp.fragment(getPackageAnchorName(usingPackage)), 231 stringContent); 232 Content summary = new ContentBuilder(); 233 addIndexComment(te, summary); 234 235 table.addRow(typeContent, summary); 236 } 237 li.addContent(table.toContent()); 238 contentTree.addContent(li); 239 } 240 } 241 242 /** 243 * Get the header for the package use listing. 244 * 245 * @return a content tree representing the package use header 246 */ getPackageUseHeader()247 private HtmlTree getPackageUseHeader() { 248 String packageText = resources.getText("doclet.Package"); 249 String name = packageElement.isUnnamed() ? "" : utils.getPackageName(packageElement); 250 String title = resources.getText("doclet.Window_ClassUse_Header", packageText, name); 251 HtmlTree bodyTree = getBody(true, getWindowTitle(title)); 252 HtmlTree htmlTree = (configuration.allowTag(HtmlTag.HEADER)) 253 ? HtmlTree.HEADER() 254 : bodyTree; 255 addTop(htmlTree); 256 Content linkContent = getModuleLink(utils.elementUtils.getModuleOf(packageElement), 257 contents.moduleLabel); 258 navBar.setNavLinkModule(linkContent); 259 navBar.setUserHeader(getUserHeaderFooter(true)); 260 htmlTree.addContent(navBar.getContent(true)); 261 if (configuration.allowTag(HtmlTag.HEADER)) { 262 bodyTree.addContent(htmlTree); 263 } 264 ContentBuilder headContent = new ContentBuilder(); 265 headContent.addContent(contents.getContent("doclet.ClassUse_Title", packageText)); 266 headContent.addContent(new HtmlTree(HtmlTag.BR)); 267 headContent.addContent(name); 268 Content heading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, true, 269 HtmlStyle.title, headContent); 270 Content div = HtmlTree.DIV(HtmlStyle.header, heading); 271 if (configuration.allowTag(HtmlTag.MAIN)) { 272 mainTree.addContent(div); 273 } else { 274 bodyTree.addContent(div); 275 } 276 return bodyTree; 277 } 278 } 279