--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Navigation.java Mon Apr 09 09:45:51 2018 -0700
@@ -0,0 +1,1089 @@
+/*
+ * Copyright (c) 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.markup;
+
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.SortedSet;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.ModuleElement;
+import javax.lang.model.element.PackageElement;
+import javax.lang.model.element.TypeElement;
+
+import jdk.javadoc.internal.doclets.formats.html.AbstractMemberWriter;
+import jdk.javadoc.internal.doclets.formats.html.Contents;
+import jdk.javadoc.internal.doclets.formats.html.HtmlConfiguration;
+import jdk.javadoc.internal.doclets.formats.html.SectionName;
+import jdk.javadoc.internal.doclets.toolkit.Content;
+import jdk.javadoc.internal.doclets.toolkit.builders.MemberSummaryBuilder;
+import jdk.javadoc.internal.doclets.toolkit.util.DocFile;
+import jdk.javadoc.internal.doclets.toolkit.util.DocLink;
+import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
+import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
+
+/**
+ * Factory for navigation bar.
+ *
+ * <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>
+ */
+public class Navigation {
+
+ private final HtmlConfiguration configuration;
+ private final Element element;
+ private final Contents contents;
+ private final DocPath path;
+ private final DocPath pathToRoot;
+ private final Links links;
+ private final HtmlTree fixedNavDiv;
+ private final PageMode documentedPage;
+ private Content navLinkModule;
+ private Content navLinkPackage;
+ private Content navLinkClass;
+ private MemberSummaryBuilder memberSummaryBuilder;
+ private boolean displaySummaryModuleDescLink;
+ private boolean displaySummaryModulesLink;
+ private boolean displaySummaryPackagesLink;
+ private boolean displaySummaryServicesLink;
+ private final Map<Position, Deque<Content>> topBottomNavContents;
+ private Content userHeader;
+ private Content userFooter;
+ private final String rowListTitle;
+ private final Content searchLabel;
+ private static final Script FIXED_NAV_SCRIPT = new Script("<!--\n"
+ + "$('.navPadding').css('padding-top', $('.fixedNav').css(\"height\"));\n"
+ + "//-->\n");
+
+ public enum PageMode {
+ CLASS,
+ CONSTANTVALUES,
+ DEPRECATED,
+ DOCFILE,
+ HELP,
+ INDEX,
+ MODULE,
+ OVERVIEW,
+ PACKAGE,
+ SERIALIZEDFORM,
+ TREE,
+ USE;
+ }
+
+ enum Position {
+ BOTTOM("allclasses_navbar_bottom", HtmlConstants.START_OF_BOTTOM_NAVBAR, HtmlConstants.END_OF_BOTTOM_NAVBAR),
+ TOP("allclasses_navbar_top", HtmlConstants.START_OF_TOP_NAVBAR, HtmlConstants.END_OF_TOP_NAVBAR);
+
+ final String allClassesLinkId;
+ final Content startOfNav;
+ final Content endOfNav;
+
+ Position(String allClassesLinkId, Content startOfNav, Content endOfNav) {
+ this.allClassesLinkId = allClassesLinkId;
+ this.startOfNav = startOfNav;
+ this.endOfNav = endOfNav;
+ }
+
+ String allClassesLinkId() {
+ return allClassesLinkId;
+ }
+
+ Content startOfNav() {
+ return startOfNav;
+ }
+
+ Content endOfNav() {
+ return endOfNav;
+ }
+
+ Script allClassesLinkScript() {
+ return new Script("<!--\n"
+ + " allClassesLink = document.getElementById(")
+ .appendStringLiteral(allClassesLinkId)
+ .append(");\n"
+ + " if(window==top) {\n"
+ + " allClassesLink.style.display = \"block\";\n"
+ + " }\n"
+ + " else {\n"
+ + " allClassesLink.style.display = \"none\";\n"
+ + " }\n"
+ + " //-->\n");
+ }
+ }
+
+ /**
+ * Creates a {@code Navigation} object for a specific file, to be written in a specific HTML
+ * version.
+ *
+ * @param element element being documented. null if its not an element documentation page
+ * @param configuration the configuration object
+ * @param fixedNavDiv the fixed navigation for the header navigation
+ * @param page the kind of page being documented
+ * @param path the DocPath object
+ */
+ public Navigation(Element element, HtmlConfiguration configuration, HtmlTree fixedNavDiv,
+ PageMode page, DocPath path) {
+ this.configuration = configuration;
+ this.element = element;
+ this.fixedNavDiv = fixedNavDiv;
+ this.contents = configuration.contents;
+ this.documentedPage = page;
+ this.path = path;
+ this.pathToRoot = path.parent().invert();
+ this.links = new Links(path, configuration.htmlVersion);
+ this.topBottomNavContents = new HashMap<>();
+ this.rowListTitle = configuration.getText("doclet.Navigation");
+ this.searchLabel = configuration.getContent("doclet.search");
+ populateNavContents(Position.TOP);
+ populateNavContents(Position.BOTTOM);
+ }
+
+ /**
+ * Populate the navigation contents for top and bottom navigation
+ *
+ * @param position the position of the navigation bar on the page
+ */
+ private void populateNavContents(Position position) {
+ Deque<Content> queue = new ArrayDeque<>();
+ Content skipNavLinks = configuration.getContent("doclet.Skip_navigation_links");
+ switch (position) {
+ case TOP:
+ queue.addLast(links.createAnchor(SectionName.NAVBAR_TOP));
+ queue.addLast(links.createLink(SectionName.SKIP_NAVBAR_TOP, skipNavLinks,
+ skipNavLinks.toString(), ""));
+ queue.addLast(links.createAnchor(SectionName.NAVBAR_TOP_FIRSTROW));
+ queue.addLast(links.createAnchor(SectionName.SKIP_NAVBAR_TOP));
+ topBottomNavContents.put(position, queue);
+ break;
+ case BOTTOM:
+ queue.addLast(links.createAnchor(SectionName.NAVBAR_BOTTOM));
+ queue.addLast(links.createLink(SectionName.SKIP_NAVBAR_BOTTOM, skipNavLinks,
+ skipNavLinks.toString(), ""));
+ queue.addLast(links.createAnchor(SectionName.NAVBAR_BOTTOM_FIRSTROW));
+ queue.addLast(links.createAnchor(SectionName.SKIP_NAVBAR_BOTTOM));
+ topBottomNavContents.put(position, queue);
+ break;
+ default:
+ break;
+ }
+ }
+
+ public Navigation setNavLinkModule(Content navLinkModule) {
+ this.navLinkModule = navLinkModule;
+ return this;
+ }
+
+ public Navigation setNavLinkPackage(Content navLinkPackage) {
+ this.navLinkPackage = navLinkPackage;
+ return this;
+ }
+
+ public Navigation setNavLinkClass(Content navLinkClass) {
+ this.navLinkClass = navLinkClass;
+ return this;
+ }
+
+ public Navigation setMemberSummaryBuilder(MemberSummaryBuilder memberSummaryBuilder) {
+ this.memberSummaryBuilder = memberSummaryBuilder;
+ return this;
+ }
+
+ public Navigation setDisplaySummaryModuleDescLink(boolean displaySummaryModuleDescLink) {
+ this.displaySummaryModuleDescLink = displaySummaryModuleDescLink;
+ return this;
+ }
+
+ public Navigation setDisplaySummaryModulesLink(boolean displaySummaryModulesLink) {
+ this.displaySummaryModulesLink = displaySummaryModulesLink;
+ return this;
+ }
+
+ public Navigation setDisplaySummaryPackagesLink(boolean displaySummaryPackagesLink) {
+ this.displaySummaryPackagesLink = displaySummaryPackagesLink;
+ return this;
+ }
+
+ public Navigation setDisplaySummaryServicesLink(boolean displaySummaryServicesLink) {
+ this.displaySummaryServicesLink = displaySummaryServicesLink;
+ return this;
+ }
+
+ public Navigation setUserHeader(Content userHeader) {
+ this.userHeader = userHeader;
+ return this;
+ }
+
+ public Navigation setUserFooter(Content userFooter) {
+ this.userFooter = userFooter;
+ return this;
+ }
+
+ /**
+ * Add the links for the main navigation.
+ *
+ * @param tree the content tree to which the main navigation will added
+ */
+ private void addMainNavLinks(Content tree) {
+ switch (documentedPage) {
+ case OVERVIEW:
+ addActivePageLink(tree, contents.overviewLabel, configuration.createoverview);
+ addModuleLink(tree);
+ addPackageLink(tree);
+ addPageLabel(tree, contents.classLabel, true);
+ addPageLabel(tree, contents.useLabel, configuration.classuse);
+ addTreeLink(tree);
+ addDeprecatedLink(tree);
+ addIndexLink(tree);
+ addHelpLink(tree);
+ break;
+ case MODULE:
+ addOverviewLink(tree);
+ addActivePageLink(tree, contents.moduleLabel, configuration.showModules);
+ addPackageLink(tree);
+ addPageLabel(tree, contents.classLabel, true);
+ addPageLabel(tree, contents.useLabel, configuration.classuse);
+ addTreeLink(tree);
+ addDeprecatedLink(tree);
+ addIndexLink(tree);
+ addHelpLink(tree);
+ break;
+ case PACKAGE:
+ addOverviewLink(tree);
+ addModuleOfElementLink(tree);
+ addActivePageLink(tree, contents.packageLabel, true);
+ addPageLabel(tree, contents.classLabel, true);
+ if (configuration.classuse) {
+ addContentToTree(tree, links.createLink(DocPaths.PACKAGE_USE,
+ contents.useLabel, "", ""));
+ }
+ if (configuration.createtree) {
+ addContentToTree(tree, links.createLink(DocPaths.PACKAGE_TREE,
+ contents.treeLabel, "", ""));
+ }
+ addDeprecatedLink(tree);
+ addIndexLink(tree);
+ addHelpLink(tree);
+ break;
+ case CLASS:
+ addOverviewLink(tree);
+ addModuleOfElementLink(tree);
+ addPackageSummaryLink(tree);
+ addActivePageLink(tree, contents.classLabel, true);
+ if (configuration.classuse) {
+ addContentToTree(tree, links.createLink(DocPaths.CLASS_USE.resolve(path.basename()),
+ contents.useLabel));
+ }
+ if (configuration.createtree) {
+ addContentToTree(tree, links.createLink(DocPaths.PACKAGE_TREE,
+ contents.treeLabel, "", ""));
+ }
+ addDeprecatedLink(tree);
+ addIndexLink(tree);
+ addHelpLink(tree);
+ break;
+ case USE:
+ addOverviewLink(tree);
+ addModuleOfElementLink(tree);
+ if (element instanceof PackageElement) {
+ addPackageSummaryLink(tree);
+ addPageLabel(tree, contents.classLabel, true);
+ } else {
+ addPackageOfElementLink(tree);
+ addContentToTree(tree, navLinkClass);
+ }
+ addActivePageLink(tree, contents.useLabel, configuration.classuse);
+ if (element instanceof PackageElement) {
+ addContentToTree(tree, links.createLink(DocPaths.PACKAGE_TREE, contents.treeLabel));
+ } else {
+ addContentToTree(tree, configuration.utils.isEnclosingPackageIncluded((TypeElement) element)
+ ? links.createLink(DocPath.parent.resolve(DocPaths.PACKAGE_TREE), contents.treeLabel)
+ : links.createLink(pathToRoot.resolve(DocPaths.OVERVIEW_TREE), contents.treeLabel));
+ }
+ addDeprecatedLink(tree);
+ addIndexLink(tree);
+ addHelpLink(tree);
+ break;
+ case TREE:
+ addOverviewLink(tree);
+ if (element == null) {
+ addPageLabel(tree, contents.moduleLabel, configuration.showModules);
+ addPageLabel(tree, contents.packageLabel, true);
+ } else {
+ addModuleOfElementLink(tree);
+ addPackageSummaryLink(tree);
+ }
+ addPageLabel(tree, contents.classLabel, true);
+ addPageLabel(tree, contents.useLabel, configuration.classuse);
+ addActivePageLink(tree, contents.treeLabel, configuration.createtree);
+ addDeprecatedLink(tree);
+ addIndexLink(tree);
+ addHelpLink(tree);
+ break;
+ case DEPRECATED:
+ case INDEX:
+ case HELP:
+ addOverviewLink(tree);
+ addModuleLink(tree);
+ addPackageLink(tree);
+ addPageLabel(tree, contents.classLabel, true);
+ addPageLabel(tree, contents.useLabel, configuration.classuse);
+ addTreeLink(tree);
+ if (documentedPage == PageMode.DEPRECATED) {
+ addActivePageLink(tree, contents.deprecatedLabel, !(configuration.nodeprecated
+ || configuration.nodeprecatedlist));
+ } else {
+ addDeprecatedLink(tree);
+ }
+ if (documentedPage == PageMode.INDEX) {
+ addActivePageLink(tree, contents.indexLabel, configuration.createindex);
+ } else {
+ addIndexLink(tree);
+ }
+ if (documentedPage == PageMode.HELP) {
+ addActivePageLink(tree, contents.helpLabel, !configuration.nohelp);
+ } else {
+ addHelpLink(tree);
+ }
+ break;
+ case CONSTANTVALUES:
+ case SERIALIZEDFORM:
+ addOverviewLink(tree);
+ addModuleLink(tree);
+ addPackageLink(tree);
+ addPageLabel(tree, contents.classLabel, true);
+ addPageLabel(tree, contents.useLabel, configuration.classuse);
+ addTreeLink(tree);
+ addDeprecatedLink(tree);
+ addIndexLink(tree);
+ addHelpLink(tree);
+ break;
+ case DOCFILE:
+ addOverviewLink(tree);
+ addModuleOfElementLink(tree);
+ addContentToTree(tree, navLinkPackage);
+ addPageLabel(tree, contents.classLabel, true);
+ addPageLabel(tree, contents.useLabel, configuration.classuse);
+ addTreeLink(tree);
+ addDeprecatedLink(tree);
+ addIndexLink(tree);
+ addHelpLink(tree);
+ break;
+ default:
+ break;
+ }
+ }
+
+ /**
+ * Add the summary links to the sub-navigation.
+ *
+ * @param tree the content tree to which the sub-navigation will added
+ */
+ private void addSummaryLinks(Content tree) {
+ List<Content> listContents = new ArrayList<>();
+ switch (documentedPage) {
+ case CLASS:
+ if (element.getKind() == ElementKind.ANNOTATION_TYPE) {
+ addAnnotationTypeSummaryLink("doclet.navField",
+ VisibleMemberMap.Kind.ANNOTATION_TYPE_FIELDS, listContents);
+ addAnnotationTypeSummaryLink("doclet.navAnnotationTypeRequiredMember",
+ VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_REQUIRED, listContents);
+ addAnnotationTypeSummaryLink("doclet.navAnnotationTypeOptionalMember",
+ VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_OPTIONAL, listContents);
+ } else {
+ TypeElement typeElement = (TypeElement) element;
+ for (VisibleMemberMap.Kind kind : VisibleMemberMap.Kind.summarySet) {
+ if (kind == VisibleMemberMap.Kind.ENUM_CONSTANTS && !configuration.utils.isEnum(typeElement)) {
+ continue;
+ }
+ if (kind == VisibleMemberMap.Kind.CONSTRUCTORS && configuration.utils.isEnum(typeElement)) {
+ continue;
+ }
+ AbstractMemberWriter writer
+ = ((AbstractMemberWriter) memberSummaryBuilder.getMemberSummaryWriter(kind));
+ if (writer == null) {
+ addContentToList(listContents,
+ contents.getContent(VisibleMemberMap.Kind.getNavLinkLabels(kind)));
+ } else {
+ addTypeSummaryLink(memberSummaryBuilder.members(kind),
+ memberSummaryBuilder.getVisibleMemberMap(kind), listContents);
+ }
+ }
+ }
+ if (!listContents.isEmpty()) {
+ Content li = HtmlTree.LI(contents.summaryLabel);
+ li.addContent(Contents.SPACE);
+ tree.addContent(li);
+ addListToNav(listContents, tree);
+ }
+ break;
+ case MODULE:
+ if (displaySummaryModuleDescLink) {
+ addContentToList(listContents,
+ links.createLink(SectionName.MODULE_DESCRIPTION, contents.navModuleDescription));
+ } else {
+ addContentToList(listContents, contents.navModuleDescription);
+ }
+ if (displaySummaryModulesLink) {
+ addContentToList(listContents,
+ links.createLink(SectionName.MODULES, contents.navModules));
+ } else {
+ addContentToList(listContents, contents.navModules);
+ }
+ if (displaySummaryPackagesLink) {
+ addContentToList(listContents,
+ links.createLink(SectionName.PACKAGES, contents.navPackages));
+ } else {
+ addContentToList(listContents, contents.navPackages);
+ }
+ if (displaySummaryServicesLink) {
+ addContentToList(listContents,
+ links.createLink(SectionName.SERVICES, contents.navServices));
+ } else {
+ addContentToList(listContents, contents.navServices);
+ }
+ if (!listContents.isEmpty()) {
+ Content li = HtmlTree.LI(contents.moduleSubNavLabel);
+ li.addContent(Contents.SPACE);
+ tree.addContent(li);
+ addListToNav(listContents, tree);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ /**
+ * Add the navigation summary link.
+ *
+ * @param members members to be linked
+ * @param visibleMemberMap the visible inherited members map
+ * @param listContents the list of contents
+ */
+ private void addTypeSummaryLink(SortedSet<? extends Element> members,
+ VisibleMemberMap visibleMemberMap, List<Content> listContents) {
+ if (!members.isEmpty()) {
+ addTypeSummaryLink(null, visibleMemberMap.kind, true, listContents);
+ return;
+ }
+
+ SortedSet<TypeElement> visibleClasses = visibleMemberMap.getVisibleClasses();
+ for (TypeElement t : visibleClasses) {
+ if (!configuration.getVisibleMemberMap(t, visibleMemberMap.kind).getLeafMembers().isEmpty()) {
+ addTypeSummaryLink(null, visibleMemberMap.kind, true, listContents);
+ return;
+ }
+ }
+ addTypeSummaryLink(null, visibleMemberMap.kind, false, listContents);
+ }
+
+ /**
+ * Add the navigation Type summary link.
+ *
+ * @param typeElement the Type being documented
+ * @param kind the kind of member being documented
+ * @param link true if the members are listed and need to be linked
+ * @param listContents the list of contents to which the summary will be added
+ */
+ private void addTypeSummaryLink(TypeElement typeElement, VisibleMemberMap.Kind kind, boolean link,
+ List<Content> listContents) {
+ switch (kind) {
+ case CONSTRUCTORS:
+ if (link) {
+ addContentToList(listContents, links.createLink(SectionName.CONSTRUCTOR_SUMMARY,
+ contents.navConstructor));
+ } else {
+ addContentToList(listContents, contents.navConstructor);
+ }
+ break;
+ case ENUM_CONSTANTS:
+ if (link) {
+ if (typeElement == null) {
+ addContentToList(listContents, links.createLink(SectionName.ENUM_CONSTANT_SUMMARY,
+ contents.navEnum));
+ } else {
+ addContentToList(listContents, links.createLink(
+ SectionName.ENUM_CONSTANTS_INHERITANCE,
+ configuration.getClassName(typeElement), contents.navEnum));
+ }
+ } else {
+ addContentToList(listContents, contents.navEnum);
+ }
+ break;
+ case FIELDS:
+ if (link) {
+ if (typeElement == null) {
+ addContentToList(listContents,
+ links.createLink(SectionName.FIELD_SUMMARY, contents.navField));
+ } else {
+ addContentToList(listContents, links.createLink(SectionName.FIELDS_INHERITANCE,
+ configuration.getClassName(typeElement), contents.navField));
+ }
+ } else {
+ addContentToList(listContents, contents.navField);
+ }
+ break;
+ case METHODS:
+ if (link) {
+ if (typeElement == null) {
+ addContentToList(listContents,
+ links.createLink(SectionName.METHOD_SUMMARY, contents.navMethod));
+ } else {
+ addContentToList(listContents, links.createLink(SectionName.METHODS_INHERITANCE,
+ configuration.getClassName(typeElement), contents.navMethod));
+ }
+ } else {
+ addContentToList(listContents, contents.navMethod);
+ }
+ break;
+ case INNER_CLASSES:
+ if (link) {
+ if (typeElement == null) {
+ addContentToList(listContents,
+ links.createLink(SectionName.NESTED_CLASS_SUMMARY, contents.navNested));
+ } else {
+ addContentToList(listContents, links.createLink(SectionName.NESTED_CLASSES_INHERITANCE,
+ configuration.utils.getFullyQualifiedName(typeElement), contents.navNested));
+ }
+ } else {
+ addContentToList(listContents, contents.navNested);
+ }
+ break;
+ case PROPERTIES:
+ if (link) {
+ if (typeElement == null) {
+ addContentToList(listContents,
+ links.createLink(SectionName.PROPERTY_SUMMARY, contents.navProperty));
+ } else {
+ addContentToList(listContents, links.createLink(SectionName.PROPERTIES_INHERITANCE,
+ configuration.getClassName(typeElement), contents.navProperty));
+ }
+ } else {
+ addContentToList(listContents, contents.navProperty);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ /**
+ * Add the navigation Type summary link.
+ *
+ * @param label the label to be added
+ * @param type the kind of member being documented
+ * @param listContents the list of contents to which the summary will be added
+ */
+ private void addAnnotationTypeSummaryLink(String label, VisibleMemberMap.Kind type, List<Content> listContents) {
+ AbstractMemberWriter writer = ((AbstractMemberWriter) memberSummaryBuilder.
+ getMemberSummaryWriter(type));
+ if (writer == null) {
+ addContentToList(listContents, contents.getContent(label));
+ } else {
+ boolean link = !memberSummaryBuilder.getVisibleMemberMap(type).noVisibleMembers();
+ switch (type) {
+ case ANNOTATION_TYPE_FIELDS:
+ if (link) {
+ addContentToList(listContents, links.createLink(SectionName.ANNOTATION_TYPE_FIELD_SUMMARY,
+ contents.navField));
+ } else {
+ addContentToList(listContents, contents.navField);
+ }
+ break;
+ case ANNOTATION_TYPE_MEMBER_REQUIRED:
+ if (link) {
+ addContentToList(listContents, links.createLink(
+ SectionName.ANNOTATION_TYPE_REQUIRED_ELEMENT_SUMMARY,
+ contents.navAnnotationTypeRequiredMember));
+ } else {
+ addContentToList(listContents, contents.navAnnotationTypeRequiredMember);
+ }
+ break;
+ case ANNOTATION_TYPE_MEMBER_OPTIONAL:
+ if (link) {
+ addContentToList(listContents, links.createLink(
+ SectionName.ANNOTATION_TYPE_OPTIONAL_ELEMENT_SUMMARY,
+ contents.navAnnotationTypeOptionalMember));
+ } else {
+ addContentToList(listContents, contents.navAnnotationTypeOptionalMember);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ /**
+ * Add the detail links to sub-navigation.
+ *
+ * @param tree the content tree to which the links will be added
+ */
+ private void addDetailLinks(Content tree) {
+ switch (documentedPage) {
+ case CLASS:
+ List<Content> listContents = new ArrayList<>();
+ if (element.getKind() == ElementKind.ANNOTATION_TYPE) {
+ addAnnotationTypeDetailLink(listContents);
+ } else {
+ TypeElement typeElement = (TypeElement) element;
+ for (VisibleMemberMap.Kind kind : VisibleMemberMap.Kind.detailSet) {
+ AbstractMemberWriter writer
+ = ((AbstractMemberWriter) memberSummaryBuilder.
+ getMemberSummaryWriter(kind));
+ if (kind == VisibleMemberMap.Kind.ENUM_CONSTANTS && !configuration.utils.isEnum(typeElement)) {
+ continue;
+ }
+ if (kind == VisibleMemberMap.Kind.CONSTRUCTORS && configuration.utils.isEnum(typeElement)) {
+ continue;
+ }
+ if (writer == null) {
+ addContentToList(listContents, contents.getContent(VisibleMemberMap.Kind.getNavLinkLabels(kind)));
+ } else {
+ addTypeDetailLink(kind, !memberSummaryBuilder.members(kind).isEmpty(), listContents);
+ }
+ }
+ }
+ if (!listContents.isEmpty()) {
+ Content li = HtmlTree.LI(contents.detailLabel);
+ li.addContent(Contents.SPACE);
+ tree.addContent(li);
+ addListToNav(listContents, tree);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ /**
+ * Add the navigation Type detail link.
+ *
+ * @param kind the kind of member being documented
+ * @param link true if the members are listed and need to be linked
+ * @param listContents the list of contents to which the detail will be added.
+ */
+ protected void addTypeDetailLink(VisibleMemberMap.Kind kind, boolean link, List<Content> listContents) {
+ switch (kind) {
+ case CONSTRUCTORS:
+ if (link) {
+ addContentToList(listContents, links.createLink(SectionName.CONSTRUCTOR_DETAIL, contents.navConstructor));
+ } else {
+ addContentToList(listContents, contents.navConstructor);
+ }
+ break;
+ case ENUM_CONSTANTS:
+ if (link) {
+ addContentToList(listContents, links.createLink(SectionName.ENUM_CONSTANT_DETAIL, contents.navEnum));
+ } else {
+ addContentToList(listContents, contents.navEnum);
+ }
+ break;
+ case FIELDS:
+ if (link) {
+ addContentToList(listContents, links.createLink(SectionName.FIELD_DETAIL, contents.navField));
+ } else {
+ addContentToList(listContents, contents.navField);
+ }
+ break;
+ case METHODS:
+ if (link) {
+ addContentToList(listContents, links.createLink(SectionName.METHOD_DETAIL, contents.navMethod));
+ } else {
+ addContentToList(listContents, contents.navMethod);
+ }
+ break;
+ case PROPERTIES:
+ if (link) {
+ addContentToList(listContents, links.createLink(SectionName.PROPERTY_DETAIL, contents.navProperty));
+ } else {
+ addContentToList(listContents, contents.navProperty);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ /**
+ * Add the navigation Annotation Type detail link.
+ *
+ * @param listContents the list of contents to which the annotation detail will be added.
+ */
+ protected void addAnnotationTypeDetailLink(List<Content> listContents) {
+ TypeElement annotationType = (TypeElement) element;
+ AbstractMemberWriter writerField
+ = ((AbstractMemberWriter) memberSummaryBuilder.
+ getMemberSummaryWriter(VisibleMemberMap.Kind.ANNOTATION_TYPE_FIELDS));
+ AbstractMemberWriter writerOptional
+ = ((AbstractMemberWriter) memberSummaryBuilder.
+ getMemberSummaryWriter(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_OPTIONAL));
+ AbstractMemberWriter writerRequired
+ = ((AbstractMemberWriter) memberSummaryBuilder.
+ getMemberSummaryWriter(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_REQUIRED));
+ if (writerField != null) {
+ addAnnotationTypeDetailLink(VisibleMemberMap.Kind.ANNOTATION_TYPE_FIELDS,
+ !configuration.utils.getAnnotationFields(annotationType).isEmpty(),
+ listContents);
+ } else {
+ addContentToList(listContents, contents.navField);
+ }
+ if (writerOptional != null) {
+ addAnnotationTypeDetailLink(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_OPTIONAL,
+ !annotationType.getAnnotationMirrors().isEmpty(), listContents);
+ } else if (writerRequired != null) {
+ addAnnotationTypeDetailLink(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_REQUIRED,
+ !annotationType.getAnnotationMirrors().isEmpty(), listContents);
+ } else {
+ addContentToList(listContents, contents.navAnnotationTypeMember);
+ }
+ }
+
+ /**
+ * Add the navigation Annotation Type detail link.
+ *
+ * @param type the kind of member being documented
+ * @param link true if the member details need to be linked
+ * @param listContents the list of contents to which the annotation detail will be added.
+ */
+ protected void addAnnotationTypeDetailLink(VisibleMemberMap.Kind type, boolean link, List<Content> listContents) {
+ switch (type) {
+ case ANNOTATION_TYPE_FIELDS:
+ if (link) {
+ addContentToList(listContents, links.createLink(SectionName.ANNOTATION_TYPE_FIELD_DETAIL,
+ contents.navField));
+ } else {
+ addContentToList(listContents, contents.navField);
+ }
+ break;
+ case ANNOTATION_TYPE_MEMBER_REQUIRED:
+ case ANNOTATION_TYPE_MEMBER_OPTIONAL:
+ if (link) {
+ addContentToList(listContents, links.createLink(SectionName.ANNOTATION_TYPE_ELEMENT_DETAIL,
+ contents.navAnnotationTypeMember));
+ } else {
+ addContentToList(listContents, contents.navAnnotationTypeMember);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ private void addContentToList(List<Content> listContents, Content tree) {
+ listContents.add(HtmlTree.LI(tree));
+ }
+
+ private void addContentToTree(Content tree, Content content) {
+ tree.addContent(HtmlTree.LI(content));
+ }
+
+ private void addListToNav(List<Content> listContents, Content tree) {
+ int count = 0;
+ for (Content liContent : listContents) {
+ if (count < listContents.size() - 1) {
+ liContent.addContent(Contents.SPACE);
+ liContent.addContent("|");
+ liContent.addContent(Contents.SPACE);
+ }
+ tree.addContent(liContent);
+ count++;
+ }
+ }
+
+ private void addActivePageLink(Content tree, Content label, boolean display) {
+ if (display) {
+ tree.addContent(HtmlTree.LI(HtmlStyle.navBarCell1Rev, label));
+ }
+ }
+
+ private void addPageLabel(Content tree, Content label, boolean display) {
+ if (display) {
+ tree.addContent(HtmlTree.LI(label));
+ }
+ }
+
+ private void addOverviewLink(Content tree) {
+ if (configuration.createoverview) {
+ tree.addContent(HtmlTree.LI(links.createLink(pathToRoot.resolve(DocPaths.overviewSummary(configuration.frames)),
+ contents.overviewLabel, "", "")));
+ }
+ }
+
+ private void addModuleLink(Content tree) {
+ if (configuration.showModules) {
+ if (configuration.modules.size() == 1) {
+ ModuleElement mdle = configuration.modules.first();
+ boolean included = configuration.utils.isIncluded(mdle);
+ tree.addContent(HtmlTree.LI((included)
+ ? links.createLink(pathToRoot.resolve(configuration.docPaths.moduleSummary(mdle)), contents.moduleLabel, "", "")
+ : contents.moduleLabel));
+ } else if (!configuration.modules.isEmpty()) {
+ addPageLabel(tree, contents.moduleLabel, true);
+ }
+ }
+ }
+
+ private void addModuleOfElementLink(Content tree) {
+ if (configuration.showModules) {
+ tree.addContent(HtmlTree.LI(navLinkModule));
+ }
+ }
+
+ private void addPackageLink(Content tree) {
+ if (configuration.packages.size() == 1) {
+ PackageElement packageElement = configuration.packages.first();
+ boolean included = packageElement != null && configuration.utils.isIncluded(packageElement);
+ if (!included) {
+ for (PackageElement p : configuration.packages) {
+ if (p.equals(packageElement)) {
+ included = true;
+ break;
+ }
+ }
+ }
+ if (included || packageElement == null) {
+ tree.addContent(HtmlTree.LI(links.createLink(
+ pathToRoot.resolve(configuration.docPaths.forPackage(packageElement).resolve(DocPaths.PACKAGE_SUMMARY)),
+ contents.packageLabel)));
+ } else {
+ DocLink crossPkgLink = configuration.extern.getExternalLink(
+ configuration.utils.getPackageName(packageElement), pathToRoot,
+ DocPaths.PACKAGE_SUMMARY.getPath());
+ if (crossPkgLink != null) {
+ tree.addContent(HtmlTree.LI(links.createLink(crossPkgLink, contents.packageLabel)));
+ } else {
+ tree.addContent(HtmlTree.LI(contents.packageLabel));
+ }
+ }
+ } else if (!configuration.packages.isEmpty()) {
+ addPageLabel(tree, contents.packageLabel, true);
+ }
+ }
+
+ private void addPackageOfElementLink(Content tree) {
+ tree.addContent(HtmlTree.LI(links.createLink(DocPath.parent.resolve(DocPaths.PACKAGE_SUMMARY),
+ contents.packageLabel)));
+ }
+
+ private void addPackageSummaryLink(Content tree) {
+ tree.addContent(HtmlTree.LI(links.createLink(DocPaths.PACKAGE_SUMMARY, contents.packageLabel)));
+ }
+
+ private void addTreeLink(Content tree) {
+ if (configuration.createtree) {
+ List<PackageElement> packages = new ArrayList<>(configuration.getSpecifiedPackageElements());
+ DocPath docPath = packages.size() == 1 && configuration.getSpecifiedTypeElements().isEmpty()
+ ? pathToRoot.resolve(configuration.docPaths.forPackage(packages.get(0)).resolve(DocPaths.PACKAGE_TREE))
+ : pathToRoot.resolve(DocPaths.OVERVIEW_TREE);
+ tree.addContent(HtmlTree.LI(links.createLink(docPath, contents.treeLabel, "", "")));
+ }
+ }
+
+ private void addDeprecatedLink(Content tree) {
+ if (!(configuration.nodeprecated || configuration.nodeprecatedlist)) {
+ tree.addContent(HtmlTree.LI(links.createLink(pathToRoot.resolve(DocPaths.DEPRECATED_LIST),
+ contents.deprecatedLabel, "", "")));
+ }
+ }
+
+ private void addIndexLink(Content tree) {
+ if (configuration.createindex) {
+ tree.addContent(HtmlTree.LI(links.createLink(pathToRoot.resolve(
+ (configuration.splitindex
+ ? DocPaths.INDEX_FILES.resolve(DocPaths.indexN(1))
+ : DocPaths.INDEX_ALL)),
+ contents.indexLabel, "", "")));
+ }
+ }
+
+ private void addHelpLink(Content tree) {
+ if (!configuration.nohelp) {
+ String helpfile = configuration.helpfile;
+ DocPath helpfilenm;
+ if (helpfile.isEmpty()) {
+ helpfilenm = DocPaths.HELP_DOC;
+ } else {
+ DocFile file = DocFile.createFileForInput(configuration, helpfile);
+ helpfilenm = DocPath.create(file.getName());
+ }
+ tree.addContent(HtmlTree.LI(links.createLink(pathToRoot.resolve(helpfilenm),
+ contents.helpLabel, "", "")));
+ }
+ }
+
+ /**
+ * Add "FRAMES" link, to switch to the frame version of the output.
+ *
+ * @param tree the content tree to which the link will be added
+ */
+ private void addNavShowLists(Content tree) {
+ DocLink dl = new DocLink(pathToRoot.resolve(DocPaths.INDEX), path.getPath(), null);
+ Content framesContent = links.createLink(dl, contents.framesLabel, "", "_top");
+ tree.addContent(HtmlTree.LI(framesContent));
+ }
+
+ /**
+ * Add "NO FRAMES" link, to switch to the non-frame version of the output.
+ *
+ * @param tree the content tree to which the link will be added
+ */
+ private void addNavHideLists(Content tree) {
+ Content noFramesContent = links.createLink(path.basename(), contents.noFramesLabel, "", "_top");
+ tree.addContent(HtmlTree.LI(noFramesContent));
+ }
+
+ private void addNavLinkClassIndex(Content tree) {
+ Content allClassesContent = links.createLink(pathToRoot.resolve(
+ DocPaths.AllClasses(configuration.frames)),
+ contents.allClassesLabel, "", "");
+ tree.addContent(HtmlTree.LI(allClassesContent));
+ }
+
+ private void addSearch(Content tree) {
+ String searchValueId = "search";
+ String reset = "reset";
+ HtmlTree inputText = HtmlTree.INPUT("text", searchValueId, searchValueId);
+ HtmlTree inputReset = HtmlTree.INPUT(reset, reset, reset);
+ HtmlTree liInput = HtmlTree.LI(HtmlTree.LABEL(searchValueId, searchLabel));
+ liInput.addContent(inputText);
+ liInput.addContent(inputReset);
+ HtmlTree ulSearch = HtmlTree.UL(HtmlStyle.navListSearch, liInput);
+ tree.addContent(ulSearch);
+ }
+
+ private void addAllClassesLinkScript(Content tree, boolean top) {
+ Content div = HtmlTree.DIV(top
+ ? Position.TOP.allClassesLinkScript().asContent()
+ : Position.BOTTOM.allClassesLinkScript().asContent());
+ Content div_noscript = HtmlTree.DIV(contents.noScriptMessage);
+ Content noScript = HtmlTree.NOSCRIPT(div_noscript);
+ div.addContent(noScript);
+ tree.addContent(div);
+ }
+
+ private void addFixedNavScript(Content tree) {
+ tree.addContent(FIXED_NAV_SCRIPT.asContent());
+ }
+
+ /**
+ * Get the navigation content.
+ *
+ * @param top true if the top navigation bar is to be printed
+ * @return the navigation contents
+ */
+ public Content getContent(boolean top) {
+ Content contentTree = new ContentBuilder();
+ if (!configuration.nonavbar) {
+ Deque<Content> queue;
+ Content tree = (configuration.htmlVersion == HtmlVersion.HTML5)
+ ? HtmlTree.NAV()
+ : contentTree;
+ HtmlTree navDiv = new HtmlTree(HtmlTag.DIV);
+ if (top) {
+ queue = topBottomNavContents.get(Position.TOP);
+ fixedNavDiv.addContent(Position.TOP.startOfNav());
+ navDiv.setStyle(HtmlStyle.topNav);
+ } else {
+ queue = topBottomNavContents.get(Position.BOTTOM);
+ tree.addContent(Position.BOTTOM.startOfNav());
+ navDiv.setStyle(HtmlStyle.bottomNav);
+ }
+ navDiv.addContent(queue.poll());
+ HtmlTree skipLinkDiv = HtmlTree.DIV(HtmlStyle.skipNav, queue.poll());
+ navDiv.addContent(skipLinkDiv);
+ navDiv.addContent(queue.poll());
+ HtmlTree navList = new HtmlTree(HtmlTag.UL);
+ navList.setStyle(HtmlStyle.navList);
+ navList.addAttr(HtmlAttr.TITLE, rowListTitle);
+ fixedNavDiv.setStyle(HtmlStyle.fixedNav);
+ addMainNavLinks(navList);
+ navDiv.addContent(navList);
+ Content aboutDiv = HtmlTree.DIV(HtmlStyle.aboutLanguage, top ? userHeader : userFooter);
+ navDiv.addContent(aboutDiv);
+ if (top) {
+ fixedNavDiv.addContent(navDiv);
+ } else {
+ tree.addContent(navDiv);
+ }
+ HtmlTree subDiv = new HtmlTree(HtmlTag.DIV);
+ subDiv.setStyle(HtmlStyle.subNav);
+ HtmlTree ulFrames = new HtmlTree(HtmlTag.UL);
+ ulFrames.setStyle(HtmlStyle.navList);
+ if (!configuration.nonavbar) {
+ if (configuration.frames) {
+ addNavShowLists(ulFrames);
+ addNavHideLists(ulFrames);
+ }
+ }
+ subDiv.addContent(ulFrames);
+ HtmlTree ulAllClasses = new HtmlTree(HtmlTag.UL);
+ ulAllClasses.setStyle(HtmlStyle.navList);
+ ulAllClasses.addAttr(HtmlAttr.ID, top
+ ? Position.TOP.allClassesLinkId()
+ : Position.BOTTOM.allClassesLinkId());
+ addNavLinkClassIndex(ulAllClasses);
+ subDiv.addContent(ulAllClasses);
+ if (top && configuration.createindex) {
+ addSearch(subDiv);
+ }
+ addAllClassesLinkScript(subDiv, top);
+ HtmlTree div = new HtmlTree(HtmlTag.DIV);
+ // Add the summary links if present.
+ HtmlTree ulNavSummary = new HtmlTree(HtmlTag.UL);
+ ulNavSummary.setStyle(HtmlStyle.subNavList);
+ addSummaryLinks(ulNavSummary);
+ div.addContent(ulNavSummary);
+ // Add the detail links if present.
+ HtmlTree ulNavDetail = new HtmlTree(HtmlTag.UL);
+ ulNavDetail.setStyle(HtmlStyle.subNavList);
+ addDetailLinks(ulNavDetail);
+ div.addContent(ulNavDetail);
+ subDiv.addContent(div);
+ subDiv.addContent(queue.poll());
+ if (top) {
+ fixedNavDiv.addContent(subDiv);
+ fixedNavDiv.addContent(Position.TOP.endOfNav());
+ tree.addContent(fixedNavDiv);
+ HtmlTree paddingDiv = HtmlTree.DIV(HtmlStyle.navPadding, Contents.SPACE);
+ tree.addContent(paddingDiv);
+ addFixedNavScript(tree);
+ } else {
+ tree.addContent(subDiv);
+ tree.addContent(Position.BOTTOM.endOfNav());
+ }
+ return tree;
+ }
+ return contentTree;
+ }
+}