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