ModuleWriterImpl.java revision 3831:209b0eab0e1f
194742Sobrien/* 294742Sobrien * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. 394742Sobrien * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 495253Sru * 594742Sobrien * This code is free software; you can redistribute it and/or modify it 696991Srwatson * under the terms of the GNU General Public License version 2 only, as 796991Srwatson * published by the Free Software Foundation. Oracle designates this 896991Srwatson * particular file as subject to the "Classpath" exception as provided 9102773Srwatson * by Oracle in the LICENSE file that accompanied this code. 10102773Srwatson * 1194854Ssos * This code is distributed in the hope that it will be useful, but WITHOUT 1294917Simp * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13126445Sobrien * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1494917Simp * version 2 for more details (a copy is included in the LICENSE file that 1594917Simp * accompanied this code). 1694917Simp * 17117751Smarkm * You should have received a copy of the GNU General Public License version 18117751Smarkm * 2 along with this work; if not, write to the Free Software Foundation, 19116149Smarkm * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20116149Smarkm * 21125244Snectar * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22125244Snectar * or visit www.oracle.com if you need additional information or have any 2394847Sjhb * questions. 2494847Sjhb */ 2594847Sjhb 26126337Svkashyappackage jdk.javadoc.internal.doclets.formats.html; 27128023Svkashyap 2894855Sscottlimport java.util.EnumSet; 29126054Sscottlimport java.util.LinkedHashMap; 30126054Sscottlimport java.util.List; 31126054Sscottlimport java.util.Map; 32126054Sscottlimport java.util.Set; 33126054Sscottlimport java.util.SortedSet; 34126054Sscottlimport java.util.TreeMap; 3594915Skenimport java.util.TreeSet; 3699607Smjacob 3794915Skenimport javax.lang.model.element.Element; 3894915Skenimport javax.lang.model.element.ModuleElement; 3994915Skenimport javax.lang.model.element.PackageElement; 4094915Skenimport javax.lang.model.element.TypeElement; 4194915Skenimport javax.lang.model.util.ElementFilter; 4294915Sken 4394915Skenimport com.sun.source.doctree.DocTree; 4494915Skenimport jdk.javadoc.doclet.DocletEnvironment.ModuleMode; 4599607Smjacobimport jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr; 46106734Smjacobimport jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants; 47128435Stackermanimport jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; 4897611Sbillfimport jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; 4994918Sgshapiroimport jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; 5094918Sgshapiroimport jdk.javadoc.internal.doclets.formats.html.markup.RawHtml; 5194918Sgshapiroimport jdk.javadoc.internal.doclets.formats.html.markup.StringContent; 5294918Sgshapiroimport jdk.javadoc.internal.doclets.toolkit.Content; 5394918Sgshapiroimport jdk.javadoc.internal.doclets.toolkit.ModuleSummaryWriter; 54118316Smbrimport jdk.javadoc.internal.doclets.toolkit.util.CommentHelper; 5594955Smurrayimport jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException; 5695054Snectarimport jdk.javadoc.internal.doclets.toolkit.util.DocPaths; 57125080Scpercivaimport jdk.javadoc.internal.doclets.toolkit.util.ModulePackageTypes; 58106187Sdes 59106187Sdes/** 6095455Sdes * Class to generate file for each module contents in the right-hand frame. This will list all the 6198750Sdes * required modules, packages and service types for the module. A click on any of the links will update 6299606Sdes * the frame with the clicked element page. 6399606Sdes * 6499606Sdes * <p><b>This is NOT part of any supported API. 6596268Sgad * If you write code that depends on this, you do so at your own risk. 6696268Sgad * This code and its internal interfaces are subject to change or 67116233Sgad * deletion without notice.</b> 68139390Sgad * 69139390Sgad * @author Bhavesh Patel 70139390Sgad */ 7196332Speterpublic class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryWriter { 7296332Speter 7396332Speter /** 7496332Speter * The prev module name in the alpha-order list. 7596332Speter */ 76100314Sru protected ModuleElement prevModule; 7796451Sru 7897611Sbillf /** 7998333Sanholt * The next module name in the alpha-order list. 8098986Sjmallett */ 81111061Sjmallett protected ModuleElement nextModule; 8299732Sjoerg 8399732Sjoerg /** 84113692Snectar * The module being documented. 85113692Snectar */ 86115825Sfanf protected ModuleElement mdle; 87126445Sobrien 88117645Sdwmalone /** 89118204Sbp * The module mode for this javadoc run. It can be set to "api" or "all". 90118204Sbp */ 91118204Sbp private final ModuleMode moduleMode; 92118204Sbp 93127337Smlaier /** 94126445Sobrien * Map of module elements and modifiers required by this module. 95133182Spjd */ 96133182Spjd private final Map<ModuleElement, Content> requires 97133182Spjd = new TreeMap<>(utils.makeModuleComparator()); 98133182Spjd 99133182Spjd /** 100133841Spjd * Map of additional modules and modifiers, transitive closure, required by this module. 101133182Spjd */ 102133182Spjd private final Map<ModuleElement, Content> additionalModules 103132311Salfred = new TreeMap<>(utils.makeModuleComparator()); 104132311Salfred 105132311Salfred /** 106132268Salfred * Map of packages exported by this module and the modules it's been exported to. 107138235Seik */ 108115822Sdougb private final Map<PackageElement, SortedSet<ModuleElement>> exportedPackages 109115822Sdougb = new TreeMap<>(utils.makePackageComparator()); 110115822Sdougb 111115822Sdougb /** 112115822Sdougb * Map of opened packages by this module and the modules it's been opened to. 113115822Sdougb */ 114115822Sdougb private final Map<PackageElement, SortedSet<ModuleElement>> openedPackages 115115822Sdougb = new TreeMap<>(utils.makePackageComparator()); 116115822Sdougb 117115822Sdougb /** 118115822Sdougb * Set of concealed packages of this module. 119115822Sdougb */ 120115822Sdougb private final SortedSet<PackageElement> concealedPackages = new TreeSet<>(utils.makePackageComparator()); 121115822Sdougb 122115822Sdougb /** 123115822Sdougb * Map of additional modules (transitive closure) and its exported packages. 124115822Sdougb */ 125115822Sdougb private final Map<ModuleElement, SortedSet<PackageElement>> additionalPackages 126115822Sdougb = new TreeMap<>(utils.makeModuleComparator()); 127115822Sdougb 128115822Sdougb /** 129115822Sdougb * Map of additional modules (transitive closure) and its open packages. 130115895Sguido */ 131115822Sdougb private final Map<ModuleElement, SortedSet<PackageElement>> additionalOpenPackages 132115895Sguido = new TreeMap<>(utils.makeModuleComparator()); 133115895Sguido 134115895Sguido /** 135115822Sdougb * Set of services used by the module. 136115822Sdougb */ 137115822Sdougb private final SortedSet<TypeElement> uses 138115822Sdougb = new TreeSet<>(utils.makeAllClassesComparator()); 139115822Sdougb 140115822Sdougb /** 141115822Sdougb * Map of services used by the module and specified using @uses javadoc tag, and description. 142115822Sdougb */ 143115822Sdougb private final Map<TypeElement, Content> usesTrees 144115822Sdougb = new TreeMap<>(utils.makeAllClassesComparator()); 145115822Sdougb 146115822Sdougb /** 147115822Sdougb * Map of services provided by this module, and set of its implementations. 148115822Sdougb */ 149115822Sdougb private final Map<TypeElement, SortedSet<TypeElement>> provides 150115822Sdougb = new TreeMap<>(utils.makeAllClassesComparator()); 151115822Sdougb 152115822Sdougb /** 153115822Sdougb * Map of services provided by the module and specified using @provides javadoc tag, and 154115822Sdougb * description. 155115822Sdougb */ 156115822Sdougb private final Map<TypeElement, Content> providesTrees 157115822Sdougb = new TreeMap<>(utils.makeAllClassesComparator()); 158115822Sdougb 159115822Sdougb private int packageTypesOr = 0; 160115822Sdougb 161115822Sdougb protected Set<ModulePackageTypes> modulePackageTypes = EnumSet.noneOf(ModulePackageTypes.class); 162115822Sdougb 163115822Sdougb protected Map<String, Integer> typeMap = new LinkedHashMap<>(); 164115822Sdougb 165115895Sguido /** 166115895Sguido * The HTML tree for main tag. 167115895Sguido */ 168115895Sguido protected HtmlTree mainTree = HtmlTree.MAIN(); 169115822Sdougb 170115822Sdougb /** 171115822Sdougb * The HTML tree for section tag. 172115822Sdougb */ 173 protected HtmlTree sectionTree = HtmlTree.SECTION(); 174 175 /** 176 * Constructor to construct ModuleWriter object and to generate "moduleName-summary.html" file. 177 * 178 * @param configuration the configuration of the doclet. 179 * @param mdle Module under consideration. 180 * @param prevModule Previous module in the sorted array. 181 * @param nextModule Next module in the sorted array. 182 */ 183 public ModuleWriterImpl(ConfigurationImpl configuration, 184 ModuleElement mdle, ModuleElement prevModule, ModuleElement nextModule) { 185 super(configuration, DocPaths.moduleSummary(mdle)); 186 this.prevModule = prevModule; 187 this.nextModule = nextModule; 188 this.mdle = mdle; 189 this.moduleMode = configuration.docEnv.getModuleMode(); 190 computeModulesData(); 191 } 192 193 /** 194 * Get the module header. 195 * 196 * @param heading the heading for the section 197 */ 198 @Override 199 public Content getModuleHeader(String heading) { 200 HtmlTree bodyTree = getBody(true, getWindowTitle(mdle.getQualifiedName().toString())); 201 HtmlTree htmlTree = (configuration.allowTag(HtmlTag.HEADER)) 202 ? HtmlTree.HEADER() 203 : bodyTree; 204 addTop(htmlTree); 205 addNavLinks(true, htmlTree); 206 if (configuration.allowTag(HtmlTag.HEADER)) { 207 bodyTree.addContent(htmlTree); 208 } 209 HtmlTree div = new HtmlTree(HtmlTag.DIV); 210 div.addStyle(HtmlStyle.header); 211 Content annotationContent = new HtmlTree(HtmlTag.P); 212 addAnnotationInfo(mdle, annotationContent); 213 div.addContent(annotationContent); 214 Content tHeading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, true, 215 HtmlStyle.title, contents.moduleLabel); 216 tHeading.addContent(Contents.SPACE); 217 Content moduleHead = new RawHtml(heading); 218 tHeading.addContent(moduleHead); 219 div.addContent(tHeading); 220 if (configuration.allowTag(HtmlTag.MAIN)) { 221 mainTree.addContent(div); 222 } else { 223 bodyTree.addContent(div); 224 } 225 return bodyTree; 226 } 227 228 /** 229 * Get the content header. 230 */ 231 @Override 232 public Content getContentHeader() { 233 HtmlTree div = new HtmlTree(HtmlTag.DIV); 234 div.addStyle(HtmlStyle.contentContainer); 235 return div; 236 } 237 238 /** 239 * Get the summary section header. 240 */ 241 @Override 242 public Content getSummaryHeader() { 243 HtmlTree li = new HtmlTree(HtmlTag.LI); 244 li.addStyle(HtmlStyle.blockList); 245 return li; 246 } 247 248 /** 249 * Get the summary tree. 250 * 251 * @param summaryContentTree the content tree to be added to the summary tree. 252 */ 253 @Override 254 public Content getSummaryTree(Content summaryContentTree) { 255 HtmlTree ul = HtmlTree.UL(HtmlStyle.blockList, summaryContentTree); 256 return ul; 257 } 258 259 /** 260 * Compute the modules data that will be displayed in various tables on the module summary page. 261 */ 262 public void computeModulesData() { 263 CommentHelper ch = utils.getCommentHelper(mdle); 264 // Get module dependencies using the module's transitive closure. 265 Map<ModuleElement, String> dependentModules = utils.getDependentModules(mdle); 266 // Add all dependent modules to additional modules set. We will remove the modules, 267 // listed using the requires directive, from this set to come up with the table of additional 268 // required modules. 269 dependentModules.forEach((module, mod) -> { 270 if (shouldDocument(module)) { 271 additionalModules.put(module, new StringContent(mod)); 272 } 273 }); 274 (ElementFilter.requiresIn(mdle.getDirectives())).forEach((directive) -> { 275 ModuleElement m = directive.getDependency(); 276 if (shouldDocument(m)) { 277 if (moduleMode == ModuleMode.ALL || directive.isTransitive()) { 278 requires.put(m, new StringContent(utils.getModifiers(directive))); 279 } else { 280 // For api mode, just keep the public requires in dependentModules for display of 281 // additional packages in the "Packages" section. 282 dependentModules.remove(m); 283 } 284 additionalModules.remove(m); 285 } 286 }); 287 // Get all packages for the module and put it in the concealed packages set. 288 (utils.getModulePackageMap().get(mdle)).forEach((pkg) -> { 289 if (shouldDocument(pkg)) { 290 concealedPackages.add(pkg); 291 } 292 }); 293 // Get all exported packages for the module using the exports directive for the module. 294 (ElementFilter.exportsIn(mdle.getDirectives())).forEach((directive) -> { 295 PackageElement p = directive.getPackage(); 296 if (shouldDocument(p)) { 297 SortedSet<ModuleElement> mdleList = new TreeSet<>(utils.makeModuleComparator()); 298 List<? extends ModuleElement> targetMdles = directive.getTargetModules(); 299 if (targetMdles != null) { 300 mdleList.addAll(targetMdles); 301 } 302 // Qualified exports should not be displayed in the api mode. So if mdleList is empty, 303 // its exported to all modules and hence can be added. 304 if (moduleMode == ModuleMode.ALL || mdleList.isEmpty()) { 305 exportedPackages.put(p, mdleList); 306 } 307 concealedPackages.remove(p); 308 } 309 }); 310 // Get all opened packages for the module using the opens directive for the module. 311 (ElementFilter.opensIn(mdle.getDirectives())).forEach((directive) -> { 312 PackageElement p = directive.getPackage(); 313 if (shouldDocument(p)) { 314 SortedSet<ModuleElement> mdleList = new TreeSet<>(utils.makeModuleComparator()); 315 List<? extends ModuleElement> targetMdles = directive.getTargetModules(); 316 if (targetMdles != null) { 317 mdleList.addAll(targetMdles); 318 } 319 // Qualified opens should not be displayed in the api mode. So if mdleList is empty, 320 // it's opened to all modules and hence can be added. 321 if (moduleMode == ModuleMode.ALL || mdleList.isEmpty()) { 322 openedPackages.put(p, mdleList); 323 } 324 concealedPackages.remove(p); 325 } 326 }); 327 // Remove all the exported and opened packages so we have just the concealed packages now. 328 concealedPackages.removeAll(exportedPackages.keySet()); 329 concealedPackages.removeAll(openedPackages.keySet()); 330 // Get all the exported and opened packages, for the transitive closure of the module, to be displayed in 331 // the additional packages tables. 332 dependentModules.forEach((module, mod) -> { 333 SortedSet<PackageElement> pkgList = new TreeSet<>(utils.makePackageComparator()); 334 (ElementFilter.exportsIn(module.getDirectives())).forEach((directive) -> { 335 PackageElement pkg = directive.getPackage(); 336 if (shouldDocument(pkg)) { 337 pkgList.add(pkg); 338 } 339 }); 340 // If none of the transitive modules have exported packages to be displayed, we should not be 341 // displaying the table and so it should not be added to the map. 342 if (!pkgList.isEmpty()) { 343 additionalPackages.put(module, pkgList); 344 } 345 SortedSet<PackageElement> openPkgList = new TreeSet<>(utils.makePackageComparator()); 346 (ElementFilter.opensIn(module.getDirectives())).forEach((directive) -> { 347 PackageElement pkg = directive.getPackage(); 348 if (shouldDocument(pkg)) { 349 openPkgList.add(pkg); 350 } 351 }); 352 // If none of the transitive modules have opened packages to be displayed, we should not be 353 // displaying the table and so it should not be added to the map. 354 if (!openPkgList.isEmpty()) { 355 additionalOpenPackages.put(module, openPkgList); 356 } 357 }); 358 // Get all the services listed as uses directive. 359 (ElementFilter.usesIn(mdle.getDirectives())).forEach((directive) -> { 360 TypeElement u = directive.getService(); 361 if (shouldDocument(u)) { 362 uses.add(u); 363 } 364 }); 365 // Get all the services and implementations listed as provides directive. 366 (ElementFilter.providesIn(mdle.getDirectives())).forEach((directive) -> { 367 TypeElement u = directive.getService(); 368 if (shouldDocument(u)) { 369 List<? extends TypeElement> implList = directive.getImplementations(); 370 SortedSet<TypeElement> implSet = new TreeSet<>(utils.makeAllClassesComparator()); 371 implSet.addAll(implList); 372 provides.put(u, implSet); 373 } 374 }); 375 // Generate the map of all services listed using @provides, and the description. 376 (utils.getBlockTags(mdle, DocTree.Kind.PROVIDES)).forEach((tree) -> { 377 TypeElement t = ch.getServiceType(configuration, tree); 378 if (t != null) { 379 providesTrees.put(t, commentTagsToContent(tree, mdle, ch.getDescription(configuration, tree), false)); 380 } 381 }); 382 // Generate the map of all services listed using @uses, and the description. 383 (utils.getBlockTags(mdle, DocTree.Kind.USES)).forEach((tree) -> { 384 TypeElement t = ch.getServiceType(configuration, tree); 385 if (t != null) { 386 usesTrees.put(t, commentTagsToContent(tree, mdle, ch.getDescription(configuration, tree), false)); 387 } 388 }); 389 } 390 391 /** 392 * Returns true if the element should be documented on the module summary page. 393 * 394 * @param element the element to be checked 395 * @return true if the element should be documented 396 */ 397 public boolean shouldDocument(Element element) { 398 return (moduleMode == ModuleMode.ALL || utils.isIncluded(element)); 399 } 400 401 /** 402 * Returns true if there are elements to be displayed. 403 * 404 * @param section set of elements 405 * @return true if there are elements to be displayed 406 */ 407 public boolean display(SortedSet<? extends Element> section) { 408 return section != null && !section.isEmpty(); 409 } 410 411 /** 412 * Returns true if there are elements to be displayed. 413 * 414 * @param section map of elements. 415 * @return true if there are elements to be displayed 416 */ 417 public boolean display(Map<? extends Element, ?> section) { 418 return section != null && !section.isEmpty(); 419 } 420 421 /** 422 * Add the summary header. 423 * 424 * @param startMarker the marker comment 425 * @param markerAnchor the marker anchor for the section 426 * @param heading the heading for the section 427 * @param htmltree the content tree to which the information is added 428 */ 429 public void addSummaryHeader(Content startMarker, SectionName markerAnchor, Content heading, Content htmltree) { 430 htmltree.addContent(startMarker); 431 htmltree.addContent(getMarkerAnchor(markerAnchor)); 432 htmltree.addContent(HtmlTree.HEADING(HtmlTag.H3, heading)); 433 } 434 435 /** 436 * Get table header. 437 * 438 * @param text the table caption 439 * @param tableSummary the summary for the table 440 * @param tableStyle the table style 441 * @param tableHeader the table header 442 * @return a content object 443 */ 444 public Content getTableHeader(String text, String tableSummary, HtmlStyle tableStyle, 445 List<String> tableHeader) { 446 return getTableHeader(getTableCaption(new RawHtml(text)), tableSummary, tableStyle, tableHeader); 447 } 448 449 /** 450 * Get table header. 451 * 452 * @param caption the table caption 453 * @param tableSummary the summary for the table 454 * @param tableStyle the table style 455 * @param tableHeader the table header 456 * @return a content object 457 */ 458 public Content getTableHeader(Content caption, String tableSummary, HtmlStyle tableStyle, 459 List<String> tableHeader) { 460 Content table = (configuration.isOutputHtml5()) 461 ? HtmlTree.TABLE(tableStyle, caption) 462 : HtmlTree.TABLE(tableStyle, tableSummary, caption); 463 table.addContent(getSummaryTableHeader(tableHeader, "col")); 464 return table; 465 } 466 467 /** 468 * {@inheritDoc} 469 */ 470 public void addModulesSummary(Content summaryContentTree) { 471 if (display(requires) || display(additionalModules)) { 472 HtmlTree li = new HtmlTree(HtmlTag.LI); 473 li.addStyle(HtmlStyle.blockList); 474 addSummaryHeader(HtmlConstants.START_OF_MODULES_SUMMARY, SectionName.MODULES, 475 contents.navModules, li); 476 if (display(requires)) { 477 String text = configuration.getText("doclet.Requires_Summary"); 478 String tableSummary = configuration.getText("doclet.Member_Table_Summary", 479 configuration.getText("doclet.Requires_Summary"), 480 configuration.getText("doclet.modules")); 481 Content table = getTableHeader(text, tableSummary, HtmlStyle.requiresSummary, requiresTableHeader); 482 Content tbody = new HtmlTree(HtmlTag.TBODY); 483 addModulesList(requires, tbody); 484 table.addContent(tbody); 485 li.addContent(table); 486 } 487 // Display additional modules table in both "api" and "all" mode. 488 if (display(additionalModules)) { 489 String amrText = configuration.getText("doclet.Additional_Modules_Required_Summary"); 490 String amrTableSummary = configuration.getText("doclet.Member_Table_Summary", 491 configuration.getText("doclet.Additional_Modules_Required_Summary"), 492 configuration.getText("doclet.modules")); 493 Content amrTable = getTableHeader(amrText, amrTableSummary, HtmlStyle.requiresSummary, requiresTableHeader); 494 Content amrTbody = new HtmlTree(HtmlTag.TBODY); 495 addModulesList(additionalModules, amrTbody); 496 amrTable.addContent(amrTbody); 497 li.addContent(amrTable); 498 } 499 HtmlTree ul = HtmlTree.UL(HtmlStyle.blockList, li); 500 summaryContentTree.addContent(ul); 501 } 502 } 503 504 /** 505 * Add the list of modules. 506 * 507 * @param mdleMap map of modules and modifiers 508 * @param tbody the content tree to which the list will be added 509 */ 510 public void addModulesList(Map<ModuleElement, Content> mdleMap, Content tbody) { 511 boolean altColor = true; 512 for (ModuleElement m : mdleMap.keySet()) { 513 Content tdModifiers = HtmlTree.TD(HtmlStyle.colFirst, mdleMap.get(m)); 514 Content moduleLinkContent = getModuleLink(m, new StringContent(m.getQualifiedName())); 515 Content thModule = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colSecond, moduleLinkContent); 516 HtmlTree tdSummary = new HtmlTree(HtmlTag.TD); 517 tdSummary.addStyle(HtmlStyle.colLast); 518 addSummaryComment(m, tdSummary); 519 HtmlTree tr = HtmlTree.TR(tdModifiers); 520 tr.addContent(thModule); 521 tr.addContent(tdSummary); 522 tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor); 523 tbody.addContent(tr); 524 altColor = !altColor; 525 } 526 } 527 528 public void addPackagesSummary(Content summaryContentTree) { 529 if (display(exportedPackages) || display(openedPackages) || display(concealedPackages) 530 || display(additionalPackages) || display(additionalOpenPackages)) { 531 HtmlTree li = new HtmlTree(HtmlTag.LI); 532 li.addStyle(HtmlStyle.blockList); 533 addSummaryHeader(HtmlConstants.START_OF_PACKAGES_SUMMARY, SectionName.PACKAGES, 534 contents.navPackages, li); 535 String tableSummary = configuration.getText("doclet.Member_Table_Summary", 536 configuration.getText("doclet.Packages_Summary"), 537 configuration.getText("doclet.packages")); 538 if (display(exportedPackages) || display(openedPackages) || display(concealedPackages)) { 539 addPackageSummary(tableSummary, li); 540 } 541 if (display(additionalPackages)) { 542 String aepText = configuration.getText("doclet.Additional_Exported_Packages_Summary"); 543 String aepTableSummary = configuration.getText("doclet.Additional_Packages_Table_Summary", 544 configuration.getText("doclet.Additional_Exported_Packages_Summary"), 545 configuration.getText("doclet.modules"), 546 configuration.getText("doclet.packages")); 547 Content aepTable = getTableHeader(aepText, aepTableSummary, HtmlStyle.packagesSummary, 548 additionalPackagesTableHeader); 549 Content aepTbody = new HtmlTree(HtmlTag.TBODY); 550 addAdditionalPackages(aepTbody, additionalPackages); 551 aepTable.addContent(aepTbody); 552 li.addContent(aepTable); 553 } 554 if (display(additionalOpenPackages)) { 555 String aopText = configuration.getText("doclet.Additional_Opened_Packages_Summary"); 556 String aopTableSummary = configuration.getText("doclet.Additional_Packages_Table_Summary", 557 configuration.getText("doclet.Additional_Opened_Packages_Summary"), 558 configuration.getText("doclet.modules"), 559 configuration.getText("doclet.packages")); 560 Content aopTable = getTableHeader(aopText, aopTableSummary, HtmlStyle.packagesSummary, 561 additionalPackagesTableHeader); 562 Content aopTbody = new HtmlTree(HtmlTag.TBODY); 563 addAdditionalPackages(aopTbody, additionalOpenPackages); 564 aopTable.addContent(aopTbody); 565 li.addContent(aopTable); 566 } 567 HtmlTree ul = HtmlTree.UL(HtmlStyle.blockList, li); 568 summaryContentTree.addContent(ul); 569 } 570 } 571 572 /** 573 * Add the package summary for the module. 574 * 575 * @param tableSummary 576 * @param li 577 */ 578 public void addPackageSummary(String tableSummary, HtmlTree li) { 579 Content caption; 580 Content tbody = getPackageTableRows(); 581 if (showTabs()) { 582 caption = getTableCaption(); 583 generateTableTabTypesScript(typeMap, modulePackageTypes, "packages"); 584 } else { 585 ModulePackageTypes type = modulePackageTypes.iterator().next(); 586 caption = getTableCaption(configuration.getContent(type.tableTabs().resourceKey())); 587 } 588 Content table = getTableHeader(caption, tableSummary, HtmlStyle.packagesSummary, exportedPackagesTableHeader); 589 table.addContent(tbody); 590 li.addContent(table); 591 } 592 593 /** 594 * Returns true if the table tabs needs to be displayed. 595 * 596 * @return true if the tabs should be displayed 597 */ 598 public boolean showTabs() { 599 int value; 600 for (ModulePackageTypes type : EnumSet.allOf(ModulePackageTypes.class)) { 601 value = type.tableTabs().value(); 602 if ((value & packageTypesOr) == value) { 603 modulePackageTypes.add(type); 604 } 605 } 606 boolean showTabs = modulePackageTypes.size() > 1; 607 if (showTabs) { 608 modulePackageTypes.add(ModulePackageTypes.ALL); 609 } 610 return showTabs; 611 } 612 613 /** 614 * Get the summary table caption. 615 * 616 * @return the caption for the summary table 617 */ 618 public Content getTableCaption() { 619 Content tabbedCaption = new HtmlTree(HtmlTag.CAPTION); 620 for (ModulePackageTypes type : modulePackageTypes) { 621 Content captionSpan; 622 Content span; 623 if (type.tableTabs().isDefaultTab()) { 624 captionSpan = HtmlTree.SPAN(configuration.getContent(type.tableTabs().resourceKey())); 625 span = HtmlTree.SPAN(type.tableTabs().tabId(), 626 HtmlStyle.activeTableTab, captionSpan); 627 } else { 628 captionSpan = HtmlTree.SPAN(getPackageTypeLinks(type)); 629 span = HtmlTree.SPAN(type.tableTabs().tabId(), 630 HtmlStyle.tableTab, captionSpan); 631 } 632 Content tabSpan = HtmlTree.SPAN(HtmlStyle.tabEnd, Contents.SPACE); 633 span.addContent(tabSpan); 634 tabbedCaption.addContent(span); 635 } 636 return tabbedCaption; 637 } 638 639 /** 640 * Get the package type links for the table caption. 641 * 642 * @param packageType the package type to be displayed as link 643 * @return the content tree for the package type link 644 */ 645 public Content getPackageTypeLinks(ModulePackageTypes packageType) { 646 String jsShow = "javascript:showPkgs(" + packageType.tableTabs().value() + ");"; 647 HtmlTree link = HtmlTree.A(jsShow, configuration.getContent(packageType.tableTabs().resourceKey())); 648 return link; 649 } 650 651 /** 652 * Get the package table rows. 653 * 654 * @return a content object 655 */ 656 public Content getPackageTableRows() { 657 Content tbody = new HtmlTree(HtmlTag.TBODY); 658 boolean altColor = true; 659 int counter = 0; 660 counter = addPackageTableRows(tbody, counter, ModulePackageTypes.EXPORTED, exportedPackages); 661 counter = addPackageTableRows(tbody, counter, ModulePackageTypes.OPENED, openedPackages); 662 // Show concealed packages only in "all" mode. 663 if (moduleMode == ModuleMode.ALL) { 664 for (PackageElement pkg : concealedPackages) { 665 Content pkgLinkContent = getPackageLink(pkg, new StringContent(utils.getPackageName(pkg))); 666 Content thPackage = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, pkgLinkContent); 667 HtmlTree tdModules = new HtmlTree(HtmlTag.TD); 668 tdModules.addStyle(HtmlStyle.colSecond); 669 tdModules.addContent(configuration.getText("doclet.None")); 670 HtmlTree tdSummary = new HtmlTree(HtmlTag.TD); 671 tdSummary.addStyle(HtmlStyle.colLast); 672 addSummaryComment(pkg, tdSummary); 673 HtmlTree tr = HtmlTree.TR(thPackage); 674 tr.addContent(tdModules); 675 tr.addContent(tdSummary); 676 tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor); 677 int pkgType = ModulePackageTypes.CONCEALED.tableTabs().value(); 678 packageTypesOr = packageTypesOr | pkgType; 679 String tableId = "i" + counter; 680 counter++; 681 typeMap.put(tableId, pkgType); 682 tr.addAttr(HtmlAttr.ID, tableId); 683 tbody.addContent(tr); 684 altColor = !altColor; 685 } 686 } 687 return tbody; 688 } 689 690 public int addPackageTableRows(Content tbody, int counter, ModulePackageTypes pType, 691 Map<PackageElement,SortedSet<ModuleElement>> ap) { 692 boolean altColor = true; 693 for (Map.Entry<PackageElement, SortedSet<ModuleElement>> entry : ap.entrySet()) { 694 PackageElement pkg = entry.getKey(); 695 SortedSet<ModuleElement> mdleList = entry.getValue(); 696 Content pkgLinkContent = getPackageLink(pkg, new StringContent(utils.getPackageName(pkg))); 697 Content thPackage = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, pkgLinkContent); 698 HtmlTree tr = HtmlTree.TR(thPackage); 699 if (moduleMode == ModuleMode.ALL) { 700 HtmlTree tdModules = new HtmlTree(HtmlTag.TD); 701 tdModules.addStyle(HtmlStyle.colSecond); 702 if (!mdleList.isEmpty()) { 703 int sep = 0; 704 for (ModuleElement m : mdleList) { 705 if (sep > 0) { 706 tdModules.addContent(new HtmlTree(HtmlTag.BR)); 707 } 708 tdModules.addContent(getModuleLink(m, new StringContent(m.getQualifiedName()))); 709 sep++; 710 } 711 } else { 712 tdModules.addContent(configuration.getText("doclet.All_Modules")); 713 } 714 tr.addContent(tdModules); 715 } 716 HtmlTree tdSummary = new HtmlTree(HtmlTag.TD); 717 tdSummary.addStyle(HtmlStyle.colLast); 718 addSummaryComment(pkg, tdSummary); 719 tr.addContent(tdSummary); 720 tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor); 721 int pkgType = pType.tableTabs().value(); 722 packageTypesOr = packageTypesOr | pkgType; 723 String tableId = "i" + counter; 724 counter++; 725 typeMap.put(tableId, pkgType); 726 tr.addAttr(HtmlAttr.ID, tableId); 727 tbody.addContent(tr); 728 altColor = !altColor; 729 } 730 return counter; 731 } 732 733 /** 734 * Add the additional packages for the module being documented. 735 * 736 * @param tbody the content tree to which the table will be added 737 * @param ap additional packages to be added 738 */ 739 public void addAdditionalPackages(Content tbody, Map<ModuleElement, SortedSet<PackageElement>> ap) { 740 boolean altColor = true; 741 for (Map.Entry<ModuleElement, SortedSet<PackageElement>> entry : ap.entrySet()) { 742 ModuleElement m = entry.getKey(); 743 SortedSet<PackageElement> pkgList = entry.getValue(); 744 Content moduleLinkContent = getModuleLink(m, new StringContent(m.getQualifiedName())); 745 Content thModule = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, moduleLinkContent); 746 HtmlTree tdPackages = new HtmlTree(HtmlTag.TD); 747 tdPackages.addStyle(HtmlStyle.colLast); 748 String sep = ""; 749 for (PackageElement pkg : pkgList) { 750 tdPackages.addContent(sep); 751 tdPackages.addContent(getPackageLink(pkg, new StringContent(utils.getPackageName(pkg)))); 752 sep = " "; 753 } 754 HtmlTree tr = HtmlTree.TR(thModule); 755 tr.addContent(tdPackages); 756 tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor); 757 tbody.addContent(tr); 758 altColor = !altColor; 759 } 760 } 761 762 /** 763 * {@inheritDoc} 764 */ 765 public void addServicesSummary(Content summaryContentTree) { 766 if (display(uses) || display(provides)) { 767 HtmlTree li = new HtmlTree(HtmlTag.LI); 768 li.addStyle(HtmlStyle.blockList); 769 addSummaryHeader(HtmlConstants.START_OF_SERVICES_SUMMARY, SectionName.SERVICES, 770 contents.navServices, li); 771 String text; 772 String tableSummary; 773 if (display(uses)) { 774 text = configuration.getText("doclet.Uses_Summary"); 775 tableSummary = configuration.getText("doclet.Member_Table_Summary", 776 configuration.getText("doclet.Uses_Summary"), 777 configuration.getText("doclet.types")); 778 Content table = getTableHeader(text, tableSummary, HtmlStyle.usesSummary, usesTableHeader); 779 Content tbody = new HtmlTree(HtmlTag.TBODY); 780 addUsesList(tbody); 781 if (!tbody.isEmpty()) { 782 table.addContent(tbody); 783 li.addContent(table); 784 } 785 } 786 if (display(provides)) { 787 text = configuration.getText("doclet.Provides_Summary"); 788 tableSummary = configuration.getText("doclet.Member_Table_Summary", 789 configuration.getText("doclet.Provides_Summary"), 790 configuration.getText("doclet.types")); 791 Content table = getTableHeader(text, tableSummary, HtmlStyle.providesSummary, providesTableHeader); 792 Content tbody = new HtmlTree(HtmlTag.TBODY); 793 addProvidesList(tbody); 794 if (!tbody.isEmpty()) { 795 table.addContent(tbody); 796 li.addContent(table); 797 } 798 } 799 HtmlTree ul = HtmlTree.UL(HtmlStyle.blockList, li); 800 summaryContentTree.addContent(ul); 801 } 802 } 803 804 /** 805 * Add the uses list for the module. 806 * 807 * @param tbody the content tree to which the directive will be added 808 */ 809 public void addUsesList(Content tbody) { 810 boolean altColor = true; 811 Content typeLinkContent; 812 Content thType; 813 HtmlTree tdSummary; 814 Content description; 815 for (TypeElement t : uses) { 816 // For each uses directive in the module declaration, if we are in the "api" mode and 817 // if there are service types listed using @uses javadoc tag, check if the service type in 818 // the uses directive is specified using the @uses tag. If not, we do not display the 819 // service type in the "api" mode. 820 if (moduleMode == ModuleMode.API && display(usesTrees) && !usesTrees.containsKey(t)) { 821 continue; 822 } 823 typeLinkContent = getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.PACKAGE, t)); 824 thType = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, typeLinkContent); 825 tdSummary = new HtmlTree(HtmlTag.TD); 826 tdSummary.addStyle(HtmlStyle.colLast); 827 if (display(usesTrees)) { 828 description = usesTrees.get(t); 829 if (description != null) { 830 tdSummary.addContent(description); 831 } 832 } 833 addSummaryComment(t, tdSummary); 834 HtmlTree tr = HtmlTree.TR(thType); 835 tr.addContent(tdSummary); 836 tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor); 837 tbody.addContent(tr); 838 altColor = !altColor; 839 } 840 } 841 842 /** 843 * Add the provides list for the module. 844 * 845 * @param tbody the content tree to which the directive will be added 846 */ 847 public void addProvidesList(Content tbody) { 848 boolean altColor = true; 849 TypeElement srv; 850 SortedSet<TypeElement> implSet; 851 Content description; 852 for (Map.Entry<TypeElement, SortedSet<TypeElement>> entry : provides.entrySet()) { 853 srv = entry.getKey(); 854 // For each provides directive in the module declaration, if we are in the "api" mode and 855 // if there are service types listed using @provides javadoc tag, check if the service type in 856 // the provides directive is specified using the @provides tag. If not, we do not display the 857 // service type in the "api" mode. 858 if (moduleMode == ModuleMode.API && display(providesTrees) && !providesTrees.containsKey(srv)) { 859 continue; 860 } 861 implSet = entry.getValue(); 862 Content srvLinkContent = getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.PACKAGE, srv)); 863 HtmlTree thType = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, srvLinkContent); 864 HtmlTree tdDesc = new HtmlTree(HtmlTag.TD); 865 tdDesc.addStyle(HtmlStyle.colLast); 866 if (display(providesTrees)) { 867 description = providesTrees.get(srv); 868 if (description != null) { 869 tdDesc.addContent(description); 870 } 871 } 872 addSummaryComment(srv, tdDesc); 873 // Only display the implementation details in the "all" mode. 874 if (moduleMode == ModuleMode.ALL && !implSet.isEmpty()) { 875 tdDesc.addContent(new HtmlTree(HtmlTag.BR)); 876 tdDesc.addContent("("); 877 HtmlTree implSpan = HtmlTree.SPAN(HtmlStyle.implementationLabel, contents.implementation); 878 tdDesc.addContent(implSpan); 879 tdDesc.addContent(Contents.SPACE); 880 String sep = ""; 881 for (TypeElement impl : implSet) { 882 tdDesc.addContent(sep); 883 tdDesc.addContent(getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.PACKAGE, impl))); 884 sep = ", "; 885 } 886 tdDesc.addContent(")"); 887 } 888 HtmlTree tr = HtmlTree.TR(thType); 889 tr.addContent(tdDesc); 890 tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor); 891 tbody.addContent(tr); 892 altColor = !altColor; 893 } 894 } 895 896 /** 897 * Add the module deprecation information to the documentation tree. 898 * 899 * @param div the content tree to which the deprecation information will be added 900 */ 901 public void addDeprecationInfo(Content div) { 902 List<? extends DocTree> deprs = utils.getBlockTags(mdle, DocTree.Kind.DEPRECATED); 903 if (utils.isDeprecated(mdle)) { 904 CommentHelper ch = utils.getCommentHelper(mdle); 905 HtmlTree deprDiv = new HtmlTree(HtmlTag.DIV); 906 deprDiv.addStyle(HtmlStyle.deprecatedContent); 907 Content deprPhrase = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, getDeprecatedPhrase(mdle)); 908 deprDiv.addContent(deprPhrase); 909 if (!deprs.isEmpty()) { 910 List<? extends DocTree> commentTags = ch.getDescription(configuration, deprs.get(0)); 911 if (!commentTags.isEmpty()) { 912 addInlineDeprecatedComment(mdle, deprs.get(0), deprDiv); 913 } 914 } 915 div.addContent(deprDiv); 916 } 917 } 918 919 /** 920 * {@inheritDoc} 921 */ 922 @Override 923 public void addModuleDescription(Content moduleContentTree) { 924 if (!utils.getFullBody(mdle).isEmpty()) { 925 Content tree = configuration.allowTag(HtmlTag.SECTION) ? HtmlTree.SECTION() : moduleContentTree; 926 addDeprecationInfo(tree); 927 tree.addContent(HtmlConstants.START_OF_MODULE_DESCRIPTION); 928 tree.addContent(getMarkerAnchor(SectionName.MODULE_DESCRIPTION)); 929 addInlineComment(mdle, tree); 930 if (configuration.allowTag(HtmlTag.SECTION)) { 931 moduleContentTree.addContent(tree); 932 } 933 } 934 } 935 936 /** 937 * {@inheritDoc} 938 */ 939 @Override 940 public void addModuleTags(Content moduleContentTree) { 941 Content tree = (configuration.allowTag(HtmlTag.SECTION)) 942 ? HtmlTree.SECTION() 943 : moduleContentTree; 944 addTagsInfo(mdle, tree); 945 if (configuration.allowTag(HtmlTag.SECTION)) { 946 moduleContentTree.addContent(tree); 947 } 948 } 949 950 /** 951 * Add summary details to the navigation bar. 952 * 953 * @param subDiv the content tree to which the summary detail links will be added 954 */ 955 @Override 956 protected void addSummaryDetailLinks(Content subDiv) { 957 Content div = HtmlTree.DIV(getNavSummaryLinks()); 958 subDiv.addContent(div); 959 } 960 961 /** 962 * Get summary links for navigation bar. 963 * 964 * @return the content tree for the navigation summary links 965 */ 966 protected Content getNavSummaryLinks() { 967 Content li = HtmlTree.LI(contents.moduleSubNavLabel); 968 li.addContent(Contents.SPACE); 969 Content ulNav = HtmlTree.UL(HtmlStyle.subNavList, li); 970 Content liNav = new HtmlTree(HtmlTag.LI); 971 liNav.addContent(!utils.getFullBody(mdle).isEmpty() && !configuration.nocomment 972 ? getHyperLink(SectionName.MODULE_DESCRIPTION, contents.navModuleDescription) 973 : contents.navModuleDescription); 974 addNavGap(liNav); 975 liNav.addContent((display(requires) || display(additionalModules)) 976 ? getHyperLink(SectionName.MODULES, contents.navModules) 977 : contents.navModules); 978 addNavGap(liNav); 979 liNav.addContent((display(exportedPackages) || display(openedPackages) || display(concealedPackages) 980 || display(additionalPackages) || display(additionalOpenPackages)) 981 ? getHyperLink(SectionName.PACKAGES, contents.navPackages) 982 : contents.navPackages); 983 addNavGap(liNav); 984 liNav.addContent((display(uses) || (moduleMode == ModuleMode.API && display(usesTrees)) 985 || display(provides) || (moduleMode == ModuleMode.API && display(providesTrees))) 986 ? getHyperLink(SectionName.SERVICES, contents.navServices) 987 : contents.navServices); 988 ulNav.addContent(liNav); 989 return ulNav; 990 } 991 992 /** 993 * {@inheritDoc} 994 */ 995 @Override 996 public void addModuleContent(Content contentTree, Content moduleContentTree) { 997 if (configuration.allowTag(HtmlTag.MAIN)) { 998 mainTree.addContent(moduleContentTree); 999 contentTree.addContent(mainTree); 1000 } else { 1001 contentTree.addContent(moduleContentTree); 1002 } 1003 } 1004 1005 /** 1006 * {@inheritDoc} 1007 */ 1008 @Override 1009 public void addModuleFooter(Content contentTree) { 1010 Content htmlTree = (configuration.allowTag(HtmlTag.FOOTER)) 1011 ? HtmlTree.FOOTER() 1012 : contentTree; 1013 addNavLinks(false, htmlTree); 1014 addBottom(htmlTree); 1015 if (configuration.allowTag(HtmlTag.FOOTER)) { 1016 contentTree.addContent(htmlTree); 1017 } 1018 } 1019 1020 /** 1021 * {@inheritDoc} 1022 * 1023 * @throws jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException 1024 */ 1025 @Override 1026 public void printDocument(Content contentTree) throws DocFileIOException { 1027 printHtmlDocument(configuration.metakeywords.getMetaKeywordsForModule(mdle), 1028 true, contentTree); 1029 } 1030 1031 /** 1032 * Add the module package deprecation information to the documentation tree. 1033 * 1034 * @param li the content tree to which the deprecation information will be added 1035 * @param pkg the PackageDoc that is added 1036 */ 1037 public void addPackageDeprecationInfo(Content li, PackageElement pkg) { 1038 List<? extends DocTree> deprs; 1039 if (utils.isDeprecated(pkg)) { 1040 deprs = utils.getDeprecatedTrees(pkg); 1041 HtmlTree deprDiv = new HtmlTree(HtmlTag.DIV); 1042 deprDiv.addStyle(HtmlStyle.deprecatedContent); 1043 Content deprPhrase = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, getDeprecatedPhrase(pkg)); 1044 deprDiv.addContent(deprPhrase); 1045 if (!deprs.isEmpty()) { 1046 CommentHelper ch = utils.getCommentHelper(pkg); 1047 List<? extends DocTree> commentTags = ch.getDescription(configuration, deprs.get(0)); 1048 if (!commentTags.isEmpty()) { 1049 addInlineDeprecatedComment(pkg, deprs.get(0), deprDiv); 1050 } 1051 } 1052 li.addContent(deprDiv); 1053 } 1054 } 1055 1056 /** 1057 * Get this module link. 1058 * 1059 * @return a content tree for the module link 1060 */ 1061 @Override 1062 protected Content getNavLinkModule() { 1063 Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, contents.moduleLabel); 1064 return li; 1065 } 1066 1067 /** 1068 * Get "PREV MODULE" link in the navigation bar. 1069 * 1070 * @return a content tree for the previous link 1071 */ 1072 @Override 1073 public Content getNavLinkPrevious() { 1074 Content li; 1075 if (prevModule == null) { 1076 li = HtmlTree.LI(contents.prevModuleLabel); 1077 } else { 1078 li = HtmlTree.LI(getHyperLink(pathToRoot.resolve(DocPaths.moduleSummary( 1079 prevModule)), contents.prevModuleLabel, "", "")); 1080 } 1081 return li; 1082 } 1083 1084 /** 1085 * Get "NEXT MODULE" link in the navigation bar. 1086 * 1087 * @return a content tree for the next link 1088 */ 1089 @Override 1090 public Content getNavLinkNext() { 1091 Content li; 1092 if (nextModule == null) { 1093 li = HtmlTree.LI(contents.nextModuleLabel); 1094 } else { 1095 li = HtmlTree.LI(getHyperLink(pathToRoot.resolve(DocPaths.moduleSummary( 1096 nextModule)), contents.nextModuleLabel, "", "")); 1097 } 1098 return li; 1099 } 1100} 1101