1 /* 2 * Copyright (c) 1998, 2017, 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.Links; 42 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; 43 import jdk.javadoc.internal.doclets.toolkit.Content; 44 import jdk.javadoc.internal.doclets.toolkit.util.ClassUseMapper; 45 import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException; 46 import jdk.javadoc.internal.doclets.toolkit.util.DocPath; 47 import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; 48 49 /** 50 * Generate package usage information. 51 * 52 * <p><b>This is NOT part of any supported API. 53 * If you write code that depends on this, you do so at your own risk. 54 * This code and its internal interfaces are subject to change or 55 * deletion without notice.</b> 56 * 57 * @author Robert G. Field 58 * @author Bhavesh Patel (Modified) 59 */ 60 public class PackageUseWriter extends SubWriterHolderWriter { 61 62 final PackageElement packageElement; 63 final SortedMap<String, Set<TypeElement>> usingPackageToUsedClasses = new TreeMap<>(); 64 protected HtmlTree mainTree = HtmlTree.MAIN(); 65 final String packageUseTableSummary; 66 67 /** 68 * Constructor. 69 * 70 * @param configuration the configuration 71 * @param mapper a mapper to provide details of where elements are used 72 * @param filename the file to be generated 73 * @param pkgElement the package element to be documented 74 */ 75 public PackageUseWriter(HtmlConfiguration configuration, 76 ClassUseMapper mapper, DocPath filename, 77 PackageElement pkgElement) { 78 super(configuration, DocPath.forPackage(pkgElement).resolve(filename)); 79 this.packageElement = pkgElement; 80 81 // by examining all classes in this package, find what packages 82 // use these classes - produce a map between using package and 83 // used classes. 84 for (TypeElement usedClass : utils.getEnclosedTypeElements(pkgElement)) { 85 Set<TypeElement> usingClasses = mapper.classToClass.get(usedClass); 86 if (usingClasses != null) { 87 for (TypeElement usingClass : usingClasses) { 88 PackageElement usingPackage = utils.containingPackage(usingClass); 89 Set<TypeElement> usedClasses = usingPackageToUsedClasses 90 .get(utils.getPackageName(usingPackage)); 91 if (usedClasses == null) { 92 usedClasses = new TreeSet<>(utils.makeGeneralPurposeComparator()); 93 usingPackageToUsedClasses.put(utils.getPackageName(usingPackage), 94 usedClasses); 95 } 96 usedClasses.add(usedClass); 97 } 98 } 99 } 100 101 packageUseTableSummary = resources.getText("doclet.Use_Table_Summary", 102 resources.getText("doclet.packages")); 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 */ 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 */ 125 protected void generatePackageUseFile() throws DocFileIOException { 126 HtmlTree body = getPackageUseHeader(); 127 HtmlTree div = new HtmlTree(HtmlTag.DIV); 128 div.setStyle(HtmlStyle.contentContainer); 129 if (usingPackageToUsedClasses.isEmpty()) { 130 div.addContent(contents.getContent("doclet.ClassUse_No.usage.of.0", utils.getPackageName(packageElement))); 131 } else { 132 addPackageUse(div); 133 } 134 if (configuration.allowTag(HtmlTag.MAIN)) { 135 mainTree.addContent(div); 136 body.addContent(mainTree); 137 } else { 138 body.addContent(div); 139 } 140 HtmlTree tree = (configuration.allowTag(HtmlTag.FOOTER)) 141 ? HtmlTree.FOOTER() 142 : body; 143 addNavLinks(false, tree); 144 addBottom(tree); 145 if (configuration.allowTag(HtmlTag.FOOTER)) { 146 body.addContent(tree); 147 } 148 printHtmlDocument(null, true, body); 149 } 150 151 /** 152 * Add the package use information. 153 * 154 * @param contentTree the content tree to which the package use information will be added 155 */ 156 protected void addPackageUse(Content contentTree) { 157 HtmlTree ul = new HtmlTree(HtmlTag.UL); 158 ul.setStyle(HtmlStyle.blockList); 159 if (configuration.packages.size() > 1) { 160 addPackageList(ul); 161 } 162 addClassList(ul); 163 contentTree.addContent(ul); 164 } 165 166 /** 167 * Add the list of packages that use the given package. 168 * 169 * @param contentTree the content tree to which the package list will be added 170 */ 171 protected void addPackageList(Content contentTree) { 172 Content caption = contents.getContent( 173 "doclet.ClassUse_Packages.that.use.0", 174 getPackageLink(packageElement, utils.getPackageName(packageElement))); 175 Table table = new Table(configuration.htmlVersion, HtmlStyle.useSummary) 176 .setSummary(packageUseTableSummary) 177 .setCaption(caption) 178 .setHeader(getPackageTableHeader()) 179 .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colLast); 180 for (String pkgname: usingPackageToUsedClasses.keySet()) { 181 PackageElement pkg = utils.elementUtils.getPackageElement(pkgname); 182 Content packageLink = links.createLink(utils.getPackageName(pkg), 183 new StringContent(utils.getPackageName(pkg))); 184 Content summary = new ContentBuilder(); 185 if (pkg != null && !pkg.isUnnamed()) { 186 addSummaryComment(pkg, summary); 187 } else { 188 summary.addContent(Contents.SPACE); 189 } 190 table.addRow(packageLink, summary); 191 } 192 Content li = HtmlTree.LI(HtmlStyle.blockList, table.toContent()); 193 contentTree.addContent(li); 194 } 195 196 /** 197 * Add the list of classes that use the given package. 198 * 199 * @param contentTree the content tree to which the class list will be added 200 */ 201 protected void addClassList(Content contentTree) { 202 TableHeader classTableHeader = new TableHeader( 203 contents.classLabel, contents.descriptionLabel); 204 for (String packageName : usingPackageToUsedClasses.keySet()) { 205 PackageElement usingPackage = utils.elementUtils.getPackageElement(packageName); 206 HtmlTree li = new HtmlTree(HtmlTag.LI); 207 li.setStyle(HtmlStyle.blockList); 208 if (usingPackage != null) { 209 li.addContent(links.createAnchor(utils.getPackageName(usingPackage))); 210 } 211 String tableSummary = resources.getText("doclet.Use_Table_Summary", 212 resources.getText("doclet.classes")); 213 Content caption = contents.getContent( 214 "doclet.ClassUse_Classes.in.0.used.by.1", 215 getPackageLink(packageElement, utils.getPackageName(packageElement)), 216 getPackageLink(usingPackage, utils.getPackageName(usingPackage))); 217 Table table = new Table(configuration.htmlVersion, HtmlStyle.useSummary) 218 .setSummary(tableSummary) 219 .setCaption(caption) 220 .setHeader(classTableHeader) 221 .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colLast); 222 for (TypeElement te : usingPackageToUsedClasses.get(packageName)) { 223 DocPath dp = pathString(te, 224 DocPaths.CLASS_USE.resolve(DocPath.forName(utils, te))); 225 Content stringContent = new StringContent(utils.getSimpleName(te)); 226 Content typeContent = Links.createLink(dp.fragment(getPackageAnchorName(usingPackage)), 227 stringContent); 228 Content summary = new ContentBuilder(); 229 addIndexComment(te, summary); 230 231 table.addRow(typeContent, summary); 232 } 233 li.addContent(table.toContent()); 234 contentTree.addContent(li); 235 } 236 } 237 238 /** 239 * Get the header for the package use listing. 240 * 241 * @return a content tree representing the package use header 242 */ 243 private HtmlTree getPackageUseHeader() { 244 String packageText = resources.getText("doclet.Package"); 245 String name = packageElement.isUnnamed() ? "" : utils.getPackageName(packageElement); 246 String title = resources.getText("doclet.Window_ClassUse_Header", packageText, name); 247 HtmlTree bodyTree = getBody(true, getWindowTitle(title)); 248 HtmlTree htmlTree = (configuration.allowTag(HtmlTag.HEADER)) 249 ? HtmlTree.HEADER() 250 : bodyTree; 251 addTop(htmlTree); 252 addNavLinks(true, htmlTree); 253 if (configuration.allowTag(HtmlTag.HEADER)) { 254 bodyTree.addContent(htmlTree); 255 } 256 ContentBuilder headContent = new ContentBuilder(); 257 headContent.addContent(contents.getContent("doclet.ClassUse_Title", packageText)); 258 headContent.addContent(new HtmlTree(HtmlTag.BR)); 259 headContent.addContent(name); 260 Content heading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, true, 261 HtmlStyle.title, headContent); 262 Content div = HtmlTree.DIV(HtmlStyle.header, heading); 263 if (configuration.allowTag(HtmlTag.MAIN)) { 264 mainTree.addContent(div); 265 } else { 266 bodyTree.addContent(div); 267 } 268 return bodyTree; 269 } 270 271 /** 272 * Get the module link. 273 * 274 * @return a content tree for the module link 275 */ 276 @Override 277 protected Content getNavLinkModule() { 278 Content linkContent = getModuleLink(utils.elementUtils.getModuleOf(packageElement), 279 contents.moduleLabel); 280 Content li = HtmlTree.LI(linkContent); 281 return li; 282 } 283 284 /** 285 * Get this package link. 286 * 287 * @return a content tree for the package link 288 */ 289 @Override 290 protected Content getNavLinkPackage() { 291 Content linkContent = Links.createLink(DocPaths.PACKAGE_SUMMARY, 292 contents.packageLabel); 293 Content li = HtmlTree.LI(linkContent); 294 return li; 295 } 296 297 /** 298 * Get the use link. 299 * 300 * @return a content tree for the use link 301 */ 302 @Override 303 protected Content getNavLinkClassUse() { 304 Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, contents.useLabel); 305 return li; 306 } 307 308 /** 309 * Get the tree link. 310 * 311 * @return a content tree for the tree link 312 */ 313 @Override 314 protected Content getNavLinkTree() { 315 Content linkContent = Links.createLink(DocPaths.PACKAGE_TREE, 316 contents.treeLabel); 317 Content li = HtmlTree.LI(linkContent); 318 return li; 319 } 320 }