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