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