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