1 /* 2 * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package jdk.javadoc.internal.doclets.formats.html; 26 27 import java.util.ArrayList; 28 import java.util.List; 29 import java.util.Set; 30 import java.util.SortedSet; 31 32 import javax.lang.model.element.Element; 33 import javax.lang.model.element.ElementKind; 34 import javax.lang.model.element.ModuleElement; 35 import javax.lang.model.element.PackageElement; 36 import javax.lang.model.element.TypeElement; 37 38 import jdk.javadoc.internal.doclets.formats.html.markup.Comment; 39 import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; 40 import jdk.javadoc.internal.doclets.formats.html.markup.Entity; 41 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr; 42 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; 43 import jdk.javadoc.internal.doclets.formats.html.markup.TagName; 44 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; 45 import jdk.javadoc.internal.doclets.formats.html.markup.Links; 46 import jdk.javadoc.internal.doclets.toolkit.Content; 47 import jdk.javadoc.internal.doclets.toolkit.builders.MemberSummaryBuilder; 48 import jdk.javadoc.internal.doclets.toolkit.util.DocFile; 49 import jdk.javadoc.internal.doclets.toolkit.util.DocLink; 50 import jdk.javadoc.internal.doclets.toolkit.util.DocPath; 51 import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; 52 import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable; 53 54 import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*; 55 56 /** 57 * Factory for navigation bar. 58 * 59 * <p> 60 * <b>This is NOT part of any supported API. If you write code that depends on this, you do so at 61 * your own risk. This code and its internal interfaces are subject to change or deletion without 62 * notice.</b> 63 */ 64 public class Navigation { 65 66 private final HtmlConfiguration configuration; 67 private final HtmlOptions options; 68 private final Element element; 69 private final Contents contents; 70 private final DocPath path; 71 private final DocPath pathToRoot; 72 private final Links links; 73 private final PageMode documentedPage; 74 private Content navLinkModule; 75 private Content navLinkPackage; 76 private Content navLinkClass; 77 private MemberSummaryBuilder memberSummaryBuilder; 78 private boolean displaySummaryModuleDescLink; 79 private boolean displaySummaryModulesLink; 80 private boolean displaySummaryPackagesLink; 81 private boolean displaySummaryServicesLink; 82 private Content userHeader; 83 private Content userFooter; 84 private final String rowListTitle; 85 private final Content searchLabel; 86 87 private static final Content EMPTY_COMMENT = new Comment(" "); 88 89 public enum PageMode { 90 ALL_CLASSES, 91 ALL_PACKAGES, 92 CLASS, 93 CONSTANT_VALUES, 94 DEPRECATED, 95 DOC_FILE, 96 HELP, 97 INDEX, 98 MODULE, 99 OVERVIEW, 100 PACKAGE, 101 SERIALIZED_FORM, 102 SYSTEM_PROPERTIES, 103 TREE, 104 USE; 105 } 106 107 enum Position { 108 BOTTOM(MarkerComments.START_OF_BOTTOM_NAVBAR, MarkerComments.END_OF_BOTTOM_NAVBAR), 109 TOP(MarkerComments.START_OF_TOP_NAVBAR, MarkerComments.END_OF_TOP_NAVBAR); 110 111 final Content startOfNav; 112 final Content endOfNav; 113 Position(Content startOfNav, Content endOfNav)114 Position(Content startOfNav, Content endOfNav) { 115 this.startOfNav = startOfNav; 116 this.endOfNav = endOfNav; 117 } 118 startOfNav()119 Content startOfNav() { 120 return startOfNav; 121 } 122 endOfNav()123 Content endOfNav() { 124 return endOfNav; 125 } 126 } 127 128 /** 129 * Creates a {@code Navigation} object for a specific file, to be written in a specific HTML 130 * version. 131 * 132 * @param element element being documented. null if its not an element documentation page 133 * @param configuration the configuration object 134 * @param page the kind of page being documented 135 * @param path the DocPath object 136 */ Navigation(Element element, HtmlConfiguration configuration, PageMode page, DocPath path)137 public Navigation(Element element, HtmlConfiguration configuration, PageMode page, DocPath path) { 138 this.configuration = configuration; 139 this.options = configuration.getOptions(); 140 this.element = element; 141 this.contents = configuration.contents; 142 this.documentedPage = page; 143 this.path = path; 144 this.pathToRoot = path.parent().invert(); 145 this.links = new Links(path); 146 this.rowListTitle = configuration.getDocResources().getText("doclet.Navigation"); 147 this.searchLabel = contents.getContent("doclet.search"); 148 } 149 setNavLinkModule(Content navLinkModule)150 public Navigation setNavLinkModule(Content navLinkModule) { 151 this.navLinkModule = navLinkModule; 152 return this; 153 } 154 setNavLinkPackage(Content navLinkPackage)155 public Navigation setNavLinkPackage(Content navLinkPackage) { 156 this.navLinkPackage = navLinkPackage; 157 return this; 158 } 159 setNavLinkClass(Content navLinkClass)160 public Navigation setNavLinkClass(Content navLinkClass) { 161 this.navLinkClass = navLinkClass; 162 return this; 163 } 164 setMemberSummaryBuilder(MemberSummaryBuilder memberSummaryBuilder)165 public Navigation setMemberSummaryBuilder(MemberSummaryBuilder memberSummaryBuilder) { 166 this.memberSummaryBuilder = memberSummaryBuilder; 167 return this; 168 } 169 setDisplaySummaryModuleDescLink(boolean displaySummaryModuleDescLink)170 public Navigation setDisplaySummaryModuleDescLink(boolean displaySummaryModuleDescLink) { 171 this.displaySummaryModuleDescLink = displaySummaryModuleDescLink; 172 return this; 173 } 174 setDisplaySummaryModulesLink(boolean displaySummaryModulesLink)175 public Navigation setDisplaySummaryModulesLink(boolean displaySummaryModulesLink) { 176 this.displaySummaryModulesLink = displaySummaryModulesLink; 177 return this; 178 } 179 setDisplaySummaryPackagesLink(boolean displaySummaryPackagesLink)180 public Navigation setDisplaySummaryPackagesLink(boolean displaySummaryPackagesLink) { 181 this.displaySummaryPackagesLink = displaySummaryPackagesLink; 182 return this; 183 } 184 setDisplaySummaryServicesLink(boolean displaySummaryServicesLink)185 public Navigation setDisplaySummaryServicesLink(boolean displaySummaryServicesLink) { 186 this.displaySummaryServicesLink = displaySummaryServicesLink; 187 return this; 188 } 189 setUserHeader(Content userHeader)190 public Navigation setUserHeader(Content userHeader) { 191 this.userHeader = userHeader; 192 return this; 193 } 194 setUserFooter(Content userFooter)195 public Navigation setUserFooter(Content userFooter) { 196 this.userFooter = userFooter; 197 return this; 198 } 199 200 /** 201 * Add the links for the main navigation. 202 * 203 * @param tree the content tree to which the main navigation will added 204 */ addMainNavLinks(Content tree)205 private void addMainNavLinks(Content tree) { 206 switch (documentedPage) { 207 case OVERVIEW: 208 addActivePageLink(tree, contents.overviewLabel, options.createOverview()); 209 addModuleLink(tree); 210 addPackageLink(tree); 211 addPageLabel(tree, contents.classLabel, true); 212 addPageLabel(tree, contents.useLabel, options.classUse()); 213 addTreeLink(tree); 214 addDeprecatedLink(tree); 215 addIndexLink(tree); 216 addHelpLink(tree); 217 break; 218 case MODULE: 219 addOverviewLink(tree); 220 addActivePageLink(tree, contents.moduleLabel, configuration.showModules); 221 addPackageLink(tree); 222 addPageLabel(tree, contents.classLabel, true); 223 addPageLabel(tree, contents.useLabel, options.classUse()); 224 addTreeLink(tree); 225 addDeprecatedLink(tree); 226 addIndexLink(tree); 227 addHelpLink(tree); 228 break; 229 case PACKAGE: 230 addOverviewLink(tree); 231 addModuleOfElementLink(tree); 232 addActivePageLink(tree, contents.packageLabel, true); 233 addPageLabel(tree, contents.classLabel, true); 234 if (options.classUse()) { 235 addContentToTree(tree, links.createLink(DocPaths.PACKAGE_USE, 236 contents.useLabel, "", "")); 237 } 238 if (options.createTree()) { 239 addContentToTree(tree, links.createLink(DocPaths.PACKAGE_TREE, 240 contents.treeLabel, "", "")); 241 } 242 addDeprecatedLink(tree); 243 addIndexLink(tree); 244 addHelpLink(tree); 245 break; 246 case CLASS: 247 addOverviewLink(tree); 248 addModuleOfElementLink(tree); 249 addPackageSummaryLink(tree); 250 addActivePageLink(tree, contents.classLabel, true); 251 if (options.classUse()) { 252 addContentToTree(tree, links.createLink(DocPaths.CLASS_USE.resolve(path.basename()), 253 contents.useLabel)); 254 } 255 if (options.createTree()) { 256 addContentToTree(tree, links.createLink(DocPaths.PACKAGE_TREE, 257 contents.treeLabel, "", "")); 258 } 259 addDeprecatedLink(tree); 260 addIndexLink(tree); 261 addHelpLink(tree); 262 break; 263 case USE: 264 addOverviewLink(tree); 265 addModuleOfElementLink(tree); 266 if (element instanceof PackageElement) { 267 addPackageSummaryLink(tree); 268 addPageLabel(tree, contents.classLabel, true); 269 } else { 270 addPackageOfElementLink(tree); 271 addContentToTree(tree, navLinkClass); 272 } 273 addActivePageLink(tree, contents.useLabel, options.classUse()); 274 if (element instanceof PackageElement) { 275 addContentToTree(tree, links.createLink(DocPaths.PACKAGE_TREE, contents.treeLabel)); 276 } else { 277 addContentToTree(tree, configuration.utils.isEnclosingPackageIncluded((TypeElement) element) 278 ? links.createLink(DocPath.parent.resolve(DocPaths.PACKAGE_TREE), contents.treeLabel) 279 : links.createLink(pathToRoot.resolve(DocPaths.OVERVIEW_TREE), contents.treeLabel)); 280 } 281 addDeprecatedLink(tree); 282 addIndexLink(tree); 283 addHelpLink(tree); 284 break; 285 case TREE: 286 addOverviewLink(tree); 287 if (element == null) { 288 addPageLabel(tree, contents.moduleLabel, configuration.showModules); 289 addPageLabel(tree, contents.packageLabel, true); 290 } else { 291 addModuleOfElementLink(tree); 292 addPackageSummaryLink(tree); 293 } 294 addPageLabel(tree, contents.classLabel, true); 295 addPageLabel(tree, contents.useLabel, options.classUse()); 296 addActivePageLink(tree, contents.treeLabel, options.createTree()); 297 addDeprecatedLink(tree); 298 addIndexLink(tree); 299 addHelpLink(tree); 300 break; 301 case DEPRECATED: 302 case INDEX: 303 case HELP: 304 addOverviewLink(tree); 305 addModuleLink(tree); 306 addPackageLink(tree); 307 addPageLabel(tree, contents.classLabel, true); 308 addPageLabel(tree, contents.useLabel, options.classUse()); 309 addTreeLink(tree); 310 if (documentedPage == PageMode.DEPRECATED) { 311 addActivePageLink(tree, contents.deprecatedLabel, !(options.noDeprecated() 312 || options.noDeprecatedList())); 313 } else { 314 addDeprecatedLink(tree); 315 } 316 if (documentedPage == PageMode.INDEX) { 317 addActivePageLink(tree, contents.indexLabel, options.createIndex()); 318 } else { 319 addIndexLink(tree); 320 } 321 if (documentedPage == PageMode.HELP) { 322 addActivePageLink(tree, contents.helpLabel, !options.noHelp()); 323 } else { 324 addHelpLink(tree); 325 } 326 break; 327 case ALL_CLASSES: 328 case ALL_PACKAGES: 329 case CONSTANT_VALUES: 330 case SERIALIZED_FORM: 331 case SYSTEM_PROPERTIES: 332 addOverviewLink(tree); 333 addModuleLink(tree); 334 addPackageLink(tree); 335 addPageLabel(tree, contents.classLabel, true); 336 addPageLabel(tree, contents.useLabel, options.classUse()); 337 addTreeLink(tree); 338 addDeprecatedLink(tree); 339 addIndexLink(tree); 340 addHelpLink(tree); 341 break; 342 case DOC_FILE: 343 addOverviewLink(tree); 344 addModuleOfElementLink(tree); 345 addContentToTree(tree, navLinkPackage); 346 addPageLabel(tree, contents.classLabel, true); 347 addPageLabel(tree, contents.useLabel, options.classUse()); 348 addTreeLink(tree); 349 addDeprecatedLink(tree); 350 addIndexLink(tree); 351 addHelpLink(tree); 352 break; 353 default: 354 break; 355 } 356 } 357 358 /** 359 * Add the summary links to the sub-navigation. 360 * 361 * @param tree the content tree to which the sub-navigation will added 362 */ addSummaryLinks(Content tree)363 private void addSummaryLinks(Content tree) { 364 List<Content> listContents = new ArrayList<>(); 365 switch (documentedPage) { 366 case CLASS: 367 if (element.getKind() == ElementKind.ANNOTATION_TYPE) { 368 addAnnotationTypeSummaryLink("doclet.navField", 369 FIELDS, listContents); 370 addAnnotationTypeSummaryLink("doclet.navAnnotationTypeRequiredMember", 371 ANNOTATION_TYPE_MEMBER_REQUIRED, listContents); 372 addAnnotationTypeSummaryLink("doclet.navAnnotationTypeOptionalMember", 373 ANNOTATION_TYPE_MEMBER_OPTIONAL, listContents); 374 } else { 375 TypeElement typeElement = (TypeElement) element; 376 for (VisibleMemberTable.Kind kind : summarySet) { 377 if (kind == ENUM_CONSTANTS && !configuration.utils.isEnum(typeElement)) { 378 continue; 379 } 380 if (kind == CONSTRUCTORS && configuration.utils.isEnum(typeElement)) { 381 continue; 382 } 383 AbstractMemberWriter writer 384 = ((AbstractMemberWriter) memberSummaryBuilder.getMemberSummaryWriter(kind)); 385 if (writer == null) { 386 addContentToList(listContents, contents.getNavLinkLabelContent(kind)); 387 } else { 388 addTypeSummaryLink(memberSummaryBuilder.members(kind), 389 memberSummaryBuilder.getVisibleMemberTable(), 390 kind, listContents); 391 } 392 } 393 } 394 if (!listContents.isEmpty()) { 395 Content li = HtmlTree.LI(contents.summaryLabel); 396 li.add(Entity.NO_BREAK_SPACE); 397 tree.add(li); 398 addListToNav(listContents, tree); 399 } 400 break; 401 case MODULE: 402 if (displaySummaryModuleDescLink) { 403 addContentToList(listContents, 404 links.createLink(SectionName.MODULE_DESCRIPTION, contents.navModuleDescription)); 405 } else { 406 addContentToList(listContents, contents.navModuleDescription); 407 } 408 if (displaySummaryModulesLink) { 409 addContentToList(listContents, 410 links.createLink(SectionName.MODULES, contents.navModules)); 411 } else { 412 addContentToList(listContents, contents.navModules); 413 } 414 if (displaySummaryPackagesLink) { 415 addContentToList(listContents, 416 links.createLink(SectionName.PACKAGES, contents.navPackages)); 417 } else { 418 addContentToList(listContents, contents.navPackages); 419 } 420 if (displaySummaryServicesLink) { 421 addContentToList(listContents, 422 links.createLink(SectionName.SERVICES, contents.navServices)); 423 } else { 424 addContentToList(listContents, contents.navServices); 425 } 426 if (!listContents.isEmpty()) { 427 Content li = HtmlTree.LI(contents.moduleSubNavLabel); 428 li.add(Entity.NO_BREAK_SPACE); 429 tree.add(li); 430 addListToNav(listContents, tree); 431 } 432 break; 433 default: 434 break; 435 } 436 } 437 438 /** 439 * Add the navigation summary link. 440 * 441 * @param members members to be linked 442 * @param vmt the visible member table 443 * @param kind the visible member kind 444 * @param listContents the list of contents 445 */ addTypeSummaryLink(SortedSet<? extends Element> members, VisibleMemberTable vmt, VisibleMemberTable.Kind kind, List<Content> listContents)446 private void addTypeSummaryLink(SortedSet<? extends Element> members, 447 VisibleMemberTable vmt, 448 VisibleMemberTable.Kind kind, List<Content> listContents) { 449 if (!members.isEmpty()) { 450 addTypeSummaryLink(null, kind, true, listContents); 451 return; 452 } 453 Set<TypeElement> visibleClasses = vmt.getVisibleTypeElements(); 454 for (TypeElement t : visibleClasses) { 455 if (configuration.getVisibleMemberTable(t).hasVisibleMembers(kind)) { 456 addTypeSummaryLink(null, kind, true, listContents); 457 return; 458 } 459 } 460 addTypeSummaryLink(null, kind, false, listContents); 461 } 462 463 /** 464 * Add the navigation Type summary link. 465 * 466 * @param typeElement the Type being documented 467 * @param kind the kind of member being documented 468 * @param link true if the members are listed and need to be linked 469 * @param listContents the list of contents to which the summary will be added 470 */ addTypeSummaryLink(TypeElement typeElement, VisibleMemberTable.Kind kind, boolean link, List<Content> listContents)471 private void addTypeSummaryLink(TypeElement typeElement, VisibleMemberTable.Kind kind, boolean link, 472 List<Content> listContents) { 473 switch (kind) { 474 case CONSTRUCTORS: 475 if (link) { 476 addContentToList(listContents, links.createLink(SectionName.CONSTRUCTOR_SUMMARY, 477 contents.navConstructor)); 478 } else { 479 addContentToList(listContents, contents.navConstructor); 480 } 481 break; 482 case ENUM_CONSTANTS: 483 if (link) { 484 if (typeElement == null) { 485 addContentToList(listContents, links.createLink(SectionName.ENUM_CONSTANT_SUMMARY, 486 contents.navEnum)); 487 } else { 488 addContentToList(listContents, links.createLink( 489 SectionName.ENUM_CONSTANTS_INHERITANCE, 490 configuration.getClassName(typeElement), contents.navEnum)); 491 } 492 } else { 493 addContentToList(listContents, contents.navEnum); 494 } 495 break; 496 case FIELDS: 497 if (link) { 498 if (typeElement == null) { 499 addContentToList(listContents, 500 links.createLink(SectionName.FIELD_SUMMARY, contents.navField)); 501 } else { 502 addContentToList(listContents, links.createLink(SectionName.FIELDS_INHERITANCE, 503 configuration.getClassName(typeElement), contents.navField)); 504 } 505 } else { 506 addContentToList(listContents, contents.navField); 507 } 508 break; 509 case METHODS: 510 if (link) { 511 if (typeElement == null) { 512 addContentToList(listContents, 513 links.createLink(SectionName.METHOD_SUMMARY, contents.navMethod)); 514 } else { 515 addContentToList(listContents, links.createLink(SectionName.METHODS_INHERITANCE, 516 configuration.getClassName(typeElement), contents.navMethod)); 517 } 518 } else { 519 addContentToList(listContents, contents.navMethod); 520 } 521 break; 522 case INNER_CLASSES: 523 if (link) { 524 if (typeElement == null) { 525 addContentToList(listContents, 526 links.createLink(SectionName.NESTED_CLASS_SUMMARY, contents.navNested)); 527 } else { 528 addContentToList(listContents, links.createLink(SectionName.NESTED_CLASSES_INHERITANCE, 529 configuration.utils.getFullyQualifiedName(typeElement), contents.navNested)); 530 } 531 } else { 532 addContentToList(listContents, contents.navNested); 533 } 534 break; 535 case PROPERTIES: 536 if (link) { 537 if (typeElement == null) { 538 addContentToList(listContents, 539 links.createLink(SectionName.PROPERTY_SUMMARY, contents.navProperty)); 540 } else { 541 addContentToList(listContents, links.createLink(SectionName.PROPERTIES_INHERITANCE, 542 configuration.getClassName(typeElement), contents.navProperty)); 543 } 544 } else { 545 addContentToList(listContents, contents.navProperty); 546 } 547 break; 548 default: 549 break; 550 } 551 } 552 553 /** 554 * Add the navigation Type summary link. 555 * 556 * @param label the label to be added 557 * @param kind the kind of member being documented 558 * @param listContents the list of contents to which the summary will be added 559 */ addAnnotationTypeSummaryLink(String label, VisibleMemberTable.Kind kind, List<Content> listContents)560 private void addAnnotationTypeSummaryLink(String label, VisibleMemberTable.Kind kind, List<Content> listContents) { 561 AbstractMemberWriter writer = ((AbstractMemberWriter) memberSummaryBuilder. 562 getMemberSummaryWriter(kind)); 563 if (writer == null) { 564 addContentToList(listContents, contents.getContent(label)); 565 } else { 566 boolean link = memberSummaryBuilder.getVisibleMemberTable().hasVisibleMembers(kind); 567 switch (kind) { 568 case FIELDS: 569 if (link) { 570 addContentToList(listContents, links.createLink(SectionName.FIELD_SUMMARY, 571 contents.navField)); 572 } else { 573 addContentToList(listContents, contents.navField); 574 } 575 break; 576 case ANNOTATION_TYPE_MEMBER_REQUIRED: 577 if (link) { 578 addContentToList(listContents, links.createLink( 579 SectionName.ANNOTATION_TYPE_REQUIRED_ELEMENT_SUMMARY, 580 contents.navAnnotationTypeRequiredMember)); 581 } else { 582 addContentToList(listContents, contents.navAnnotationTypeRequiredMember); 583 } 584 break; 585 case ANNOTATION_TYPE_MEMBER_OPTIONAL: 586 if (link) { 587 addContentToList(listContents, links.createLink( 588 SectionName.ANNOTATION_TYPE_OPTIONAL_ELEMENT_SUMMARY, 589 contents.navAnnotationTypeOptionalMember)); 590 } else { 591 addContentToList(listContents, contents.navAnnotationTypeOptionalMember); 592 } 593 break; 594 default: 595 break; 596 } 597 } 598 } 599 600 /** 601 * Add the detail links to sub-navigation. 602 * 603 * @param tree the content tree to which the links will be added 604 */ addDetailLinks(Content tree)605 private void addDetailLinks(Content tree) { 606 switch (documentedPage) { 607 case CLASS: 608 List<Content> listContents = new ArrayList<>(); 609 if (element.getKind() == ElementKind.ANNOTATION_TYPE) { 610 addAnnotationTypeDetailLink(listContents); 611 } else { 612 TypeElement typeElement = (TypeElement) element; 613 for (VisibleMemberTable.Kind kind : detailSet) { 614 AbstractMemberWriter writer 615 = ((AbstractMemberWriter) memberSummaryBuilder. 616 getMemberSummaryWriter(kind)); 617 if (kind == ENUM_CONSTANTS && !configuration.utils.isEnum(typeElement)) { 618 continue; 619 } 620 if (kind == CONSTRUCTORS && configuration.utils.isEnum(typeElement)) { 621 continue; 622 } 623 if (writer == null) { 624 addContentToList(listContents, contents.getNavLinkLabelContent(kind)); 625 } else { 626 addTypeDetailLink(kind, memberSummaryBuilder.hasMembers(kind), listContents); 627 } 628 } 629 } 630 if (!listContents.isEmpty()) { 631 Content li = HtmlTree.LI(contents.detailLabel); 632 li.add(Entity.NO_BREAK_SPACE); 633 tree.add(li); 634 addListToNav(listContents, tree); 635 } 636 break; 637 default: 638 break; 639 } 640 } 641 642 /** 643 * Add the navigation Type detail link. 644 * 645 * @param kind the kind of member being documented 646 * @param link true if the members are listed and need to be linked 647 * @param listContents the list of contents to which the detail will be added. 648 */ addTypeDetailLink(VisibleMemberTable.Kind kind, boolean link, List<Content> listContents)649 protected void addTypeDetailLink(VisibleMemberTable.Kind kind, boolean link, List<Content> listContents) { 650 switch (kind) { 651 case CONSTRUCTORS: 652 if (link) { 653 addContentToList(listContents, links.createLink(SectionName.CONSTRUCTOR_DETAIL, contents.navConstructor)); 654 } else { 655 addContentToList(listContents, contents.navConstructor); 656 } 657 break; 658 case ENUM_CONSTANTS: 659 if (link) { 660 addContentToList(listContents, links.createLink(SectionName.ENUM_CONSTANT_DETAIL, contents.navEnum)); 661 } else { 662 addContentToList(listContents, contents.navEnum); 663 } 664 break; 665 case FIELDS: 666 if (link) { 667 addContentToList(listContents, links.createLink(SectionName.FIELD_DETAIL, contents.navField)); 668 } else { 669 addContentToList(listContents, contents.navField); 670 } 671 break; 672 case METHODS: 673 if (link) { 674 addContentToList(listContents, links.createLink(SectionName.METHOD_DETAIL, contents.navMethod)); 675 } else { 676 addContentToList(listContents, contents.navMethod); 677 } 678 break; 679 case PROPERTIES: 680 if (link) { 681 addContentToList(listContents, links.createLink(SectionName.PROPERTY_DETAIL, contents.navProperty)); 682 } else { 683 addContentToList(listContents, contents.navProperty); 684 } 685 break; 686 default: 687 break; 688 } 689 } 690 691 /** 692 * Add the navigation Annotation Type detail link. 693 * 694 * @param listContents the list of contents to which the annotation detail will be added. 695 */ addAnnotationTypeDetailLink(List<Content> listContents)696 protected void addAnnotationTypeDetailLink(List<Content> listContents) { 697 TypeElement annotationType = (TypeElement) element; 698 AbstractMemberWriter writerField 699 = ((AbstractMemberWriter) memberSummaryBuilder. 700 getMemberSummaryWriter(FIELDS)); 701 AbstractMemberWriter writerOptional 702 = ((AbstractMemberWriter) memberSummaryBuilder. 703 getMemberSummaryWriter(ANNOTATION_TYPE_MEMBER_OPTIONAL)); 704 AbstractMemberWriter writerRequired 705 = ((AbstractMemberWriter) memberSummaryBuilder. 706 getMemberSummaryWriter(ANNOTATION_TYPE_MEMBER_REQUIRED)); 707 if (writerField != null) { 708 addAnnotationTypeDetailLink(FIELDS, 709 !configuration.utils.getFields(annotationType).isEmpty(), 710 listContents); 711 } else { 712 addContentToList(listContents, contents.navField); 713 } 714 if (writerOptional != null) { 715 addAnnotationTypeDetailLink(ANNOTATION_TYPE_MEMBER_OPTIONAL, 716 !annotationType.getAnnotationMirrors().isEmpty(), listContents); 717 } else if (writerRequired != null) { 718 addAnnotationTypeDetailLink(ANNOTATION_TYPE_MEMBER_REQUIRED, 719 !annotationType.getAnnotationMirrors().isEmpty(), listContents); 720 } else { 721 addContentToList(listContents, contents.navAnnotationTypeMember); 722 } 723 } 724 725 /** 726 * Add the navigation Annotation Type detail link. 727 * 728 * @param type the kind of member being documented 729 * @param link true if the member details need to be linked 730 * @param listContents the list of contents to which the annotation detail will be added. 731 */ addAnnotationTypeDetailLink(VisibleMemberTable.Kind type, boolean link, List<Content> listContents)732 protected void addAnnotationTypeDetailLink(VisibleMemberTable.Kind type, boolean link, List<Content> listContents) { 733 switch (type) { 734 case FIELDS: 735 if (link) { 736 addContentToList(listContents, links.createLink(SectionName.FIELD_DETAIL, 737 contents.navField)); 738 } else { 739 addContentToList(listContents, contents.navField); 740 } 741 break; 742 case ANNOTATION_TYPE_MEMBER_REQUIRED: 743 case ANNOTATION_TYPE_MEMBER_OPTIONAL: 744 if (link) { 745 addContentToList(listContents, links.createLink(SectionName.ANNOTATION_TYPE_ELEMENT_DETAIL, 746 contents.navAnnotationTypeMember)); 747 } else { 748 addContentToList(listContents, contents.navAnnotationTypeMember); 749 } 750 break; 751 default: 752 break; 753 } 754 } 755 addContentToList(List<Content> listContents, Content tree)756 private void addContentToList(List<Content> listContents, Content tree) { 757 listContents.add(HtmlTree.LI(tree)); 758 } 759 addContentToTree(Content tree, Content content)760 private void addContentToTree(Content tree, Content content) { 761 tree.add(HtmlTree.LI(content)); 762 } 763 addListToNav(List<Content> listContents, Content tree)764 private void addListToNav(List<Content> listContents, Content tree) { 765 int count = 0; 766 for (Content liContent : listContents) { 767 if (count < listContents.size() - 1) { 768 liContent.add(Entity.NO_BREAK_SPACE); 769 liContent.add("|"); 770 liContent.add(Entity.NO_BREAK_SPACE); 771 } 772 tree.add(liContent); 773 count++; 774 } 775 } 776 addActivePageLink(Content tree, Content label, boolean display)777 private void addActivePageLink(Content tree, Content label, boolean display) { 778 if (display) { 779 tree.add(HtmlTree.LI(HtmlStyle.navBarCell1Rev, label)); 780 } 781 } 782 addPageLabel(Content tree, Content label, boolean display)783 private void addPageLabel(Content tree, Content label, boolean display) { 784 if (display) { 785 tree.add(HtmlTree.LI(label)); 786 } 787 } 788 addOverviewLink(Content tree)789 private void addOverviewLink(Content tree) { 790 if (options.createOverview()) { 791 tree.add(HtmlTree.LI(links.createLink(pathToRoot.resolve(DocPaths.INDEX), 792 contents.overviewLabel, "", ""))); 793 } 794 } 795 addModuleLink(Content tree)796 private void addModuleLink(Content tree) { 797 if (configuration.showModules) { 798 if (configuration.modules.size() == 1) { 799 ModuleElement mdle = configuration.modules.first(); 800 boolean included = configuration.utils.isIncluded(mdle); 801 tree.add(HtmlTree.LI((included) 802 ? links.createLink(pathToRoot.resolve(configuration.docPaths.moduleSummary(mdle)), contents.moduleLabel, "", "") 803 : contents.moduleLabel)); 804 } else if (!configuration.modules.isEmpty()) { 805 addPageLabel(tree, contents.moduleLabel, true); 806 } 807 } 808 } 809 addModuleOfElementLink(Content tree)810 private void addModuleOfElementLink(Content tree) { 811 if (configuration.showModules) { 812 tree.add(HtmlTree.LI(navLinkModule)); 813 } 814 } 815 addPackageLink(Content tree)816 private void addPackageLink(Content tree) { 817 if (configuration.packages.size() == 1) { 818 PackageElement packageElement = configuration.packages.first(); 819 boolean included = packageElement != null && configuration.utils.isIncluded(packageElement); 820 if (!included) { 821 for (PackageElement p : configuration.packages) { 822 if (p.equals(packageElement)) { 823 included = true; 824 break; 825 } 826 } 827 } 828 if (included || packageElement == null) { 829 tree.add(HtmlTree.LI(links.createLink( 830 pathToRoot.resolve(configuration.docPaths.forPackage(packageElement).resolve(DocPaths.PACKAGE_SUMMARY)), 831 contents.packageLabel))); 832 } else { 833 DocLink crossPkgLink = configuration.extern.getExternalLink( 834 packageElement, pathToRoot, DocPaths.PACKAGE_SUMMARY.getPath()); 835 if (crossPkgLink != null) { 836 tree.add(HtmlTree.LI(links.createLink(crossPkgLink, contents.packageLabel))); 837 } else { 838 tree.add(HtmlTree.LI(contents.packageLabel)); 839 } 840 } 841 } else if (!configuration.packages.isEmpty()) { 842 addPageLabel(tree, contents.packageLabel, true); 843 } 844 } 845 addPackageOfElementLink(Content tree)846 private void addPackageOfElementLink(Content tree) { 847 tree.add(HtmlTree.LI(links.createLink(DocPath.parent.resolve(DocPaths.PACKAGE_SUMMARY), 848 contents.packageLabel))); 849 } 850 addPackageSummaryLink(Content tree)851 private void addPackageSummaryLink(Content tree) { 852 tree.add(HtmlTree.LI(links.createLink(DocPaths.PACKAGE_SUMMARY, contents.packageLabel))); 853 } 854 addTreeLink(Content tree)855 private void addTreeLink(Content tree) { 856 if (options.createTree()) { 857 List<PackageElement> packages = new ArrayList<>(configuration.getSpecifiedPackageElements()); 858 DocPath docPath = packages.size() == 1 && configuration.getSpecifiedTypeElements().isEmpty() 859 ? pathToRoot.resolve(configuration.docPaths.forPackage(packages.get(0)).resolve(DocPaths.PACKAGE_TREE)) 860 : pathToRoot.resolve(DocPaths.OVERVIEW_TREE); 861 tree.add(HtmlTree.LI(links.createLink(docPath, contents.treeLabel, "", ""))); 862 } 863 } 864 addDeprecatedLink(Content tree)865 private void addDeprecatedLink(Content tree) { 866 if (!(options.noDeprecated() || options.noDeprecatedList())) { 867 tree.add(HtmlTree.LI(links.createLink(pathToRoot.resolve(DocPaths.DEPRECATED_LIST), 868 contents.deprecatedLabel, "", ""))); 869 } 870 } 871 addIndexLink(Content tree)872 private void addIndexLink(Content tree) { 873 if (options.createIndex()) { 874 tree.add(HtmlTree.LI(links.createLink(pathToRoot.resolve( 875 (options.splitIndex() 876 ? DocPaths.INDEX_FILES.resolve(DocPaths.indexN(1)) 877 : DocPaths.INDEX_ALL)), 878 contents.indexLabel, "", ""))); 879 } 880 } 881 addHelpLink(Content tree)882 private void addHelpLink(Content tree) { 883 if (!options.noHelp()) { 884 String helpfile = options.helpFile(); 885 DocPath helpfilenm; 886 if (helpfile.isEmpty()) { 887 helpfilenm = DocPaths.HELP_DOC; 888 } else { 889 DocFile file = DocFile.createFileForInput(configuration, helpfile); 890 helpfilenm = DocPath.create(file.getName()); 891 } 892 tree.add(HtmlTree.LI(links.createLink(pathToRoot.resolve(helpfilenm), 893 contents.helpLabel, "", ""))); 894 } 895 } 896 addSearch(Content tree)897 private void addSearch(Content tree) { 898 String searchValueId = "search"; 899 String reset = "reset"; 900 HtmlTree inputText = HtmlTree.INPUT("text", searchValueId, searchValueId); 901 HtmlTree inputReset = HtmlTree.INPUT(reset, reset, reset); 902 HtmlTree searchDiv = HtmlTree.DIV(HtmlStyle.navListSearch, HtmlTree.LABEL(searchValueId, searchLabel)); 903 searchDiv.add(inputText); 904 searchDiv.add(inputReset); 905 tree.add(searchDiv); 906 } 907 908 /** 909 * Get the navigation content. 910 * 911 * @param posn the position for the navigation bar 912 * @return the navigation contents 913 */ getContent(Position posn)914 public Content getContent(Position posn) { 915 if (options.noNavbar()) { 916 return new ContentBuilder(); 917 } 918 Content tree = HtmlTree.NAV(); 919 920 HtmlTree navDiv = new HtmlTree(TagName.DIV); 921 Content skipNavLinks = contents.getContent("doclet.Skip_navigation_links"); 922 SectionName navListSection; 923 Content aboutContent; 924 boolean addSearch; 925 switch (posn) { 926 case TOP: 927 tree.add(Position.TOP.startOfNav()); 928 navDiv.setStyle(HtmlStyle.topNav) 929 .setId(SectionName.NAVBAR_TOP.getName()) 930 .add(HtmlTree.DIV(HtmlStyle.skipNav, 931 links.createLink(SectionName.SKIP_NAVBAR_TOP, skipNavLinks, 932 skipNavLinks.toString(), ""))); 933 navListSection = SectionName.NAVBAR_TOP_FIRSTROW; 934 aboutContent = userHeader; 935 addSearch = options.createIndex(); 936 break; 937 938 case BOTTOM: 939 tree.add(Position.BOTTOM.startOfNav()); 940 navDiv.setStyle(HtmlStyle.bottomNav) 941 .setId(SectionName.NAVBAR_BOTTOM.getName()) 942 .add(HtmlTree.DIV(HtmlStyle.skipNav, 943 links.createLink(SectionName.SKIP_NAVBAR_BOTTOM, skipNavLinks, 944 skipNavLinks.toString(), ""))); 945 navListSection = SectionName.NAVBAR_BOTTOM_FIRSTROW; 946 aboutContent = userFooter; 947 addSearch = false; 948 break; 949 950 default: 951 throw new Error(); 952 } 953 954 HtmlTree navList = new HtmlTree(TagName.UL) 955 .setId(navListSection.getName()) 956 .setStyle(HtmlStyle.navList) 957 .put(HtmlAttr.TITLE, rowListTitle); 958 addMainNavLinks(navList); 959 navDiv.add(navList); 960 Content aboutDiv = HtmlTree.DIV(HtmlStyle.aboutLanguage, aboutContent); 961 navDiv.add(aboutDiv); 962 tree.add(navDiv); 963 964 HtmlTree subDiv = new HtmlTree(TagName.DIV).setStyle(HtmlStyle.subNav); 965 966 HtmlTree div = new HtmlTree(TagName.DIV); 967 // Add the summary links if present. 968 HtmlTree ulNavSummary = new HtmlTree(TagName.UL).setStyle(HtmlStyle.subNavList); 969 addSummaryLinks(ulNavSummary); 970 div.add(ulNavSummary); 971 // Add the detail links if present. 972 HtmlTree ulNavDetail = new HtmlTree(TagName.UL).setStyle(HtmlStyle.subNavList); 973 addDetailLinks(ulNavDetail); 974 div.add(ulNavDetail); 975 subDiv.add(div); 976 977 if (addSearch) { 978 addSearch(subDiv); 979 } 980 tree.add(subDiv); 981 982 switch (posn) { 983 case TOP: 984 tree.add(Position.TOP.endOfNav()); 985 tree.add(HtmlTree.SPAN(HtmlStyle.skipNav, EMPTY_COMMENT) 986 .setId(SectionName.SKIP_NAVBAR_TOP.getName())); 987 break; 988 989 case BOTTOM: 990 tree.add(Position.BOTTOM.endOfNav()); 991 tree.add(HtmlTree.SPAN(HtmlStyle.skipNav, EMPTY_COMMENT) 992 .setId(SectionName.SKIP_NAVBAR_BOTTOM.getName())); 993 } 994 return tree; 995 } 996 } 997