1 /* 2 * Copyright (c) 1998, 2020, 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 java.util.Set; 29 import java.util.SortedMap; 30 import java.util.TreeMap; 31 import java.util.TreeSet; 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.Entity; 38 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; 39 import jdk.javadoc.internal.doclets.formats.html.markup.TagName; 40 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; 41 import jdk.javadoc.internal.doclets.formats.html.Navigation.PageMode; 42 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; 43 import jdk.javadoc.internal.doclets.formats.html.markup.Table; 44 import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader; 45 import jdk.javadoc.internal.doclets.toolkit.Content; 46 import jdk.javadoc.internal.doclets.toolkit.util.ClassUseMapper; 47 import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException; 48 import jdk.javadoc.internal.doclets.toolkit.util.DocPath; 49 import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; 50 51 /** 52 * Generate package usage information. 53 * 54 * <p><b>This is NOT part of any supported API. 55 * If you write code that depends on this, you do so at your own risk. 56 * This code and its internal interfaces are subject to change or 57 * deletion without notice.</b> 58 */ 59 public class PackageUseWriter extends SubWriterHolderWriter { 60 61 final PackageElement packageElement; 62 final SortedMap<String, Set<TypeElement>> usingPackageToUsedClasses = new TreeMap<>(); 63 final String packageUseTableSummary; 64 private final Navigation navBar; 65 66 /** 67 * Constructor. 68 * 69 * @param configuration the configuration 70 * @param mapper a mapper to provide details of where elements are used 71 * @param filename the file to be generated 72 * @param pkgElement the package element to be documented 73 */ PackageUseWriter(HtmlConfiguration configuration, ClassUseMapper mapper, DocPath filename, PackageElement pkgElement)74 public PackageUseWriter(HtmlConfiguration configuration, 75 ClassUseMapper mapper, DocPath filename, 76 PackageElement pkgElement) { 77 super(configuration, configuration.docPaths.forPackage(pkgElement).resolve(filename)); 78 this.packageElement = pkgElement; 79 80 // by examining all classes in this package, find what packages 81 // use these classes - produce a map between using package and 82 // used classes. 83 for (TypeElement usedClass : utils.getEnclosedTypeElements(pkgElement)) { 84 Set<TypeElement> usingClasses = mapper.classToClass.get(usedClass); 85 if (usingClasses != null) { 86 for (TypeElement usingClass : usingClasses) { 87 PackageElement usingPackage = utils.containingPackage(usingClass); 88 Set<TypeElement> usedClasses = usingPackageToUsedClasses 89 .get(utils.getPackageName(usingPackage)); 90 if (usedClasses == null) { 91 usedClasses = new TreeSet<>(comparators.makeGeneralPurposeComparator()); 92 usingPackageToUsedClasses.put(utils.getPackageName(usingPackage), 93 usedClasses); 94 } 95 usedClasses.add(usedClass); 96 } 97 } 98 } 99 100 packageUseTableSummary = resources.getText("doclet.Use_Table_Summary", 101 resources.getText("doclet.packages")); 102 this.navBar = new Navigation(packageElement, configuration, PageMode.USE, path); 103 } 104 105 /** 106 * Generate a class page. 107 * 108 * @param configuration the current configuration of the doclet. 109 * @param mapper the mapping of the class usage. 110 * @param pkgElement the package being documented. 111 * @throws DocFileIOException if there is a problem generating the package use page 112 */ generate(HtmlConfiguration configuration, ClassUseMapper mapper, PackageElement pkgElement)113 public static void generate(HtmlConfiguration configuration, 114 ClassUseMapper mapper, PackageElement pkgElement) 115 throws DocFileIOException { 116 DocPath filename = DocPaths.PACKAGE_USE; 117 PackageUseWriter pkgusegen = new PackageUseWriter(configuration, mapper, filename, pkgElement); 118 pkgusegen.generatePackageUseFile(); 119 } 120 121 /** 122 * Generate the package use list. 123 * @throws DocFileIOException if there is a problem generating the package use page 124 */ generatePackageUseFile()125 protected void generatePackageUseFile() throws DocFileIOException { 126 HtmlTree body = getPackageUseHeader(); 127 Content mainContent = new ContentBuilder(); 128 if (usingPackageToUsedClasses.isEmpty()) { 129 mainContent.add(contents.getContent("doclet.ClassUse_No.usage.of.0", utils.getPackageName(packageElement))); 130 } else { 131 addPackageUse(mainContent); 132 } 133 bodyContents.addMainContent(mainContent); 134 HtmlTree footer = HtmlTree.FOOTER(); 135 navBar.setUserFooter(getUserHeaderFooter(false)); 136 footer.add(navBar.getContent(Navigation.Position.BOTTOM)); 137 addBottom(footer); 138 bodyContents.setFooter(footer); 139 body.add(bodyContents); 140 printHtmlDocument(null, 141 getDescription("use", packageElement), 142 body); 143 } 144 145 /** 146 * Add the package use information. 147 * 148 * @param contentTree the content tree to which the package use information will be added 149 */ addPackageUse(Content contentTree)150 protected void addPackageUse(Content contentTree) { 151 Content content = new ContentBuilder(); 152 if (configuration.packages.size() > 1) { 153 addPackageList(content); 154 } 155 addClassList(content); 156 contentTree.add(content); 157 } 158 159 /** 160 * Add the list of packages that use the given package. 161 * 162 * @param contentTree the content tree to which the package list will be added 163 */ addPackageList(Content contentTree)164 protected void addPackageList(Content contentTree) { 165 Content caption = contents.getContent( 166 "doclet.ClassUse_Packages.that.use.0", 167 getPackageLink(packageElement, utils.getPackageName(packageElement))); 168 Table table = new Table(HtmlStyle.useSummary, HtmlStyle.summaryTable) 169 .setCaption(caption) 170 .setHeader(getPackageTableHeader()) 171 .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colLast); 172 for (String pkgname: usingPackageToUsedClasses.keySet()) { 173 PackageElement pkg = utils.elementUtils.getPackageElement(pkgname); 174 Content packageLink = links.createLink(getPackageAnchorName(pkg), 175 new StringContent(utils.getPackageName(pkg))); 176 Content summary = new ContentBuilder(); 177 if (pkg != null && !pkg.isUnnamed()) { 178 addSummaryComment(pkg, summary); 179 } else { 180 summary.add(Entity.NO_BREAK_SPACE); 181 } 182 table.addRow(packageLink, summary); 183 } 184 contentTree.add(table); 185 } 186 187 /** 188 * Add the list of classes that use the given package. 189 * 190 * @param contentTree the content tree to which the class list will be added 191 */ addClassList(Content contentTree)192 protected void addClassList(Content contentTree) { 193 TableHeader classTableHeader = new TableHeader( 194 contents.classLabel, contents.descriptionLabel); 195 HtmlTree ul = new HtmlTree(TagName.UL); 196 ul.setStyle(HtmlStyle.blockList); 197 for (String packageName : usingPackageToUsedClasses.keySet()) { 198 PackageElement usingPackage = utils.elementUtils.getPackageElement(packageName); 199 HtmlTree section = HtmlTree.SECTION(HtmlStyle.detail) 200 .setId(getPackageAnchorName(usingPackage)); 201 String tableSummary = resources.getText("doclet.Use_Table_Summary", 202 resources.getText("doclet.classes")); 203 Content caption = contents.getContent( 204 "doclet.ClassUse_Classes.in.0.used.by.1", 205 getPackageLink(packageElement, utils.getPackageName(packageElement)), 206 getPackageLink(usingPackage, utils.getPackageName(usingPackage))); 207 Table table = new Table(HtmlStyle.useSummary, HtmlStyle.summaryTable) 208 .setCaption(caption) 209 .setHeader(classTableHeader) 210 .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colLast); 211 for (TypeElement te : usingPackageToUsedClasses.get(packageName)) { 212 DocPath dp = pathString(te, 213 DocPaths.CLASS_USE.resolve(docPaths.forName(te))); 214 Content stringContent = new StringContent(utils.getSimpleName(te)); 215 Content typeContent = links.createLink(dp.fragment(getPackageAnchorName(usingPackage)), 216 stringContent); 217 Content summary = new ContentBuilder(); 218 addIndexComment(te, summary); 219 220 table.addRow(typeContent, summary); 221 } 222 section.add(table); 223 ul.add(HtmlTree.LI(section)); 224 } 225 Content li = HtmlTree.SECTION(HtmlStyle.packageUses, ul); 226 contentTree.add(li); 227 } 228 229 /** 230 * Get the header for the package use listing. 231 * 232 * @return a content tree representing the package use header 233 */ getPackageUseHeader()234 private HtmlTree getPackageUseHeader() { 235 String packageText = resources.getText("doclet.Package"); 236 String name = packageElement.isUnnamed() ? "" : utils.getPackageName(packageElement); 237 String title = resources.getText("doclet.Window_ClassUse_Header", packageText, name); 238 HtmlTree bodyTree = getBody(getWindowTitle(title)); 239 Content headerContent = new ContentBuilder(); 240 addTop(headerContent); 241 Content linkContent = getModuleLink(utils.elementUtils.getModuleOf(packageElement), 242 contents.moduleLabel); 243 navBar.setNavLinkModule(linkContent); 244 navBar.setUserHeader(getUserHeaderFooter(true)); 245 headerContent.add(navBar.getContent(Navigation.Position.TOP)); 246 ContentBuilder headingContent = new ContentBuilder(); 247 headingContent.add(contents.getContent("doclet.ClassUse_Title", packageText)); 248 headingContent.add(new HtmlTree(TagName.BR)); 249 headingContent.add(name); 250 Content heading = HtmlTree.HEADING_TITLE(Headings.PAGE_TITLE_HEADING, 251 HtmlStyle.title, headingContent); 252 Content div = HtmlTree.DIV(HtmlStyle.header, heading); 253 bodyContents.setHeader(headerContent) 254 .addMainContent(div); 255 return bodyTree; 256 } 257 } 258