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