ClassWriterImpl.java revision 3233:b5d08bc0d224
1/* 2 * Copyright (c) 1997, 2016, 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 26package jdk.javadoc.internal.doclets.formats.html; 27 28import java.io.IOException; 29import java.util.*; 30 31import javax.lang.model.element.AnnotationMirror; 32import javax.lang.model.element.Element; 33import javax.lang.model.element.PackageElement; 34import javax.lang.model.element.TypeElement; 35import javax.lang.model.type.TypeMirror; 36import javax.lang.model.util.SimpleElementVisitor8; 37 38import com.sun.source.doctree.DocTree; 39import com.sun.tools.javac.util.DefinedBy; 40import com.sun.tools.javac.util.DefinedBy.Api; 41import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants; 42import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; 43import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; 44import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; 45import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; 46import jdk.javadoc.internal.doclets.toolkit.ClassWriter; 47import jdk.javadoc.internal.doclets.toolkit.Content; 48import jdk.javadoc.internal.doclets.toolkit.builders.MemberSummaryBuilder; 49import jdk.javadoc.internal.doclets.toolkit.taglets.ParamTaglet; 50import jdk.javadoc.internal.doclets.toolkit.util.ClassTree; 51import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper; 52import jdk.javadoc.internal.doclets.toolkit.util.DocPath; 53import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; 54import jdk.javadoc.internal.doclets.toolkit.util.DocletAbortException; 55import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants; 56import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap; 57import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap.Kind; 58 59/** 60 * Generate the Class Information Page. 61 * 62 * <p><b>This is NOT part of any supported API. 63 * If you write code that depends on this, you do so at your own risk. 64 * This code and its internal interfaces are subject to change or 65 * deletion without notice.</b> 66 * 67 * @see javax.lang.model.element.TypeElement 68 * @see java.util.Collections 69 * @see java.util.List 70 * @see java.util.ArrayList 71 * @see java.util.HashMap 72 * 73 * @author Atul M Dambalkar 74 * @author Robert Field 75 * @author Bhavesh Patel (Modified) 76 */ 77public class ClassWriterImpl extends SubWriterHolderWriter implements ClassWriter { 78 79 protected final TypeElement typeElement; 80 81 protected final ClassTree classtree; 82 83 protected final TypeElement prev; 84 85 protected final TypeElement next; 86 87 /** 88 * @param configuration the configuration data for the doclet 89 * @param typeElement the class being documented. 90 * @param prevClass the previous class that was documented. 91 * @param nextClass the next class being documented. 92 * @param classTree the class tree for the given class. 93 * @throws java.io.IOException 94 */ 95 public ClassWriterImpl(ConfigurationImpl configuration, TypeElement typeElement, 96 TypeElement prevClass, TypeElement nextClass, ClassTree classTree) 97 throws IOException { 98 super(configuration, DocPath.forClass(configuration.utils, typeElement)); 99 this.typeElement = typeElement; 100 configuration.currentTypeElement = typeElement; 101 this.classtree = classTree; 102 this.prev = prevClass; 103 this.next = nextClass; 104 } 105 106 /** 107 * Get this package link. 108 * 109 * @return a content tree for the package link 110 */ 111 @Override 112 protected Content getNavLinkPackage() { 113 Content linkContent = getHyperLink(DocPaths.PACKAGE_SUMMARY, 114 packageLabel); 115 Content li = HtmlTree.LI(linkContent); 116 return li; 117 } 118 119 /** 120 * Get the class link. 121 * 122 * @return a content tree for the class link 123 */ 124 @Override 125 protected Content getNavLinkClass() { 126 Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, classLabel); 127 return li; 128 } 129 130 /** 131 * Get the class use link. 132 * 133 * @return a content tree for the class use link 134 */ 135 @Override 136 protected Content getNavLinkClassUse() { 137 Content linkContent = getHyperLink(DocPaths.CLASS_USE.resolve(filename), useLabel); 138 Content li = HtmlTree.LI(linkContent); 139 return li; 140 } 141 142 /** 143 * Get link to previous class. 144 * 145 * @return a content tree for the previous class link 146 */ 147 @Override 148 public Content getNavLinkPrevious() { 149 Content li; 150 if (prev != null) { 151 Content prevLink = getLink(new LinkInfoImpl(configuration, 152 LinkInfoImpl.Kind.CLASS, prev) 153 .label(prevclassLabel).strong(true)); 154 li = HtmlTree.LI(prevLink); 155 } 156 else 157 li = HtmlTree.LI(prevclassLabel); 158 return li; 159 } 160 161 /** 162 * Get link to next class. 163 * 164 * @return a content tree for the next class link 165 */ 166 @Override 167 public Content getNavLinkNext() { 168 Content li; 169 if (next != null) { 170 Content nextLink = getLink(new LinkInfoImpl(configuration, 171 LinkInfoImpl.Kind.CLASS, next) 172 .label(nextclassLabel).strong(true)); 173 li = HtmlTree.LI(nextLink); 174 } 175 else 176 li = HtmlTree.LI(nextclassLabel); 177 return li; 178 } 179 180 /** 181 * {@inheritDoc} 182 */ 183 @Override 184 public Content getHeader(String header) { 185 HtmlTree bodyTree = getBody(true, getWindowTitle(utils.getSimpleName(typeElement))); 186 HtmlTree htmlTree = (configuration.allowTag(HtmlTag.HEADER)) 187 ? HtmlTree.HEADER() 188 : bodyTree; 189 addTop(htmlTree); 190 addNavLinks(true, htmlTree); 191 if (configuration.allowTag(HtmlTag.HEADER)) { 192 bodyTree.addContent(htmlTree); 193 } 194 bodyTree.addContent(HtmlConstants.START_OF_CLASS_DATA); 195 HtmlTree div = new HtmlTree(HtmlTag.DIV); 196 div.addStyle(HtmlStyle.header); 197 PackageElement pkg = utils.containingPackage(typeElement); 198 if (!pkg.isUnnamed()) { 199 Content pkgNameContent = new StringContent(utils.getPackageName(pkg)); 200 Content pkgNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, pkgNameContent); 201 div.addContent(pkgNameDiv); 202 } 203 LinkInfoImpl linkInfo = new LinkInfoImpl(configuration, 204 LinkInfoImpl.Kind.CLASS_HEADER, typeElement); 205 //Let's not link to ourselves in the header. 206 linkInfo.linkToSelf = false; 207 Content headerContent = new StringContent(header); 208 Content heading = HtmlTree.HEADING(HtmlConstants.CLASS_PAGE_HEADING, true, 209 HtmlStyle.title, headerContent); 210 heading.addContent(getTypeParameterLinks(linkInfo)); 211 div.addContent(heading); 212 if (configuration.allowTag(HtmlTag.MAIN)) { 213 mainTree.addContent(div); 214 } else { 215 bodyTree.addContent(div); 216 } 217 return bodyTree; 218 } 219 220 /** 221 * {@inheritDoc} 222 */ 223 @Override 224 public Content getClassContentHeader() { 225 return getContentHeader(); 226 } 227 228 /** 229 * {@inheritDoc} 230 */ 231 @Override 232 public void addFooter(Content contentTree) { 233 contentTree.addContent(HtmlConstants.END_OF_CLASS_DATA); 234 Content htmlTree = (configuration.allowTag(HtmlTag.FOOTER)) 235 ? HtmlTree.FOOTER() 236 : contentTree; 237 addNavLinks(false, htmlTree); 238 addBottom(htmlTree); 239 if (configuration.allowTag(HtmlTag.FOOTER)) { 240 contentTree.addContent(htmlTree); 241 } 242 } 243 244 /** 245 * {@inheritDoc} 246 */ 247 @Override 248 public void printDocument(Content contentTree) throws IOException { 249 printHtmlDocument(configuration.metakeywords.getMetaKeywords(typeElement), 250 true, contentTree); 251 } 252 253 /** 254 * {@inheritDoc} 255 */ 256 @Override 257 public Content getClassInfoTreeHeader() { 258 return getMemberTreeHeader(); 259 } 260 261 /** 262 * {@inheritDoc} 263 */ 264 @Override 265 public Content getClassInfo(Content classInfoTree) { 266 return getMemberTree(HtmlStyle.description, classInfoTree); 267 } 268 269 /** 270 * {@inheritDoc} 271 */ 272 @Override 273 public void addClassSignature(String modifiers, Content classInfoTree) { 274 classInfoTree.addContent(new HtmlTree(HtmlTag.BR)); 275 Content pre = new HtmlTree(HtmlTag.PRE); 276 addAnnotationInfo(typeElement, pre); 277 pre.addContent(modifiers); 278 LinkInfoImpl linkInfo = new LinkInfoImpl(configuration, 279 LinkInfoImpl.Kind.CLASS_SIGNATURE, typeElement); 280 //Let's not link to ourselves in the signature. 281 linkInfo.linkToSelf = false; 282 Content className = new StringContent(utils.getSimpleName(typeElement)); 283 Content parameterLinks = getTypeParameterLinks(linkInfo); 284 if (configuration.linksource) { 285 addSrcLink(typeElement, className, pre); 286 pre.addContent(parameterLinks); 287 } else { 288 Content span = HtmlTree.SPAN(HtmlStyle.typeNameLabel, className); 289 span.addContent(parameterLinks); 290 pre.addContent(span); 291 } 292 if (!utils.isInterface(typeElement)) { 293 TypeMirror superclass = utils.getFirstVisibleSuperClass(typeElement); 294 if (superclass != null) { 295 pre.addContent(DocletConstants.NL); 296 pre.addContent("extends "); 297 Content link = getLink(new LinkInfoImpl(configuration, 298 LinkInfoImpl.Kind.CLASS_SIGNATURE_PARENT_NAME, 299 superclass)); 300 pre.addContent(link); 301 } 302 } 303 List<? extends TypeMirror> interfaces = typeElement.getInterfaces(); 304 if (!interfaces.isEmpty()) { 305 boolean isFirst = true; 306 for (TypeMirror type : interfaces) { 307 TypeElement tDoc = utils.asTypeElement(type); 308 if (!(utils.isPublic(tDoc) || utils.isLinkable(tDoc))) { 309 continue; 310 } 311 if (isFirst) { 312 pre.addContent(DocletConstants.NL); 313 pre.addContent(utils.isInterface(typeElement) ? "extends " : "implements "); 314 isFirst = false; 315 } else { 316 pre.addContent(", "); 317 } 318 Content link = getLink(new LinkInfoImpl(configuration, 319 LinkInfoImpl.Kind.CLASS_SIGNATURE_PARENT_NAME, 320 type)); 321 pre.addContent(link); 322 } 323 } 324 classInfoTree.addContent(pre); 325 } 326 327 /** 328 * {@inheritDoc} 329 */ 330 @Override 331 public void addClassDescription(Content classInfoTree) { 332 if(!configuration.nocomment) { 333 // generate documentation for the class. 334 if (!utils.getBody(typeElement).isEmpty()) { 335 addInlineComment(typeElement, classInfoTree); 336 } 337 } 338 } 339 340 /** 341 * {@inheritDoc} 342 */ 343 @Override 344 public void addClassTagInfo(Content classInfoTree) { 345 if(!configuration.nocomment) { 346 // Print Information about all the tags here 347 addTagsInfo(typeElement, classInfoTree); 348 } 349 } 350 351 /** 352 * Get the class hierarchy tree for the given class. 353 * 354 * @param type the class to print the hierarchy for 355 * @return a content tree for class inheritence 356 */ 357 private Content getClassInheritenceTree(TypeMirror type) { 358 TypeMirror sup; 359 HtmlTree classTreeUl = new HtmlTree(HtmlTag.UL); 360 classTreeUl.addStyle(HtmlStyle.inheritance); 361 Content liTree = null; 362 do { 363 sup = utils.getFirstVisibleSuperClass(type); 364 if (sup != null) { 365 HtmlTree ul = new HtmlTree(HtmlTag.UL); 366 ul.addStyle(HtmlStyle.inheritance); 367 ul.addContent(getTreeForClassHelper(type)); 368 if (liTree != null) 369 ul.addContent(liTree); 370 Content li = HtmlTree.LI(ul); 371 liTree = li; 372 type = sup; 373 } else 374 classTreeUl.addContent(getTreeForClassHelper(type)); 375 } while (sup != null); 376 if (liTree != null) 377 classTreeUl.addContent(liTree); 378 return classTreeUl; 379 } 380 381 /** 382 * Get the class helper tree for the given class. 383 * 384 * @param type the class to print the helper for 385 * @return a content tree for class helper 386 */ 387 private Content getTreeForClassHelper(TypeMirror type) { 388 Content li = new HtmlTree(HtmlTag.LI); 389 if (type.equals(typeElement.asType())) { 390 Content typeParameters = getTypeParameterLinks( 391 new LinkInfoImpl(configuration, LinkInfoImpl.Kind.TREE, 392 typeElement)); 393 if (configuration.shouldExcludeQualifier(utils.containingPackage(typeElement).toString())) { 394 li.addContent(utils.asTypeElement(type).getSimpleName().toString()); 395 li.addContent(typeParameters); 396 } else { 397 li.addContent(utils.asTypeElement(type).getQualifiedName().toString()); 398 li.addContent(typeParameters); 399 } 400 } else { 401 Content link = getLink(new LinkInfoImpl(configuration, 402 LinkInfoImpl.Kind.CLASS_TREE_PARENT, type) 403 .label(configuration.getClassName(utils.asTypeElement(type)))); 404 li.addContent(link); 405 } 406 return li; 407 } 408 409 /** 410 * {@inheritDoc} 411 */ 412 @Override 413 public void addClassTree(Content classContentTree) { 414 if (!utils.isClass(typeElement)) { 415 return; 416 } 417 classContentTree.addContent(getClassInheritenceTree(typeElement.asType())); 418 } 419 420 /** 421 * {@inheritDoc} 422 */ 423 @Override 424 public void addTypeParamInfo(Content classInfoTree) { 425 if (!utils.getTypeParamTrees(typeElement).isEmpty()) { 426 Content typeParam = (new ParamTaglet()).getTagletOutput(typeElement, 427 getTagletWriterInstance(false)); 428 Content dl = HtmlTree.DL(typeParam); 429 classInfoTree.addContent(dl); 430 } 431 } 432 433 /** 434 * {@inheritDoc} 435 */ 436 @Override 437 public void addSubClassInfo(Content classInfoTree) { 438 if (utils.isClass(typeElement)) { 439 if (typeElement.getQualifiedName().toString().equals("java.lang.Object") || 440 typeElement.getQualifiedName().toString().equals("org.omg.CORBA.Object")) { 441 return; // Don't generate the list, too huge 442 } 443 Set<TypeElement> subclasses = classtree.directSubClasses(typeElement, false); 444 if (!subclasses.isEmpty()) { 445 Content label = getResource( 446 "doclet.Subclasses"); 447 Content dt = HtmlTree.DT(label); 448 Content dl = HtmlTree.DL(dt); 449 dl.addContent(getClassLinks(LinkInfoImpl.Kind.SUBCLASSES, 450 subclasses)); 451 classInfoTree.addContent(dl); 452 } 453 } 454 } 455 456 /** 457 * {@inheritDoc} 458 */ 459 @Override 460 public void addSubInterfacesInfo(Content classInfoTree) { 461 if (utils.isInterface(typeElement)) { 462 Set<TypeElement> subInterfaces = classtree.allSubClasses(typeElement, false); 463 if (!subInterfaces.isEmpty()) { 464 Content label = getResource( 465 "doclet.Subinterfaces"); 466 Content dt = HtmlTree.DT(label); 467 Content dl = HtmlTree.DL(dt); 468 dl.addContent(getClassLinks(LinkInfoImpl.Kind.SUBINTERFACES, 469 subInterfaces)); 470 classInfoTree.addContent(dl); 471 } 472 } 473 } 474 475 /** 476 * {@inheritDoc} 477 */ 478 @Override 479 public void addInterfaceUsageInfo (Content classInfoTree) { 480 if (!utils.isInterface(typeElement)) { 481 return; 482 } 483 if (typeElement.getQualifiedName().toString().equals("java.lang.Cloneable") || 484 typeElement.getQualifiedName().toString().equals("java.io.Serializable")) { 485 return; // Don't generate the list, too big 486 } 487 Set<TypeElement> implcl = classtree.implementingClasses(typeElement); 488 if (!implcl.isEmpty()) { 489 Content label = getResource( 490 "doclet.Implementing_Classes"); 491 Content dt = HtmlTree.DT(label); 492 Content dl = HtmlTree.DL(dt); 493 dl.addContent(getClassLinks(LinkInfoImpl.Kind.IMPLEMENTED_CLASSES, 494 implcl)); 495 classInfoTree.addContent(dl); 496 } 497 } 498 499 /** 500 * {@inheritDoc} 501 */ 502 @Override 503 public void addImplementedInterfacesInfo(Content classInfoTree) { 504 SortedSet<TypeMirror> interfaces = new TreeSet<>(utils.makeTypeMirrorClassUseComparator()); 505 interfaces.addAll(utils.getAllInterfaces(typeElement)); 506 if (utils.isClass(typeElement) && !interfaces.isEmpty()) { 507 Content label = getResource( 508 "doclet.All_Implemented_Interfaces"); 509 Content dt = HtmlTree.DT(label); 510 Content dl = HtmlTree.DL(dt); 511 dl.addContent(getClassLinks(LinkInfoImpl.Kind.IMPLEMENTED_INTERFACES, interfaces)); 512 classInfoTree.addContent(dl); 513 } 514 } 515 516 /** 517 * {@inheritDoc} 518 */ 519 @Override 520 public void addSuperInterfacesInfo(Content classInfoTree) { 521 SortedSet<TypeMirror> interfaces = 522 new TreeSet<>(utils.makeTypeMirrorIndexUseComparator()); 523 interfaces.addAll(utils.getAllInterfaces(typeElement)); 524 525 if (utils.isInterface(typeElement) && !interfaces.isEmpty()) { 526 Content label = getResource("doclet.All_Superinterfaces"); 527 Content dt = HtmlTree.DT(label); 528 Content dl = HtmlTree.DL(dt); 529 dl.addContent(getClassLinks(LinkInfoImpl.Kind.SUPER_INTERFACES, interfaces)); 530 classInfoTree.addContent(dl); 531 } 532 } 533 534 /** 535 * {@inheritDoc} 536 */ 537 @Override 538 public void addNestedClassInfo(final Content classInfoTree) { 539 Element outerClass = typeElement.getEnclosingElement(); 540 if (outerClass == null) 541 return; 542 new SimpleElementVisitor8<Void, Void>() { 543 @Override @DefinedBy(Api.LANGUAGE_MODEL) 544 public Void visitType(TypeElement e, Void p) { 545 String label = utils.isInterface(e) 546 ? "doclet.Enclosing_Interface" 547 : "doclet.Enclosing_Class"; 548 Content dt = HtmlTree.DT(getResource(label)); 549 Content dl = HtmlTree.DL(dt); 550 Content dd = new HtmlTree(HtmlTag.DD); 551 dd.addContent(getLink(new LinkInfoImpl(configuration, 552 LinkInfoImpl.Kind.CLASS, e))); 553 dl.addContent(dd); 554 classInfoTree.addContent(dl); 555 return null; 556 } 557 }.visit(outerClass); 558 } 559 560 /** 561 * {@inheritDoc} 562 */ 563 @Override 564 public void addFunctionalInterfaceInfo (Content classInfoTree) { 565 if (isFunctionalInterface()) { 566 Content dt = HtmlTree.DT(getResource("doclet.Functional_Interface")); 567 Content dl = HtmlTree.DL(dt); 568 Content dd = new HtmlTree(HtmlTag.DD); 569 dd.addContent(getResource("doclet.Functional_Interface_Message")); 570 dl.addContent(dd); 571 classInfoTree.addContent(dl); 572 } 573 } 574 575 public boolean isFunctionalInterface() { 576 List<? extends AnnotationMirror> annotationMirrors = ((Element) typeElement).getAnnotationMirrors(); 577 for (AnnotationMirror anno : annotationMirrors) { 578 if (utils.isFunctionalInterface(anno)) { 579 return true; 580 } 581 } 582 return false; 583 } 584 585 586 /** 587 * {@inheritDoc} 588 */ 589 @Override 590 public void addClassDeprecationInfo(Content classInfoTree) { 591 Content hr = new HtmlTree(HtmlTag.HR); 592 classInfoTree.addContent(hr); 593 List<? extends DocTree> deprs = utils.getBlockTags(typeElement, DocTree.Kind.DEPRECATED); 594 if (utils.isDeprecated(typeElement)) { 595 Content deprLabel = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, deprecatedPhrase); 596 Content div = HtmlTree.DIV(HtmlStyle.block, deprLabel); 597 if (!deprs.isEmpty()) { 598 CommentHelper ch = utils.getCommentHelper(typeElement); 599 DocTree dt = deprs.get(0); 600 List<? extends DocTree> commentTags = ch.getBody(configuration, dt); 601 if (!commentTags.isEmpty()) { 602 div.addContent(getSpace()); 603 addInlineDeprecatedComment(typeElement, deprs.get(0), div); 604 } 605 } 606 classInfoTree.addContent(div); 607 } 608 } 609 610 /** 611 * Get links to the given classes. 612 * 613 * @param context the id of the context where the link will be printed 614 * @param list the list of classes 615 * @return a content tree for the class list 616 */ 617 private Content getClassLinks(LinkInfoImpl.Kind context, Collection<?> list) { 618 Content dd = new HtmlTree(HtmlTag.DD); 619 boolean isFirst = true; 620 for (Object type : list) { 621 if (!isFirst) { 622 Content separator = new StringContent(", "); 623 dd.addContent(separator); 624 } else { 625 isFirst = false; 626 } 627 // TODO: should we simply split this method up to avoid instanceof ? 628 if (type instanceof TypeElement) { 629 Content link = getLink( 630 new LinkInfoImpl(configuration, context, (TypeElement)(type))); 631 dd.addContent(link); 632 } else { 633 Content link = getLink( 634 new LinkInfoImpl(configuration, context, ((TypeMirror)type))); 635 dd.addContent(link); 636 } 637 } 638 return dd; 639 } 640 641 /** 642 * {@inheritDoc} 643 */ 644 @Override 645 protected Content getNavLinkTree() { 646 Content treeLinkContent = getHyperLink(DocPaths.PACKAGE_TREE, 647 treeLabel, "", ""); 648 Content li = HtmlTree.LI(treeLinkContent); 649 return li; 650 } 651 652 /** 653 * Add summary details to the navigation bar. 654 * 655 * @param subDiv the content tree to which the summary detail links will be added 656 */ 657 protected void addSummaryDetailLinks(Content subDiv) { 658 try { 659 Content div = HtmlTree.DIV(getNavSummaryLinks()); 660 div.addContent(getNavDetailLinks()); 661 subDiv.addContent(div); 662 } catch (Exception e) { 663 throw new DocletAbortException(e); 664 } 665 } 666 667 /** 668 * Get summary links for navigation bar. 669 * 670 * @return the content tree for the navigation summary links 671 */ 672 protected Content getNavSummaryLinks() throws Exception { 673 Content li = HtmlTree.LI(summaryLabel); 674 li.addContent(getSpace()); 675 Content ulNav = HtmlTree.UL(HtmlStyle.subNavList, li); 676 MemberSummaryBuilder memberSummaryBuilder = (MemberSummaryBuilder) 677 configuration.getBuilderFactory().getMemberSummaryBuilder(this); 678 for (VisibleMemberMap.Kind kind : VisibleMemberMap.Kind.summarySet) { 679 Content liNav = new HtmlTree(HtmlTag.LI); 680 if (kind == VisibleMemberMap.Kind.ENUM_CONSTANTS && !utils.isEnum(typeElement)) { 681 continue; 682 } 683 if (kind == VisibleMemberMap.Kind.CONSTRUCTORS && utils.isEnum(typeElement)) { 684 continue; 685 } 686 AbstractMemberWriter writer = 687 ((AbstractMemberWriter) memberSummaryBuilder.getMemberSummaryWriter(kind)); 688 if (writer == null) { 689 liNav.addContent(getResource(VisibleMemberMap.Kind.getNavLinkLabels(kind))); 690 } else { 691 writer.addNavSummaryLink( 692 memberSummaryBuilder.members(kind), 693 memberSummaryBuilder.getVisibleMemberMap(kind), liNav); 694 } 695 if (kind != Kind.METHODS) { 696 addNavGap(liNav); 697 } 698 ulNav.addContent(liNav); 699 } 700 return ulNav; 701 } 702 703 /** 704 * Get detail links for the navigation bar. 705 * 706 * @return the content tree for the detail links 707 * @throws java.lang.Exception 708 */ 709 protected Content getNavDetailLinks() throws Exception { 710 Content li = HtmlTree.LI(detailLabel); 711 li.addContent(getSpace()); 712 Content ulNav = HtmlTree.UL(HtmlStyle.subNavList, li); 713 MemberSummaryBuilder memberSummaryBuilder = (MemberSummaryBuilder) 714 configuration.getBuilderFactory().getMemberSummaryBuilder(this); 715 for (VisibleMemberMap.Kind kind : VisibleMemberMap.Kind.detailSet) { 716 Content liNav = new HtmlTree(HtmlTag.LI); 717 AbstractMemberWriter writer = 718 ((AbstractMemberWriter) memberSummaryBuilder. 719 getMemberSummaryWriter(kind)); 720 if (kind == VisibleMemberMap.Kind.ENUM_CONSTANTS && !utils.isEnum(typeElement)) { 721 continue; 722 } 723 if (kind == VisibleMemberMap.Kind.CONSTRUCTORS && utils.isEnum(typeElement)) { 724 continue; 725 } 726 if (writer == null) { 727 liNav.addContent(getResource(VisibleMemberMap.Kind.getNavLinkLabels(kind))); 728 } else { 729 writer.addNavDetailLink(memberSummaryBuilder.members(kind), liNav); 730 } 731 if (kind != Kind.METHODS) { 732 addNavGap(liNav); 733 } 734 ulNav.addContent(liNav); 735 } 736 return ulNav; 737 } 738 739 /** 740 * Add gap between navigation bar elements. 741 * 742 * @param liNav the content tree to which the gap will be added 743 */ 744 protected void addNavGap(Content liNav) { 745 liNav.addContent(getSpace()); 746 liNav.addContent("|"); 747 liNav.addContent(getSpace()); 748 } 749 750 /** 751 * Return the TypeElement being documented. 752 * 753 * @return the TypeElement being documented. 754 */ 755 @Override 756 public TypeElement getTypeElement() { 757 return typeElement; 758 } 759} 760