1 /*
   2  * Copyright (c) 2003, 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.List;
  29 
  30 import javax.lang.model.element.ModuleElement;
  31 import javax.lang.model.element.PackageElement;
  32 import javax.lang.model.element.TypeElement;
  33 import javax.lang.model.type.TypeMirror;
  34 
  35 import com.sun.source.doctree.DocTree;
  36 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
  37 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
  38 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
  39 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
  40 import jdk.javadoc.internal.doclets.formats.html.markup.Links;
  41 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
  42 import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeWriter;
  43 import jdk.javadoc.internal.doclets.toolkit.Content;
  44 import jdk.javadoc.internal.doclets.toolkit.builders.MemberSummaryBuilder;
  45 import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper;
  46 import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
  47 import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
  48 import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
  49 import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
  50 
  51 /**
  52  * Generate the Class Information Page.
  53  *
  54  *  <p><b>This is NOT part of any supported API.
  55  *  If you write code that depends on this, you do so at your own risk.
  56  *  This code and its internal interfaces are subject to change or
  57  *  deletion without notice.</b>
  58  *
  59  * @see java.util.Collections
  60  * @see java.util.List
  61  * @see java.util.ArrayList
  62  * @see java.util.HashMap
  63  *
  64  * @author Atul M Dambalkar
  65  * @author Robert Field
  66  * @author Bhavesh Patel (Modified)
  67  */
  68 public class AnnotationTypeWriterImpl extends SubWriterHolderWriter
  69         implements AnnotationTypeWriter {
  70 
  71     protected TypeElement annotationType;
  72 
  73     protected TypeMirror prev;
  74 
  75     protected TypeMirror next;
  76 
  77     /**
  78      * @param configuration the configuration
  79      * @param annotationType the annotation type being documented.
  80      * @param prevType the previous class that was documented.
  81      * @param nextType the next class being documented.
  82      */
  83     public AnnotationTypeWriterImpl(HtmlConfiguration configuration,
  84             TypeElement annotationType, TypeMirror prevType, TypeMirror nextType) {
  85         super(configuration, configuration.docPaths.forClass(annotationType));
  86         this.annotationType = annotationType;
  87         configuration.currentTypeElement = annotationType;
  88         this.prev = prevType;
  89         this.next = nextType;
  90     }
  91 
  92     /**
  93      * Get the module link.
  94      *
  95      * @return a content tree for the module link
  96      */
  97     @Override
  98     protected Content getNavLinkModule() {
  99         Content linkContent = getModuleLink(utils.elementUtils.getModuleOf(annotationType),
 100                 contents.moduleLabel);
 101         Content li = HtmlTree.LI(linkContent);
 102         return li;
 103     }
 104 
 105     /**
 106      * Get this package link.
 107      *
 108      * @return a content tree for the package link
 109      */
 110     @Override
 111     protected Content getNavLinkPackage() {
 112         Content linkContent = links.createLink(DocPaths.PACKAGE_SUMMARY,
 113                 contents.packageLabel);
 114         Content li = HtmlTree.LI(linkContent);
 115         return li;
 116     }
 117 
 118     /**
 119      * Get the class link.
 120      *
 121      * @return a content tree for the class link
 122      */
 123     @Override
 124     protected Content getNavLinkClass() {
 125         Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, contents.classLabel);
 126         return li;
 127     }
 128 
 129     /**
 130      * Get the class use link.
 131      *
 132      * @return a content tree for the class use link
 133      */
 134     @Override
 135     protected Content getNavLinkClassUse() {
 136         Content linkContent = links.createLink(DocPaths.CLASS_USE.resolve(filename), contents.useLabel);
 137         Content li = HtmlTree.LI(linkContent);
 138         return li;
 139     }
 140 
 141     /**
 142      * Get link to previous class.
 143      *
 144      * @return a content tree for the previous class link
 145      */
 146     @Override
 147     public Content getNavLinkPrevious() {
 148         Content li;
 149         if (prev != null) {
 150             Content prevLink = getLink(new LinkInfoImpl(configuration,
 151                     LinkInfoImpl.Kind.CLASS, utils.asTypeElement(prev))
 152                     .label(contents.prevClassLabel).strong(true));
 153             li = HtmlTree.LI(prevLink);
 154         }
 155         else
 156             li = HtmlTree.LI(contents.prevClassLabel);
 157         return li;
 158     }
 159 
 160     /**
 161      * Get link to next class.
 162      *
 163      * @return a content tree for the next class link
 164      */
 165     @Override
 166     public Content getNavLinkNext() {
 167         Content li;
 168         if (next != null) {
 169             Content nextLink = getLink(new LinkInfoImpl(configuration,
 170                     LinkInfoImpl.Kind.CLASS, utils.asTypeElement(next))
 171                     .label(contents.nextClassLabel).strong(true));
 172             li = HtmlTree.LI(nextLink);
 173         }
 174         else
 175             li = HtmlTree.LI(contents.nextClassLabel);
 176         return li;
 177     }
 178 
 179     /**
 180      * {@inheritDoc}
 181      */
 182     @Override
 183     public Content getHeader(String header) {
 184         HtmlTree bodyTree = getBody(true, getWindowTitle(utils.getSimpleName(annotationType)));
 185         HtmlTree htmlTree = (configuration.allowTag(HtmlTag.HEADER))
 186                 ? HtmlTree.HEADER()
 187                 : bodyTree;
 188         addTop(htmlTree);
 189         addNavLinks(true, htmlTree);
 190         if (configuration.allowTag(HtmlTag.HEADER)) {
 191             bodyTree.addContent(htmlTree);
 192         }
 193         bodyTree.addContent(HtmlConstants.START_OF_CLASS_DATA);
 194         HtmlTree div = new HtmlTree(HtmlTag.DIV);
 195         div.setStyle(HtmlStyle.header);
 196         if (configuration.showModules) {
 197             ModuleElement mdle = configuration.docEnv.getElementUtils().getModuleOf(annotationType);
 198             Content typeModuleLabel = HtmlTree.SPAN(HtmlStyle.moduleLabelInType, contents.moduleLabel);
 199             Content moduleNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, typeModuleLabel);
 200             moduleNameDiv.addContent(Contents.SPACE);
 201             moduleNameDiv.addContent(getModuleLink(mdle, new StringContent(mdle.getQualifiedName())));
 202             div.addContent(moduleNameDiv);
 203         }
 204         PackageElement pkg = utils.containingPackage(annotationType);
 205         if (!pkg.isUnnamed()) {
 206             Content typePackageLabel = HtmlTree.SPAN(HtmlStyle.packageLabelInType, contents.packageLabel);
 207             Content pkgNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, typePackageLabel);
 208             pkgNameDiv.addContent(Contents.SPACE);
 209             Content pkgNameContent = getPackageLink(pkg, new StringContent(utils.getPackageName(pkg)));
 210             pkgNameDiv.addContent(pkgNameContent);
 211             div.addContent(pkgNameDiv);
 212         }
 213         LinkInfoImpl linkInfo = new LinkInfoImpl(configuration,
 214                 LinkInfoImpl.Kind.CLASS_HEADER, annotationType);
 215         Content headerContent = new StringContent(header);
 216         Content heading = HtmlTree.HEADING(HtmlConstants.CLASS_PAGE_HEADING, true,
 217                 HtmlStyle.title, headerContent);
 218         heading.addContent(getTypeParameterLinks(linkInfo));
 219         div.addContent(heading);
 220         if (configuration.allowTag(HtmlTag.MAIN)) {
 221             mainTree.addContent(div);
 222         } else {
 223             bodyTree.addContent(div);
 224         }
 225         return bodyTree;
 226     }
 227 
 228     /**
 229      * {@inheritDoc}
 230      */
 231     @Override
 232     public Content getAnnotationContentHeader() {
 233         return getContentHeader();
 234     }
 235 
 236     /**
 237      * {@inheritDoc}
 238      */
 239     @Override
 240     public void addFooter(Content contentTree) {
 241         contentTree.addContent(HtmlConstants.END_OF_CLASS_DATA);
 242         Content htmlTree = (configuration.allowTag(HtmlTag.FOOTER))
 243                 ? HtmlTree.FOOTER()
 244                 : contentTree;
 245         addNavLinks(false, htmlTree);
 246         addBottom(htmlTree);
 247         if (configuration.allowTag(HtmlTag.FOOTER)) {
 248             contentTree.addContent(htmlTree);
 249         }
 250     }
 251 
 252     /**
 253      * {@inheritDoc}
 254      */
 255     @Override
 256     public void printDocument(Content contentTree) throws DocFileIOException {
 257         printHtmlDocument(configuration.metakeywords.getMetaKeywords(annotationType),
 258                 true, contentTree);
 259     }
 260 
 261     /**
 262      * {@inheritDoc}
 263      */
 264     @Override
 265     public Content getAnnotationInfoTreeHeader() {
 266         return getMemberTreeHeader();
 267     }
 268 
 269     /**
 270      * {@inheritDoc}
 271      */
 272     @Override
 273     public Content getAnnotationInfo(Content annotationInfoTree) {
 274         return getMemberTree(HtmlStyle.description, annotationInfoTree);
 275     }
 276 
 277     /**
 278      * {@inheritDoc}
 279      */
 280     @Override
 281     public void addAnnotationTypeSignature(String modifiers, Content annotationInfoTree) {
 282         Content hr = new HtmlTree(HtmlTag.HR);
 283         annotationInfoTree.addContent(hr);
 284         Content pre = new HtmlTree(HtmlTag.PRE);
 285         addAnnotationInfo(annotationType, pre);
 286         pre.addContent(modifiers);
 287         LinkInfoImpl linkInfo = new LinkInfoImpl(configuration,
 288                 LinkInfoImpl.Kind.CLASS_SIGNATURE, annotationType);
 289         Content annotationName = new StringContent(utils.getSimpleName(annotationType));
 290         Content parameterLinks = getTypeParameterLinks(linkInfo);
 291         if (configuration.linksource) {
 292             addSrcLink(annotationType, annotationName, pre);
 293             pre.addContent(parameterLinks);
 294         } else {
 295             Content span = HtmlTree.SPAN(HtmlStyle.memberNameLabel, annotationName);
 296             span.addContent(parameterLinks);
 297             pre.addContent(span);
 298         }
 299         annotationInfoTree.addContent(pre);
 300     }
 301 
 302     /**
 303      * {@inheritDoc}
 304      */
 305     @Override
 306     public void addAnnotationTypeDescription(Content annotationInfoTree) {
 307         if (!configuration.nocomment) {
 308             if (!utils.getFullBody(annotationType).isEmpty()) {
 309                 addInlineComment(annotationType, annotationInfoTree);
 310             }
 311         }
 312     }
 313 
 314     /**
 315      * {@inheritDoc}
 316      */
 317     @Override
 318     public void addAnnotationTypeTagInfo(Content annotationInfoTree) {
 319         if (!configuration.nocomment) {
 320             addTagsInfo(annotationType, annotationInfoTree);
 321         }
 322     }
 323 
 324     /**
 325      * {@inheritDoc}
 326      */
 327     @Override
 328     public void addAnnotationTypeDeprecationInfo(Content annotationInfoTree) {
 329         List<? extends DocTree> deprs = utils.getBlockTags(annotationType, DocTree.Kind.DEPRECATED);
 330         if (utils.isDeprecated(annotationType)) {
 331             CommentHelper ch = utils.getCommentHelper(annotationType);
 332             Content deprLabel = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, getDeprecatedPhrase(annotationType));
 333             Content div = HtmlTree.DIV(HtmlStyle.deprecationBlock, deprLabel);
 334             if (!deprs.isEmpty()) {
 335 
 336                 List<? extends DocTree> commentTags = ch.getDescription(configuration, deprs.get(0));
 337                 if (!commentTags.isEmpty()) {
 338                     addInlineDeprecatedComment(annotationType, deprs.get(0), div);
 339                 }
 340             }
 341             annotationInfoTree.addContent(div);
 342         }
 343     }
 344 
 345     /**
 346      * {@inheritDoc}
 347      */
 348     @Override
 349     protected Content getNavLinkTree() {
 350         Content treeLinkContent = links.createLink(DocPaths.PACKAGE_TREE,
 351                 contents.treeLabel, "", "");
 352         Content li = HtmlTree.LI(treeLinkContent);
 353         return li;
 354     }
 355 
 356     /**
 357      * Add summary details to the navigation bar.
 358      *
 359      * @param subDiv the content tree to which the summary detail links will be added
 360      */
 361     @Override
 362     protected void addSummaryDetailLinks(Content subDiv) {
 363         Content div = HtmlTree.DIV(getNavSummaryLinks());
 364         div.addContent(getNavDetailLinks());
 365         subDiv.addContent(div);
 366     }
 367 
 368     /**
 369      * Get summary links for navigation bar.
 370      *
 371      * @return the content tree for the navigation summary links
 372      */
 373     protected Content getNavSummaryLinks() {
 374         Content li = HtmlTree.LI(contents.summaryLabel);
 375         li.addContent(Contents.SPACE);
 376         Content ulNav = HtmlTree.UL(HtmlStyle.subNavList, li);
 377         MemberSummaryBuilder memberSummaryBuilder =
 378                 configuration.getBuilderFactory().getMemberSummaryBuilder(this);
 379         Content liNavField = new HtmlTree(HtmlTag.LI);
 380         addNavSummaryLink(memberSummaryBuilder,
 381                 "doclet.navField",
 382                 VisibleMemberMap.Kind.ANNOTATION_TYPE_FIELDS, liNavField);
 383         addNavGap(liNavField);
 384         ulNav.addContent(liNavField);
 385         Content liNavReq = new HtmlTree(HtmlTag.LI);
 386         addNavSummaryLink(memberSummaryBuilder,
 387                 "doclet.navAnnotationTypeRequiredMember",
 388                 VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_REQUIRED, liNavReq);
 389         addNavGap(liNavReq);
 390         ulNav.addContent(liNavReq);
 391         Content liNavOpt = new HtmlTree(HtmlTag.LI);
 392         addNavSummaryLink(memberSummaryBuilder,
 393                 "doclet.navAnnotationTypeOptionalMember",
 394                 VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_OPTIONAL, liNavOpt);
 395         ulNav.addContent(liNavOpt);
 396         return ulNav;
 397     }
 398 
 399     /**
 400      * Add the navigation summary link.
 401      *
 402      * @param builder builder for the member to be documented
 403      * @param label the label for the navigation
 404      * @param type type to be documented
 405      * @param liNav the content tree to which the navigation summary link will be added
 406      */
 407     protected void addNavSummaryLink(MemberSummaryBuilder builder,
 408             String label, VisibleMemberMap.Kind type, Content liNav) {
 409         AbstractMemberWriter writer = ((AbstractMemberWriter) builder.
 410                 getMemberSummaryWriter(type));
 411         if (writer == null) {
 412             liNav.addContent(contents.getContent(label));
 413         } else {
 414             liNav.addContent(writer.getNavSummaryLink(null,
 415                     ! builder.getVisibleMemberMap(type).noVisibleMembers()));
 416         }
 417     }
 418 
 419     /**
 420      * Get detail links for the navigation bar.
 421      *
 422      * @return the content tree for the detail links
 423      */
 424     protected Content getNavDetailLinks() {
 425         Content li = HtmlTree.LI(contents.detailLabel);
 426         li.addContent(Contents.SPACE);
 427         Content ulNav = HtmlTree.UL(HtmlStyle.subNavList, li);
 428         MemberSummaryBuilder memberSummaryBuilder =
 429                 configuration.getBuilderFactory().getMemberSummaryBuilder(this);
 430         AbstractMemberWriter writerField =
 431                 ((AbstractMemberWriter) memberSummaryBuilder.
 432                 getMemberSummaryWriter(VisibleMemberMap.Kind.ANNOTATION_TYPE_FIELDS));
 433         AbstractMemberWriter writerOptional =
 434                 ((AbstractMemberWriter) memberSummaryBuilder.
 435                 getMemberSummaryWriter(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_OPTIONAL));
 436         AbstractMemberWriter writerRequired =
 437                 ((AbstractMemberWriter) memberSummaryBuilder.
 438                 getMemberSummaryWriter(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_REQUIRED));
 439         Content liNavField = new HtmlTree(HtmlTag.LI);
 440         if (writerField != null) {
 441             writerField.addNavDetailLink(!utils.getAnnotationFields(annotationType).isEmpty(), liNavField);
 442         } else {
 443             liNavField.addContent(contents.navField);
 444         }
 445         addNavGap(liNavField);
 446         ulNav.addContent(liNavField);
 447         if (writerOptional != null){
 448             Content liNavOpt = new HtmlTree(HtmlTag.LI);
 449             writerOptional.addNavDetailLink(!annotationType.getAnnotationMirrors().isEmpty(), liNavOpt);
 450             ulNav.addContent(liNavOpt);
 451         } else if (writerRequired != null){
 452             Content liNavReq = new HtmlTree(HtmlTag.LI);
 453             writerRequired.addNavDetailLink(!annotationType.getAnnotationMirrors().isEmpty(), liNavReq);
 454             ulNav.addContent(liNavReq);
 455         } else {
 456             Content liNav = HtmlTree.LI(contents.navAnnotationTypeMember);
 457             ulNav.addContent(liNav);
 458         }
 459         return ulNav;
 460     }
 461 
 462     /**
 463      * {@inheritDoc}
 464      */
 465     @Override
 466     public TypeElement getAnnotationTypeElement() {
 467         return annotationType;
 468     }
 469 }