/*
 * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package jdk.javadoc.internal.doclets.formats.html;

import jdk.javadoc.internal.doclets.formats.html.markup.Table;
import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;

import javax.lang.model.element.Element;
import javax.lang.model.element.ModuleElement;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.ElementFilter;

import com.sun.source.doctree.DocTree;
import jdk.javadoc.doclet.DocletEnvironment.ModuleMode;
import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
import jdk.javadoc.internal.doclets.formats.html.markup.Navigation;
import jdk.javadoc.internal.doclets.formats.html.markup.Navigation.PageMode;
import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml;
import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
import jdk.javadoc.internal.doclets.toolkit.Content;
import jdk.javadoc.internal.doclets.toolkit.ModuleSummaryWriter;
import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper;
import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;

Class to generate file for each module contents in the right-hand frame. This will list all the required modules, packages and service types for the module. A click on any of the links will update the frame with the clicked element page.

This is NOT part of any supported API. If you write code that depends on this, you do so at your own risk. This code and its internal interfaces are subject to change or deletion without notice.

Author:Bhavesh Patel
/** * Class to generate file for each module contents in the right-hand frame. This will list all the * required modules, packages and service types for the module. A click on any of the links will update * the frame with the clicked element page. * * <p><b>This is NOT part of any supported API. * If you write code that depends on this, you do so at your own risk. * This code and its internal interfaces are subject to change or * deletion without notice.</b> * * @author Bhavesh Patel */
public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryWriter {
The module being documented.
/** * The module being documented. */
protected ModuleElement mdle;
The module mode for this javadoc run. It can be set to "api" or "all".
/** * The module mode for this javadoc run. It can be set to "api" or "all". */
private final ModuleMode moduleMode;
Map of module elements and modifiers required by this module.
/** * Map of module elements and modifiers required by this module. */
private final Map<ModuleElement, Content> requires = new TreeMap<>(utils.makeModuleComparator());
Map of indirect modules and modifiers, transitive closure, required by this module.
/** * Map of indirect modules and modifiers, transitive closure, required by this module. */
private final Map<ModuleElement, Content> indirectModules = new TreeMap<>(utils.makeModuleComparator());
Details about a package in a module. A package may be not exported, or exported to some modules, or exported to all modules. A package may be not opened, or opened to some modules, or opened to all modules. A package that is neither exported or opened to any modules is a concealed package. An open module opens all its packages to all modules.
/** * Details about a package in a module. * A package may be not exported, or exported to some modules, or exported to all modules. * A package may be not opened, or opened to some modules, or opened to all modules. * A package that is neither exported or opened to any modules is a concealed package. * An open module opens all its packages to all modules. */
class PackageEntry {
Summary of package exports: If null, the package is not exported to any modules; if empty, the package is exported to all modules; otherwise, the package is exported to these modules.
/** * Summary of package exports: * If null, the package is not exported to any modules; * if empty, the package is exported to all modules; * otherwise, the package is exported to these modules. */
Set<ModuleElement> exportedTo;
Summary of package opens: If null, the package is not opened to any modules; if empty, the package is opened to all modules; otherwise, the package is opened to these modules.
/** * Summary of package opens: * If null, the package is not opened to any modules; * if empty, the package is opened to all modules; * otherwise, the package is opened to these modules. */
Set<ModuleElement> openedTo; }
Map of packages of this module, and details of whether they are exported or opened.
/** * Map of packages of this module, and details of whether they are exported or opened. */
private final Map<PackageElement, PackageEntry> packages = new TreeMap<>(utils.makePackageComparator());
Map of indirect modules (transitive closure) and their exported packages.
/** * Map of indirect modules (transitive closure) and their exported packages. */
private final Map<ModuleElement, SortedSet<PackageElement>> indirectPackages = new TreeMap<>(utils.makeModuleComparator());
Map of indirect modules (transitive closure) and their open packages.
/** * Map of indirect modules (transitive closure) and their open packages. */
private final Map<ModuleElement, SortedSet<PackageElement>> indirectOpenPackages = new TreeMap<>(utils.makeModuleComparator());
Set of services used by the module.
/** * Set of services used by the module. */
private final SortedSet<TypeElement> uses = new TreeSet<>(utils.makeAllClassesComparator());
Map of services used by the module and specified using @uses javadoc tag, and description.
/** * Map of services used by the module and specified using @uses javadoc tag, and description. */
private final Map<TypeElement, Content> usesTrees = new TreeMap<>(utils.makeAllClassesComparator());
Map of services provided by this module, and set of its implementations.
/** * Map of services provided by this module, and set of its implementations. */
private final Map<TypeElement, SortedSet<TypeElement>> provides = new TreeMap<>(utils.makeAllClassesComparator());
Map of services provided by the module and specified using @provides javadoc tag, and description.
/** * Map of services provided by the module and specified using @provides javadoc tag, and * description. */
private final Map<TypeElement, Content> providesTrees = new TreeMap<>(utils.makeAllClassesComparator());
The HTML tree for main tag.
/** * The HTML tree for main tag. */
protected HtmlTree mainTree = HtmlTree.MAIN();
The HTML tree for section tag.
/** * The HTML tree for section tag. */
protected HtmlTree sectionTree = HtmlTree.SECTION(); private final Navigation navBar;
Constructor to construct ModuleWriter object and to generate "moduleName-summary.html" file.
Params:
  • configuration – the configuration of the doclet.
  • mdle – Module under consideration.
/** * Constructor to construct ModuleWriter object and to generate "moduleName-summary.html" file. * * @param configuration the configuration of the doclet. * @param mdle Module under consideration. */
public ModuleWriterImpl(HtmlConfiguration configuration, ModuleElement mdle) { super(configuration, configuration.docPaths.moduleSummary(mdle)); this.mdle = mdle; this.moduleMode = configuration.docEnv.getModuleMode(); this.navBar = new Navigation(mdle, configuration, fixedNavDiv, PageMode.MODULE, path); computeModulesData(); }
Get the module header.
Params:
  • heading – the heading for the section
/** * Get the module header. * * @param heading the heading for the section */
@Override public Content getModuleHeader(String heading) { HtmlTree bodyTree = getBody(true, getWindowTitle(mdle.getQualifiedName().toString())); HtmlTree htmlTree = (configuration.allowTag(HtmlTag.HEADER)) ? HtmlTree.HEADER() : bodyTree; addTop(htmlTree); navBar.setDisplaySummaryModuleDescLink(!utils.getFullBody(mdle).isEmpty() && !configuration.nocomment); navBar.setDisplaySummaryModulesLink(display(requires) || display(indirectModules)); navBar.setDisplaySummaryPackagesLink(display(packages) || display(indirectPackages) || display(indirectOpenPackages)); navBar.setDisplaySummaryServicesLink(displayServices(uses, usesTrees) || displayServices(provides.keySet(), providesTrees)); navBar.setUserHeader(getUserHeaderFooter(true)); htmlTree.addContent(navBar.getContent(true)); if (configuration.allowTag(HtmlTag.HEADER)) { bodyTree.addContent(htmlTree); } HtmlTree div = new HtmlTree(HtmlTag.DIV); div.setStyle(HtmlStyle.header); Content annotationContent = new HtmlTree(HtmlTag.P); addAnnotationInfo(mdle, annotationContent); div.addContent(annotationContent); Content label = mdle.isOpen() && (configuration.docEnv.getModuleMode() == ModuleMode.ALL) ? contents.openModuleLabel : contents.moduleLabel; Content tHeading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, true, HtmlStyle.title, label); tHeading.addContent(Contents.SPACE); Content moduleHead = new RawHtml(heading); tHeading.addContent(moduleHead); div.addContent(tHeading); if (configuration.allowTag(HtmlTag.MAIN)) { mainTree.addContent(div); } else { bodyTree.addContent(div); } return bodyTree; }
Get the content header.
/** * Get the content header. */
@Override public Content getContentHeader() { HtmlTree div = new HtmlTree(HtmlTag.DIV); div.setStyle(HtmlStyle.contentContainer); return div; }
Get the summary section header.
/** * Get the summary section header. */
@Override public Content getSummaryHeader() { HtmlTree li = new HtmlTree(HtmlTag.LI); li.setStyle(HtmlStyle.blockList); return li; }
Get the summary tree.
Params:
  • summaryContentTree – the content tree to be added to the summary tree.
/** * Get the summary tree. * * @param summaryContentTree the content tree to be added to the summary tree. */
@Override public Content getSummaryTree(Content summaryContentTree) { HtmlTree ul = HtmlTree.UL(HtmlStyle.blockList, summaryContentTree); return ul; }
Compute the modules data that will be displayed in various tables on the module summary page.
/** * Compute the modules data that will be displayed in various tables on the module summary page. */
public void computeModulesData() { CommentHelper ch = utils.getCommentHelper(mdle); // Get module dependencies using the module's transitive closure. Map<ModuleElement, String> dependentModules = utils.getDependentModules(mdle); // Add all dependent modules to indirect modules set. We will remove the modules, // listed using the requires directive, from this set to come up with the table of indirect // required modules. dependentModules.forEach((module, mod) -> { if (shouldDocument(module)) { indirectModules.put(module, new StringContent(mod)); } }); (ElementFilter.requiresIn(mdle.getDirectives())).forEach((directive) -> { ModuleElement m = directive.getDependency(); if (shouldDocument(m)) { if (moduleMode == ModuleMode.ALL || directive.isTransitive()) { requires.put(m, new StringContent(utils.getModifiers(directive))); } else { // For api mode, just keep the public requires in dependentModules for display of // indirect packages in the "Packages" section. dependentModules.remove(m); } indirectModules.remove(m); } }); // Get all packages if module is open or if displaying concealed modules for (PackageElement pkg : utils.getModulePackageMap().getOrDefault(mdle, Collections.emptySet())) { if (shouldDocument(pkg) && (mdle.isOpen() || moduleMode == ModuleMode.ALL)) { PackageEntry e = new PackageEntry(); if (mdle.isOpen()) { e.openedTo = Collections.emptySet(); } packages.put(pkg, e); } }; // Get all exported packages for the module, using the exports directive for the module. for (ModuleElement.ExportsDirective directive : ElementFilter.exportsIn(mdle.getDirectives())) { PackageElement p = directive.getPackage(); if (shouldDocument(p)) { List<? extends ModuleElement> targetMdles = directive.getTargetModules(); // Include package if in details mode, or exported to all (i.e. targetModules == null) if (moduleMode == ModuleMode.ALL || targetMdles == null) { PackageEntry packageEntry = packages.computeIfAbsent(p, pkg -> new PackageEntry()); SortedSet<ModuleElement> mdleList = new TreeSet<>(utils.makeModuleComparator()); if (targetMdles != null) { mdleList.addAll(targetMdles); } packageEntry.exportedTo = mdleList; } } } // Get all opened packages for the module, using the opens directive for the module. // If it is an open module, there will be no separate opens directives. for (ModuleElement.OpensDirective directive : ElementFilter.opensIn(mdle.getDirectives())) { PackageElement p = directive.getPackage(); if (shouldDocument(p)) { List<? extends ModuleElement> targetMdles = directive.getTargetModules(); // Include package if in details mode, or opened to all (i.e. targetModules == null) if (moduleMode == ModuleMode.ALL || targetMdles == null) { PackageEntry packageEntry = packages.computeIfAbsent(p, pkg -> new PackageEntry()); SortedSet<ModuleElement> mdleList = new TreeSet<>(utils.makeModuleComparator()); if (targetMdles != null) { mdleList.addAll(targetMdles); } packageEntry.openedTo = mdleList; } } } // Get all the exported and opened packages, for the transitive closure of the module, to be displayed in // the indirect packages tables. dependentModules.forEach((module, mod) -> { SortedSet<PackageElement> exportPkgList = new TreeSet<>(utils.makePackageComparator()); (ElementFilter.exportsIn(module.getDirectives())).forEach((directive) -> { PackageElement pkg = directive.getPackage(); if (shouldDocument(pkg)) { // Qualified exports are not displayed in API mode if (moduleMode == ModuleMode.ALL || directive.getTargetModules() == null) { exportPkgList.add(pkg); } } }); // If none of the indirect modules have exported packages to be displayed, we should not be // displaying the table and so it should not be added to the map. if (!exportPkgList.isEmpty()) { indirectPackages.put(module, exportPkgList); } SortedSet<PackageElement> openPkgList = new TreeSet<>(utils.makePackageComparator()); if (module.isOpen()) { openPkgList.addAll(utils.getModulePackageMap().getOrDefault(module, Collections.emptySet())); } else { (ElementFilter.opensIn(module.getDirectives())).forEach((directive) -> { PackageElement pkg = directive.getPackage(); if (shouldDocument(pkg)) { // Qualified opens are not displayed in API mode if (moduleMode == ModuleMode.ALL || directive.getTargetModules() == null) { openPkgList.add(pkg); } } }); } // If none of the indirect modules have opened packages to be displayed, we should not be // displaying the table and so it should not be added to the map. if (!openPkgList.isEmpty()) { indirectOpenPackages.put(module, openPkgList); } }); // Get all the services listed as uses directive. (ElementFilter.usesIn(mdle.getDirectives())).forEach((directive) -> { TypeElement u = directive.getService(); if (shouldDocument(u)) { uses.add(u); } }); // Get all the services and implementations listed as provides directive. (ElementFilter.providesIn(mdle.getDirectives())).forEach((directive) -> { TypeElement u = directive.getService(); if (shouldDocument(u)) { List<? extends TypeElement> implList = directive.getImplementations(); SortedSet<TypeElement> implSet = new TreeSet<>(utils.makeAllClassesComparator()); implSet.addAll(implList); provides.put(u, implSet); } }); // Generate the map of all services listed using @provides, and the description. (utils.getBlockTags(mdle, DocTree.Kind.PROVIDES)).forEach((tree) -> { TypeElement t = ch.getServiceType(configuration, tree); if (t != null) { providesTrees.put(t, commentTagsToContent(tree, mdle, ch.getDescription(configuration, tree), false, true)); } }); // Generate the map of all services listed using @uses, and the description. (utils.getBlockTags(mdle, DocTree.Kind.USES)).forEach((tree) -> { TypeElement t = ch.getServiceType(configuration, tree); if (t != null) { usesTrees.put(t, commentTagsToContent(tree, mdle, ch.getDescription(configuration, tree), false, true)); } }); }
Returns true if the element should be documented on the module summary page.
Params:
  • element – the element to be checked
Returns:true if the element should be documented
/** * Returns true if the element should be documented on the module summary page. * * @param element the element to be checked * @return true if the element should be documented */
public boolean shouldDocument(Element element) { return (moduleMode == ModuleMode.ALL || utils.isIncluded(element)); }
Returns true if there are elements to be displayed.
Params:
  • section – set of elements
Returns:true if there are elements to be displayed
/** * Returns true if there are elements to be displayed. * * @param section set of elements * @return true if there are elements to be displayed */
public boolean display(Set<? extends Element> section) { return section != null && !section.isEmpty(); }
Returns true if there are elements to be displayed.
Params:
  • section – map of elements.
Returns:true if there are elements to be displayed
/** * Returns true if there are elements to be displayed. * * @param section map of elements. * @return true if there are elements to be displayed */
public boolean display(Map<? extends Element, ?> section) { return section != null && !section.isEmpty(); } /* * Returns true, in API mode, if at least one type element in * the typeElements set is referenced by a javadoc tag in tagsMap. */ private boolean displayServices(Set<TypeElement> typeElements, Map<TypeElement, Content> tagsMap) { return typeElements != null && typeElements.stream().anyMatch((v) -> displayServiceDirective(v, tagsMap)); } /* * Returns true, in API mode, if the type element is referenced * from a javadoc tag in tagsMap. */ private boolean displayServiceDirective(TypeElement typeElement, Map<TypeElement, Content> tagsMap) { return moduleMode == ModuleMode.ALL || tagsMap.containsKey(typeElement); }
Add the summary header.
Params:
  • startMarker – the marker comment
  • markerAnchor – the marker anchor for the section
  • heading – the heading for the section
  • htmltree – the content tree to which the information is added
/** * Add the summary header. * * @param startMarker the marker comment * @param markerAnchor the marker anchor for the section * @param heading the heading for the section * @param htmltree the content tree to which the information is added */
public void addSummaryHeader(Content startMarker, SectionName markerAnchor, Content heading, Content htmltree) { htmltree.addContent(startMarker); htmltree.addContent(links.createAnchor(markerAnchor)); htmltree.addContent(HtmlTree.HEADING(HtmlTag.H3, heading)); }
Get a table, with two columns.
Params:
  • caption – the table caption
  • tableSummary – the summary for the table
  • tableStyle – the table style
  • tableHeader – the table header
Returns:a content object
/** * Get a table, with two columns. * * @param caption the table caption * @param tableSummary the summary for the table * @param tableStyle the table style * @param tableHeader the table header * @return a content object */
private Table getTable2(Content caption, String tableSummary, HtmlStyle tableStyle, TableHeader tableHeader) { return new Table(configuration.htmlVersion, tableStyle) .setSummary(tableSummary) .setCaption(caption) .setHeader(tableHeader) .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colLast); }
Get a table, with three columns, with the second column being the defining column.
Params:
  • caption – the table caption
  • tableSummary – the summary for the table
  • tableStyle – the table style
  • tableHeader – the table header
Returns:a content object
/** * Get a table, with three columns, with the second column being the defining column. * * @param caption the table caption * @param tableSummary the summary for the table * @param tableStyle the table style * @param tableHeader the table header * @return a content object */
private Table getTable3(Content caption, String tableSummary, HtmlStyle tableStyle, TableHeader tableHeader) { return new Table(configuration.htmlVersion, tableStyle) .setSummary(tableSummary) .setCaption(caption) .setHeader(tableHeader) .setRowScopeColumn(1) .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colSecond, HtmlStyle.colLast); }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public void addModulesSummary(Content summaryContentTree) { if (display(requires) || display(indirectModules)) { TableHeader requiresTableHeader = new TableHeader(contents.modifierLabel, contents.moduleLabel, contents.descriptionLabel); HtmlTree li = new HtmlTree(HtmlTag.LI); li.setStyle(HtmlStyle.blockList); addSummaryHeader(HtmlConstants.START_OF_MODULES_SUMMARY, SectionName.MODULES, contents.navModules, li); if (display(requires)) { String text = resources.getText("doclet.Requires_Summary"); String tableSummary = resources.getText("doclet.Member_Table_Summary", text, resources.getText("doclet.modules")); Content caption = getTableCaption(new StringContent(text)); Table table = getTable3(caption, tableSummary, HtmlStyle.requiresSummary, requiresTableHeader); addModulesList(requires, table); li.addContent(table.toContent()); } // Display indirect modules table in both "api" and "all" mode. if (display(indirectModules)) { String amrText = resources.getText("doclet.Indirect_Requires_Summary"); String amrTableSummary = resources.getText("doclet.Member_Table_Summary", amrText, resources.getText("doclet.modules")); Content amrCaption = getTableCaption(new StringContent(amrText)); Table amrTable = getTable3(amrCaption, amrTableSummary, HtmlStyle.requiresSummary, requiresTableHeader); addModulesList(indirectModules, amrTable); li.addContent(amrTable.toContent()); } HtmlTree ul = HtmlTree.UL(HtmlStyle.blockList, li); summaryContentTree.addContent(ul); } }
Add the list of modules.
Params:
  • mdleMap – map of modules and modifiers
  • tbody – the content tree to which the list will be added
/** * Add the list of modules. * * @param mdleMap map of modules and modifiers * @param tbody the content tree to which the list will be added */
private void addModulesList(Map<ModuleElement, Content> mdleMap, Table table) { for (ModuleElement m : mdleMap.keySet()) { Content modifiers = mdleMap.get(m); Content moduleLink = getModuleLink(m, new StringContent(m.getQualifiedName())); Content moduleSummary = new ContentBuilder(); addSummaryComment(m, moduleSummary); table.addRow(modifiers, moduleLink, moduleSummary); } } @Override public void addPackagesSummary(Content summaryContentTree) { if (display(packages) || display(indirectPackages) || display(indirectOpenPackages)) { HtmlTree li = new HtmlTree(HtmlTag.LI); li.setStyle(HtmlStyle.blockList); addSummaryHeader(HtmlConstants.START_OF_PACKAGES_SUMMARY, SectionName.PACKAGES, contents.navPackages, li); if (display(packages)) { String tableSummary = resources.getText("doclet.Member_Table_Summary", resources.getText("doclet.Packages_Summary"), resources.getText("doclet.packages")); addPackageSummary(tableSummary, li); } TableHeader indirectPackagesHeader = new TableHeader(contents.fromLabel, contents.packagesLabel); if (display(indirectPackages)) { String aepText = resources.getText("doclet.Indirect_Exports_Summary"); String aepTableSummary = resources.getText("doclet.Indirect_Packages_Table_Summary", aepText, resources.getText("doclet.modules"), resources.getText("doclet.packages")); Table aepTable = getTable2(new StringContent(aepText), aepTableSummary, HtmlStyle.packagesSummary, indirectPackagesHeader); addIndirectPackages(aepTable, indirectPackages); li.addContent(aepTable.toContent()); } if (display(indirectOpenPackages)) { String aopText = resources.getText("doclet.Indirect_Opens_Summary"); String aopTableSummary = resources.getText("doclet.Indirect_Packages_Table_Summary", aopText, resources.getText("doclet.modules"), resources.getText("doclet.packages")); Table aopTable = getTable2(new StringContent(aopText), aopTableSummary, HtmlStyle.packagesSummary, indirectPackagesHeader); addIndirectPackages(aopTable, indirectOpenPackages); li.addContent(aopTable.toContent()); } HtmlTree ul = HtmlTree.UL(HtmlStyle.blockList, li); summaryContentTree.addContent(ul); } }
Add the package summary for the module.
Params:
  • tableSummary –
  • li –
/** * Add the package summary for the module. * * @param tableSummary * @param li */
public void addPackageSummary(String tableSummary, HtmlTree li) { Table table = new Table(configuration.htmlVersion, HtmlStyle.packagesSummary) .setSummary(tableSummary) .setDefaultTab(resources.getText("doclet.All_Packages")) .addTab(resources.getText("doclet.Exported_Packages_Summary"), this::isExported) .addTab(resources.getText("doclet.Opened_Packages_Summary"), this::isOpened) .addTab(resources.getText("doclet.Concealed_Packages_Summary"), this::isConcealed) .setTabScript(i -> String.format("show(%d);", i)); // Determine whether to show the "Exported To" and "Opened To" columns, // based on whether such columns would provide "useful" info. int numExports = 0; int numUnqualifiedExports = 0; int numOpens = 0; int numUnqualifiedOpens = 0; for (PackageEntry e : packages.values()) { if (e.exportedTo != null) { numExports++; if (e.exportedTo.isEmpty()) { numUnqualifiedExports++; } } if (e.openedTo != null) { numOpens++; if (e.openedTo.isEmpty()) { numUnqualifiedOpens++; } } } boolean showExportedTo = numExports > 0 && (numOpens > 0 || numUnqualifiedExports < packages.size()); boolean showOpenedTo = numOpens > 0 && (numExports > 0 || numUnqualifiedOpens < packages.size()); // Create the table header and column styles. List<Content> colHeaders = new ArrayList<>(); List<HtmlStyle> colStyles = new ArrayList<>(); colHeaders.add(contents.packageLabel); colStyles.add(HtmlStyle.colFirst); if (showExportedTo) { colHeaders.add(contents.exportedTo); colStyles.add(HtmlStyle.colSecond); } if (showOpenedTo) { colHeaders.add(contents.openedTo); colStyles.add(HtmlStyle.colSecond); } colHeaders.add(contents.descriptionLabel); colStyles.add(HtmlStyle.colLast); table.setHeader(new TableHeader(colHeaders).styles(colStyles)) .setColumnStyles(colStyles); // Add the table rows, based on the "packages" map. for (Map.Entry<PackageElement, PackageEntry> e : packages.entrySet()) { PackageElement pkg = e.getKey(); PackageEntry entry = e.getValue(); List<Content> row = new ArrayList<>(); Content pkgLinkContent = getPackageLink(pkg, new StringContent(utils.getPackageName(pkg))); row.add(pkgLinkContent); if (showExportedTo) { row.add(getPackageExportOpensTo(entry.exportedTo)); } if (showOpenedTo) { row.add(getPackageExportOpensTo(entry.openedTo)); } Content summary = new ContentBuilder(); addSummaryComment(pkg, summary); row.add(summary); table.addRow(pkg, row); } li.addContent(table.toContent()); if (table.needsScript()) { mainBodyScript.append(table.getScript()); } } private boolean isExported(Element e) { PackageEntry entry = packages.get((PackageElement) e); return (entry != null) && (entry.exportedTo != null); } private boolean isOpened(Element e) { PackageEntry entry = packages.get((PackageElement) e); return (entry != null) && (entry.openedTo != null); } private boolean isConcealed(Element e) { PackageEntry entry = packages.get((PackageElement) e); return (entry != null) && (entry.exportedTo == null) && (entry.openedTo == null); } private Content getPackageExportOpensTo(Set<ModuleElement> modules) { if (modules == null) { return new StringContent(resources.getText("doclet.None")); } else if (modules.isEmpty()) { return new StringContent(resources.getText("doclet.All_Modules")); } else { Content list = new ContentBuilder(); for (ModuleElement m : modules) { if (!list.isEmpty()) { list.addContent(new StringContent(", ")); } list.addContent(getModuleLink(m, new StringContent(m.getQualifiedName()))); } return list; } }
Add the indirect packages for the module being documented.
Params:
  • table – the table to which the content rows will be added
  • ip – indirect packages to be added
/** * Add the indirect packages for the module being documented. * * @param table the table to which the content rows will be added * @param ip indirect packages to be added */
public void addIndirectPackages(Table table, Map<ModuleElement, SortedSet<PackageElement>> ip) { for (Map.Entry<ModuleElement, SortedSet<PackageElement>> entry : ip.entrySet()) { ModuleElement m = entry.getKey(); SortedSet<PackageElement> pkgList = entry.getValue(); Content moduleLinkContent = getModuleLink(m, new StringContent(m.getQualifiedName())); Content list = new ContentBuilder(); String sep = ""; for (PackageElement pkg : pkgList) { list.addContent(sep); list.addContent(getPackageLink(pkg, new StringContent(utils.getPackageName(pkg)))); sep = " "; } table.addRow(moduleLinkContent, list); } }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public void addServicesSummary(Content summaryContentTree) { boolean haveUses = displayServices(uses, usesTrees); boolean haveProvides = displayServices(provides.keySet(), providesTrees); if (haveProvides || haveUses) { HtmlTree li = new HtmlTree(HtmlTag.LI); li.setStyle(HtmlStyle.blockList); addSummaryHeader(HtmlConstants.START_OF_SERVICES_SUMMARY, SectionName.SERVICES, contents.navServices, li); TableHeader usesProvidesTableHeader = new TableHeader(contents.typeLabel, contents.descriptionLabel); if (haveProvides) { String label = resources.getText("doclet.Provides_Summary"); String tableSummary = resources.getText("doclet.Member_Table_Summary", label, resources.getText("doclet.types")); Table table = getTable2(new StringContent(label), tableSummary, HtmlStyle.providesSummary, usesProvidesTableHeader); addProvidesList(table); if (!table.isEmpty()) { li.addContent(table.toContent()); } } if (haveUses){ String label = resources.getText("doclet.Uses_Summary"); String tableSummary = resources.getText("doclet.Member_Table_Summary", label, resources.getText("doclet.types")); Table table = getTable2(new StringContent(label), tableSummary, HtmlStyle.usesSummary, usesProvidesTableHeader); addUsesList(table); if (!table.isEmpty()) { li.addContent(table.toContent()); } } HtmlTree ul = HtmlTree.UL(HtmlStyle.blockList, li); summaryContentTree.addContent(ul); } }
Add the uses list for the module.
Params:
  • table – the table to which the services used will be added
/** * Add the uses list for the module. * * @param table the table to which the services used will be added */
public void addUsesList(Table table) { Content typeLinkContent; Content description; for (TypeElement t : uses) { if (!displayServiceDirective(t, usesTrees)) { continue; } typeLinkContent = getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.PACKAGE, t)); Content summary = new ContentBuilder(); if (display(usesTrees)) { description = usesTrees.get(t); if (description != null && !description.isEmpty()) { summary.addContent(HtmlTree.DIV(HtmlStyle.block, description)); } else { addSummaryComment(t, summary); } } else { summary.addContent(Contents.SPACE); } table.addRow(typeLinkContent, summary); } }
Add the provides list for the module.
Params:
  • table – the table to which the services provided will be added
/** * Add the provides list for the module. * * @param table the table to which the services provided will be added */
public void addProvidesList(Table table) { SortedSet<TypeElement> implSet; Content description; for (Map.Entry<TypeElement, SortedSet<TypeElement>> entry : provides.entrySet()) { TypeElement srv = entry.getKey(); if (!displayServiceDirective(srv, providesTrees)) { continue; } implSet = entry.getValue(); Content srvLinkContent = getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.PACKAGE, srv)); Content desc = new ContentBuilder(); if (display(providesTrees)) { description = providesTrees.get(srv); desc.addContent((description != null && !description.isEmpty()) ? HtmlTree.DIV(HtmlStyle.block, description) : Contents.SPACE); } else { desc.addContent(Contents.SPACE); } // Only display the implementation details in the "all" mode. if (moduleMode == ModuleMode.ALL && !implSet.isEmpty()) { desc.addContent(new HtmlTree(HtmlTag.BR)); desc.addContent("("); HtmlTree implSpan = HtmlTree.SPAN(HtmlStyle.implementationLabel, contents.implementation); desc.addContent(implSpan); desc.addContent(Contents.SPACE); String sep = ""; for (TypeElement impl : implSet) { desc.addContent(sep); desc.addContent(getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.PACKAGE, impl))); sep = ", "; } desc.addContent(")"); } table.addRow(srvLinkContent, desc); } }
Add the module deprecation information to the documentation tree.
Params:
  • div – the content tree to which the deprecation information will be added
/** * Add the module deprecation information to the documentation tree. * * @param div the content tree to which the deprecation information will be added */
public void addDeprecationInfo(Content div) { List<? extends DocTree> deprs = utils.getBlockTags(mdle, DocTree.Kind.DEPRECATED); if (utils.isDeprecated(mdle)) { CommentHelper ch = utils.getCommentHelper(mdle); HtmlTree deprDiv = new HtmlTree(HtmlTag.DIV); deprDiv.setStyle(HtmlStyle.deprecationBlock); Content deprPhrase = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, getDeprecatedPhrase(mdle)); deprDiv.addContent(deprPhrase); if (!deprs.isEmpty()) { List<? extends DocTree> commentTags = ch.getDescription(configuration, deprs.get(0)); if (!commentTags.isEmpty()) { addInlineDeprecatedComment(mdle, deprs.get(0), deprDiv); } } div.addContent(deprDiv); } }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public void addModuleDescription(Content moduleContentTree) { if (!utils.getFullBody(mdle).isEmpty()) { Content tree = configuration.allowTag(HtmlTag.SECTION) ? HtmlTree.SECTION() : moduleContentTree; addDeprecationInfo(tree); tree.addContent(HtmlConstants.START_OF_MODULE_DESCRIPTION); tree.addContent(links.createAnchor(SectionName.MODULE_DESCRIPTION)); addInlineComment(mdle, tree); if (configuration.allowTag(HtmlTag.SECTION)) { moduleContentTree.addContent(tree); } } }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public void addModuleTags(Content moduleContentTree) { Content tree = (configuration.allowTag(HtmlTag.SECTION)) ? HtmlTree.SECTION() : moduleContentTree; addTagsInfo(mdle, tree); if (configuration.allowTag(HtmlTag.SECTION)) { moduleContentTree.addContent(tree); } }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public void addModuleContent(Content contentTree, Content moduleContentTree) { if (configuration.allowTag(HtmlTag.MAIN)) { mainTree.addContent(moduleContentTree); contentTree.addContent(mainTree); } else { contentTree.addContent(moduleContentTree); } }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public void addModuleFooter(Content contentTree) { Content htmlTree = (configuration.allowTag(HtmlTag.FOOTER)) ? HtmlTree.FOOTER() : contentTree; navBar.setUserFooter(getUserHeaderFooter(false)); htmlTree.addContent(navBar.getContent(false)); addBottom(htmlTree); if (configuration.allowTag(HtmlTag.FOOTER)) { contentTree.addContent(htmlTree); } }
{@inheritDoc}
Throws:
/** * {@inheritDoc} * * @throws jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException */
@Override public void printDocument(Content contentTree) throws DocFileIOException { printHtmlDocument(configuration.metakeywords.getMetaKeywordsForModule(mdle), true, contentTree); }
Add the module package deprecation information to the documentation tree.
Params:
  • li – the content tree to which the deprecation information will be added
  • pkg – the PackageDoc that is added
/** * Add the module package deprecation information to the documentation tree. * * @param li the content tree to which the deprecation information will be added * @param pkg the PackageDoc that is added */
public void addPackageDeprecationInfo(Content li, PackageElement pkg) { List<? extends DocTree> deprs; if (utils.isDeprecated(pkg)) { deprs = utils.getDeprecatedTrees(pkg); HtmlTree deprDiv = new HtmlTree(HtmlTag.DIV); deprDiv.setStyle(HtmlStyle.deprecationBlock); Content deprPhrase = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, getDeprecatedPhrase(pkg)); deprDiv.addContent(deprPhrase); if (!deprs.isEmpty()) { CommentHelper ch = utils.getCommentHelper(pkg); List<? extends DocTree> commentTags = ch.getDescription(configuration, deprs.get(0)); if (!commentTags.isEmpty()) { addInlineDeprecatedComment(pkg, deprs.get(0), deprDiv); } } li.addContent(deprDiv); } } }