1 /* 2 * Copyright (c) 1998, 2015, 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 com.sun.tools.doclets.formats.html; 27 28 import java.io.*; 29 import java.util.*; 30 31 import com.sun.javadoc.*; 32 import com.sun.tools.doclets.formats.html.markup.*; 33 import com.sun.tools.doclets.internal.toolkit.*; 34 import com.sun.tools.doclets.internal.toolkit.util.*; 35 36 /** 37 * Generate package usage information. 38 * 39 * <p><b>This is NOT part of any supported API. 40 * If you write code that depends on this, you do so at your own risk. 41 * This code and its internal interfaces are subject to change or 42 * deletion without notice.</b> 43 * 44 * @author Robert G. Field 45 * @author Bhavesh Patel (Modified) 46 */ 47 public class PackageUseWriter extends SubWriterHolderWriter { 48 49 final PackageDoc pkgdoc; 50 final SortedMap<String,Set<ClassDoc>> usingPackageToUsedClasses = new TreeMap<>(); 51 protected HtmlTree mainTree = HtmlTree.MAIN(); 52 53 /** 54 * Constructor. 55 * 56 * @param filename the file to be generated. 57 * @throws IOException 58 * @throws DocletAbortException 59 */ 60 public PackageUseWriter(ConfigurationImpl configuration, 61 ClassUseMapper mapper, DocPath filename, 62 PackageDoc pkgdoc) throws IOException { 63 super(configuration, DocPath.forPackage(pkgdoc).resolve(filename)); 64 this.pkgdoc = pkgdoc; 65 66 // by examining all classes in this package, find what packages 67 // use these classes - produce a map between using package and 68 // used classes. 69 for (ClassDoc usedClass : pkgdoc.allClasses()) { 70 Set<ClassDoc> usingClasses = mapper.classToClass.get(usedClass.qualifiedName()); 71 if (usingClasses != null) { 72 for (ClassDoc usingClass : usingClasses) { 73 PackageDoc usingPackage = usingClass.containingPackage(); 74 Set<ClassDoc> usedClasses = usingPackageToUsedClasses 75 .get(usingPackage.name()); 76 if (usedClasses == null) { 77 usedClasses = new TreeSet<>(); 78 usingPackageToUsedClasses.put(utils.getPackageName(usingPackage), 79 usedClasses); 80 } 81 usedClasses.add(usedClass); 82 } 83 } 84 } 85 } 86 87 /** 88 * Generate a class page. 89 * 90 * @param configuration the current configuration of the doclet. 91 * @param mapper the mapping of the class usage. 92 * @param pkgdoc the package doc being documented. 93 */ 94 public static void generate(ConfigurationImpl configuration, 95 ClassUseMapper mapper, PackageDoc pkgdoc) { 96 PackageUseWriter pkgusegen; 97 DocPath filename = DocPaths.PACKAGE_USE; 98 try { 99 pkgusegen = new PackageUseWriter(configuration, 100 mapper, filename, pkgdoc); 101 pkgusegen.generatePackageUseFile(); 102 pkgusegen.close(); 103 } catch (IOException exc) { 104 configuration.standardmessage.error( 105 "doclet.exception_encountered", 106 exc.toString(), filename); 107 throw new DocletAbortException(exc); 108 } 109 } 110 111 112 /** 113 * Generate the package use list. 114 */ 115 protected void generatePackageUseFile() throws IOException { 116 HtmlTree body = getPackageUseHeader(); 117 HtmlTree div = new HtmlTree(HtmlTag.DIV); 118 div.addStyle(HtmlStyle.contentContainer); 119 if (usingPackageToUsedClasses.isEmpty()) { 120 div.addContent(getResource( 121 "doclet.ClassUse_No.usage.of.0", pkgdoc.name())); 122 } else { 123 addPackageUse(div); 124 } 125 if (configuration.allowTag(HtmlTag.MAIN)) { 126 mainTree.addContent(div); 127 body.addContent(mainTree); 128 } else { 129 body.addContent(div); 130 } 131 HtmlTree tree = (configuration.allowTag(HtmlTag.FOOTER)) 132 ? HtmlTree.FOOTER() 133 : body; 134 addNavLinks(false, tree); 135 addBottom(tree); 136 if (configuration.allowTag(HtmlTag.FOOTER)) { 137 body.addContent(tree); 138 } 139 printHtmlDocument(null, true, body); 140 } 141 142 /** 143 * Add the package use information. 144 * 145 * @param contentTree the content tree to which the package use information will be added 146 */ 147 protected void addPackageUse(Content contentTree) throws IOException { 148 HtmlTree ul = new HtmlTree(HtmlTag.UL); 149 ul.addStyle(HtmlStyle.blockList); 150 if (configuration.packages.size() > 1) { 151 addPackageList(ul); 152 } 153 addClassList(ul); 154 contentTree.addContent(ul); 155 } 156 157 /** 158 * Add the list of packages that use the given package. 159 * 160 * @param contentTree the content tree to which the package list will be added 161 */ 162 protected void addPackageList(Content contentTree) throws IOException { 163 Content caption = getTableCaption(configuration.getResource( 164 "doclet.ClassUse_Packages.that.use.0", 165 getPackageLink(pkgdoc, utils.getPackageName(pkgdoc)))); 166 Content table = (configuration.isOutputHtml5()) 167 ? HtmlTree.TABLE(HtmlStyle.useSummary, caption) 168 : HtmlTree.TABLE(HtmlStyle.useSummary, useTableSummary, caption); 169 table.addContent(getSummaryTableHeader(packageTableHeader, "col")); 170 Content tbody = new HtmlTree(HtmlTag.TBODY); 171 Iterator<String> it = usingPackageToUsedClasses.keySet().iterator(); 172 for (int i = 0; it.hasNext(); i++) { 173 PackageDoc pkg = configuration.root.packageNamed(it.next()); 174 HtmlTree tr = new HtmlTree(HtmlTag.TR); 175 if (i % 2 == 0) { 176 tr.addStyle(HtmlStyle.altColor); 177 } else { 178 tr.addStyle(HtmlStyle.rowColor); 179 } 180 addPackageUse(pkg, tr); 181 tbody.addContent(tr); 182 } 183 table.addContent(tbody); 184 Content li = HtmlTree.LI(HtmlStyle.blockList, table); 185 contentTree.addContent(li); 186 } 187 188 /** 189 * Add the list of classes that use the given package. 190 * 191 * @param contentTree the content tree to which the class list will be added 192 */ 193 protected void addClassList(Content contentTree) throws IOException { 194 String[] classTableHeader = new String[] { 195 configuration.getText("doclet.0_and_1", 196 configuration.getText("doclet.Class"), 197 configuration.getText("doclet.Description")) 198 }; 199 for (String packageName : usingPackageToUsedClasses.keySet()) { 200 PackageDoc usingPackage = configuration.root.packageNamed(packageName); 201 HtmlTree li = new HtmlTree(HtmlTag.LI); 202 li.addStyle(HtmlStyle.blockList); 203 if (usingPackage != null) { 204 li.addContent(getMarkerAnchor(usingPackage.name())); 205 } 206 String tableSummary = configuration.getText("doclet.Use_Table_Summary", 207 configuration.getText("doclet.classes")); 208 Content caption = getTableCaption(configuration.getResource( 209 "doclet.ClassUse_Classes.in.0.used.by.1", 210 getPackageLink(pkgdoc, utils.getPackageName(pkgdoc)), 211 getPackageLink(usingPackage, utils.getPackageName(usingPackage)))); 212 Content table = (configuration.isOutputHtml5()) 213 ? HtmlTree.TABLE(HtmlStyle.useSummary, caption) 214 : HtmlTree.TABLE(HtmlStyle.useSummary, tableSummary, caption); 215 table.addContent(getSummaryTableHeader(classTableHeader, "col")); 216 Content tbody = new HtmlTree(HtmlTag.TBODY); 217 Iterator<ClassDoc> itc = 218 usingPackageToUsedClasses.get(packageName).iterator(); 219 for (int i = 0; itc.hasNext(); i++) { 220 HtmlTree tr = new HtmlTree(HtmlTag.TR); 221 if (i % 2 == 0) { 222 tr.addStyle(HtmlStyle.altColor); 223 } else { 224 tr.addStyle(HtmlStyle.rowColor); 225 } 226 addClassRow(itc.next(), usingPackage, tr); 227 tbody.addContent(tr); 228 } 229 table.addContent(tbody); 230 li.addContent(table); 231 contentTree.addContent(li); 232 } 233 } 234 235 /** 236 * Add a row for the class that uses the given package. 237 * 238 * @param usedClass the class that uses the given package 239 * @param pkg the package to which the class belongs 240 * @param contentTree the content tree to which the row will be added 241 */ 242 protected void addClassRow(ClassDoc usedClass, PackageDoc pkg, 243 Content contentTree) { 244 DocPath dp = pathString(usedClass, 245 DocPaths.CLASS_USE.resolve(DocPath.forName(usedClass))); 246 Content td = HtmlTree.TD(HtmlStyle.colOne, 247 getHyperLink(dp.fragment(getPackageAnchorName(pkg)), new StringContent(usedClass.name()))); 248 addIndexComment(usedClass, td); 249 contentTree.addContent(td); 250 } 251 252 /** 253 * Add the package use information. 254 * 255 * @param pkg the package that used the given package 256 * @param contentTree the content tree to which the information will be added 257 */ 258 protected void addPackageUse(PackageDoc pkg, Content contentTree) throws IOException { 259 Content tdFirst = HtmlTree.TD(HtmlStyle.colFirst, 260 getHyperLink(utils.getPackageName(pkg), 261 new StringContent(utils.getPackageName(pkg)))); 262 contentTree.addContent(tdFirst); 263 HtmlTree tdLast = new HtmlTree(HtmlTag.TD); 264 tdLast.addStyle(HtmlStyle.colLast); 265 if (pkg != null && pkg.name().length() != 0) { 266 addSummaryComment(pkg, tdLast); 267 } else { 268 tdLast.addContent(getSpace()); 269 } 270 contentTree.addContent(tdLast); 271 } 272 273 /** 274 * Get the header for the package use listing. 275 * 276 * @return a content tree representing the package use header 277 */ 278 protected HtmlTree getPackageUseHeader() { 279 String packageText = configuration.getText("doclet.Package"); 280 String name = pkgdoc.name(); 281 String title = configuration.getText("doclet.Window_ClassUse_Header", 282 packageText, name); 283 HtmlTree bodyTree = getBody(true, getWindowTitle(title)); 284 HtmlTree htmlTree = (configuration.allowTag(HtmlTag.HEADER)) 285 ? HtmlTree.HEADER() 286 : bodyTree; 287 addTop(htmlTree); 288 addNavLinks(true, htmlTree); 289 if (configuration.allowTag(HtmlTag.HEADER)) { 290 bodyTree.addContent(htmlTree); 291 } 292 ContentBuilder headContent = new ContentBuilder(); 293 headContent.addContent(getResource("doclet.ClassUse_Title", packageText)); 294 headContent.addContent(new HtmlTree(HtmlTag.BR)); 295 headContent.addContent(name); 296 Content heading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, true, 297 HtmlStyle.title, headContent); 298 Content div = HtmlTree.DIV(HtmlStyle.header, heading); 299 if (configuration.allowTag(HtmlTag.MAIN)) { 300 mainTree.addContent(div); 301 } else { 302 bodyTree.addContent(div); 303 } 304 return bodyTree; 305 } 306 307 /** 308 * Get this package link. 309 * 310 * @return a content tree for the package link 311 */ 312 protected Content getNavLinkPackage() { 313 Content linkContent = getHyperLink(DocPaths.PACKAGE_SUMMARY, 314 packageLabel); 315 Content li = HtmlTree.LI(linkContent); 316 return li; 317 } 318 319 /** 320 * Get the use link. 321 * 322 * @return a content tree for the use link 323 */ 324 protected Content getNavLinkClassUse() { 325 Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, useLabel); 326 return li; 327 } 328 329 /** 330 * Get the tree link. 331 * 332 * @return a content tree for the tree link 333 */ 334 protected Content getNavLinkTree() { 335 Content linkContent = getHyperLink(DocPaths.PACKAGE_TREE, 336 treeLabel); 337 Content li = HtmlTree.LI(linkContent); 338 return li; 339 } 340 }