1 /*
   2  * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package jdk.javadoc.internal.doclets.formats.html;
  27 
  28 import java.util.List;
  29 import java.util.SortedSet;
  30 
  31 import javax.lang.model.element.ModuleElement;
  32 import javax.lang.model.element.PackageElement;
  33 import javax.lang.model.element.TypeElement;
  34 
  35 import com.sun.source.doctree.DocTree;
  36 import jdk.javadoc.internal.doclets.formats.html.markup.BodyContents;
  37 import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
  38 import jdk.javadoc.internal.doclets.formats.html.markup.Entity;
  39 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
  40 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
  41 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
  42 import jdk.javadoc.internal.doclets.formats.html.markup.Navigation;
  43 import jdk.javadoc.internal.doclets.formats.html.markup.Navigation.PageMode;
  44 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
  45 import jdk.javadoc.internal.doclets.formats.html.markup.Table;
  46 import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
  47 import jdk.javadoc.internal.doclets.toolkit.Content;
  48 import jdk.javadoc.internal.doclets.toolkit.PackageSummaryWriter;
  49 import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper;
  50 import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
  51 import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
  52 import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
  53 
  54 /**
  55  * Class to generate file for each package contents in the right-hand
  56  * frame. This will list all the Class Kinds in the package. A click on any
  57  * class-kind will update the frame with the clicked class-kind page.
  58  *
  59  *  <p><b>This is NOT part of any supported API.
  60  *  If you write code that depends on this, you do so at your own risk.
  61  *  This code and its internal interfaces are subject to change or
  62  *  deletion without notice.</b>
  63  */
  64 public class PackageWriterImpl extends HtmlDocletWriter
  65     implements PackageSummaryWriter {
  66 
  67     /**
  68      * The package being documented.
  69      */
  70     protected PackageElement packageElement;
  71 
  72     /**
  73      * The HTML tree for section tag.
  74      */
  75     protected HtmlTree sectionTree = HtmlTree.SECTION(HtmlStyle.packageDescription, new ContentBuilder());
  76 
  77     private final Navigation navBar;
  78 
  79     private final BodyContents bodyContents = new BodyContents();
  80 
  81     /**
  82      * Constructor to construct PackageWriter object and to generate
  83      * "package-summary.html" file in the respective package directory.
  84      * For example for package "java.lang" this will generate file
  85      * "package-summary.html" file in the "java/lang" directory. It will also
  86      * create "java/lang" directory in the current or the destination directory
  87      * if it doesn't exist.
  88      *
  89      * @param configuration the configuration of the doclet.
  90      * @param packageElement    PackageElement under consideration.
  91      */
  92     public PackageWriterImpl(HtmlConfiguration configuration, PackageElement packageElement) {
  93         super(configuration,
  94                 configuration.docPaths.forPackage(packageElement)
  95                 .resolve(DocPaths.PACKAGE_SUMMARY));
  96         this.packageElement = packageElement;
  97         this.navBar = new Navigation(packageElement, configuration, PageMode.PACKAGE, path);
  98     }
  99 
 100     /**
 101      * {@inheritDoc}
 102      */
 103     @Override
 104     public Content getPackageHeader(String heading) {
 105         HtmlTree bodyTree = getBody(getWindowTitle(utils.getPackageName(packageElement)));
 106         Content headerContent = new ContentBuilder();
 107         addTop(headerContent);
 108         Content linkContent = getModuleLink(utils.elementUtils.getModuleOf(packageElement),
 109                 contents.moduleLabel);
 110         navBar.setNavLinkModule(linkContent);
 111         navBar.setUserHeader(getUserHeaderFooter(true));
 112         headerContent.add(navBar.getContent(true));
 113         HtmlTree div = new HtmlTree(HtmlTag.DIV);
 114         div.setStyle(HtmlStyle.header);
 115         if (configuration.showModules) {
 116             ModuleElement mdle = configuration.docEnv.getElementUtils().getModuleOf(packageElement);
 117             Content classModuleLabel = HtmlTree.SPAN(HtmlStyle.moduleLabelInPackage, contents.moduleLabel);
 118             Content moduleNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, classModuleLabel);
 119             moduleNameDiv.add(Entity.NO_BREAK_SPACE);
 120             moduleNameDiv.add(getModuleLink(mdle,
 121                     new StringContent(mdle.getQualifiedName().toString())));
 122             div.add(moduleNameDiv);
 123         }
 124         Content annotationContent = new HtmlTree(HtmlTag.P);
 125         addAnnotationInfo(packageElement, annotationContent);
 126         div.add(annotationContent);
 127         Content tHeading = HtmlTree.HEADING(Headings.PAGE_TITLE_HEADING, true,
 128                 HtmlStyle.title, contents.packageLabel);
 129         tHeading.add(Entity.NO_BREAK_SPACE);
 130         Content packageHead = new StringContent(heading);
 131         tHeading.add(packageHead);
 132         div.add(tHeading);
 133         bodyContents.setHeader(headerContent)
 134                 .addMainContent(div);
 135         return bodyTree;
 136     }
 137 
 138     /**
 139      * {@inheritDoc}
 140      */
 141     @Override
 142     public Content getContentHeader() {
 143         HtmlTree div = new HtmlTree(HtmlTag.DIV);
 144         div.setStyle(HtmlStyle.contentContainer);
 145         return div;
 146     }
 147 
 148     /**
 149      * Add the package deprecation information to the documentation tree.
 150      *
 151      * @param div the content tree to which the deprecation information will be added
 152      */
 153     public void addDeprecationInfo(Content div) {
 154         List<? extends DocTree> deprs = utils.getBlockTags(packageElement, DocTree.Kind.DEPRECATED);
 155         if (utils.isDeprecated(packageElement)) {
 156             CommentHelper ch = utils.getCommentHelper(packageElement);
 157             HtmlTree deprDiv = new HtmlTree(HtmlTag.DIV);
 158             deprDiv.setStyle(HtmlStyle.deprecationBlock);
 159             Content deprPhrase = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, getDeprecatedPhrase(packageElement));
 160             deprDiv.add(deprPhrase);
 161             if (!deprs.isEmpty()) {
 162                 List<? extends DocTree> commentTags = ch.getDescription(configuration, deprs.get(0));
 163                 if (!commentTags.isEmpty()) {
 164                     addInlineDeprecatedComment(packageElement, deprs.get(0), deprDiv);
 165                 }
 166             }
 167             div.add(deprDiv);
 168         }
 169     }
 170 
 171     /**
 172      * {@inheritDoc}
 173      */
 174     @Override
 175     public Content getSummaryHeader() {
 176         HtmlTree ul = new HtmlTree(HtmlTag.UL);
 177         ul.setStyle(HtmlStyle.blockList);
 178         return ul;
 179     }
 180 
 181     /**
 182      * {@inheritDoc}
 183      */
 184     @Override
 185     public void addInterfaceSummary(SortedSet<TypeElement> interfaces, Content summaryContentTree) {
 186         TableHeader tableHeader= new TableHeader(contents.interfaceLabel, contents.descriptionLabel);
 187         addClassesSummary(interfaces, resources.interfaceSummary, tableHeader, summaryContentTree);
 188     }
 189 
 190     /**
 191      * {@inheritDoc}
 192      */
 193     @Override
 194     public void addClassSummary(SortedSet<TypeElement> classes, Content summaryContentTree) {
 195         TableHeader tableHeader= new TableHeader(contents.classLabel, contents.descriptionLabel);
 196         addClassesSummary(classes, resources.classSummary, tableHeader, summaryContentTree);
 197     }
 198 
 199     /**
 200      * {@inheritDoc}
 201      */
 202     @Override
 203     public void addEnumSummary(SortedSet<TypeElement> enums, Content summaryContentTree) {
 204         TableHeader tableHeader= new TableHeader(contents.enum_, contents.descriptionLabel);
 205         addClassesSummary(enums, resources.enumSummary, tableHeader, summaryContentTree);
 206     }
 207 
 208     /**
 209      * {@inheritDoc}
 210      */
 211     @Override
 212     public void addRecordSummary(SortedSet<TypeElement> records, Content summaryContentTree) {
 213         TableHeader tableHeader= new TableHeader(contents.record, contents.descriptionLabel);
 214         addClassesSummary(records, resources.recordSummary, tableHeader, summaryContentTree);
 215     }
 216 
 217     /**
 218      * {@inheritDoc}
 219      */
 220     @Override
 221     public void addExceptionSummary(SortedSet<TypeElement> exceptions, Content summaryContentTree) {
 222         TableHeader tableHeader= new TableHeader(contents.exception, contents.descriptionLabel);
 223         addClassesSummary(exceptions, resources.exceptionSummary, tableHeader, summaryContentTree);
 224     }
 225 
 226     /**
 227      * {@inheritDoc}
 228      */
 229     @Override
 230     public void addErrorSummary(SortedSet<TypeElement> errors, Content summaryContentTree) {
 231         TableHeader tableHeader= new TableHeader(contents.error, contents.descriptionLabel);
 232         addClassesSummary(errors, resources.errorSummary, tableHeader, summaryContentTree);
 233     }
 234 
 235     /**
 236      * {@inheritDoc}
 237      */
 238     @Override
 239     public void addAnnotationTypeSummary(SortedSet<TypeElement> annoTypes, Content summaryContentTree) {
 240         TableHeader tableHeader= new TableHeader(contents.annotationType, contents.descriptionLabel);
 241         addClassesSummary(annoTypes, resources.annotationTypeSummary, tableHeader, summaryContentTree);
 242     }
 243 
 244     public void addClassesSummary(SortedSet<TypeElement> classes, String label,
 245             TableHeader tableHeader, Content summaryContentTree) {
 246         if(!classes.isEmpty()) {
 247             Table table = new Table(HtmlStyle.typeSummary)
 248                     .setCaption(getTableCaption(new StringContent(label)))
 249                     .setHeader(tableHeader)
 250                     .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colLast);
 251 
 252             for (TypeElement klass : classes) {
 253                 if (!utils.isCoreClass(klass) || !configuration.isGeneratedDoc(klass)) {
 254                     continue;
 255                 }
 256                 Content classLink = getLink(new LinkInfoImpl(
 257                         configuration, LinkInfoImpl.Kind.PACKAGE, klass));
 258                 ContentBuilder description = new ContentBuilder();
 259                 if (utils.isDeprecated(klass)) {
 260                     description.add(getDeprecatedPhrase(klass));
 261                     List<? extends DocTree> tags = utils.getDeprecatedTrees(klass);
 262                     if (!tags.isEmpty()) {
 263                         addSummaryDeprecatedComment(klass, tags.get(0), description);
 264                     }
 265                 } else {
 266                     addSummaryComment(klass, description);
 267                 }
 268                 table.addRow(classLink, description);
 269             }
 270             Content li = HtmlTree.LI(HtmlStyle.blockList, table.toContent());
 271             summaryContentTree.add(li);
 272         }
 273     }
 274 
 275     /**
 276      * {@inheritDoc}
 277      */
 278     @Override
 279     public void addPackageDescription(Content packageContentTree) {
 280         if (!utils.getBody(packageElement).isEmpty()) {
 281             Content tree = sectionTree;
 282             tree.add(links.createAnchor(SectionName.PACKAGE_DESCRIPTION));
 283             addDeprecationInfo(tree);
 284             addInlineComment(packageElement, tree);
 285         }
 286     }
 287 
 288     /**
 289      * {@inheritDoc}
 290      */
 291     @Override
 292     public void addPackageTags(Content packageContentTree) {
 293         Content htmlTree = sectionTree;
 294         addTagsInfo(packageElement, htmlTree);
 295         packageContentTree.add(sectionTree);
 296     }
 297 
 298     /**
 299      * {@inheritDoc}
 300      */
 301     @Override
 302     public void addPackageContent(Content packageContentTree) {
 303         bodyContents.addMainContent(packageContentTree);
 304     }
 305 
 306     /**
 307      * {@inheritDoc}
 308      */
 309     @Override
 310     public void addPackageFooter() {
 311         Content htmlTree = HtmlTree.FOOTER();
 312         navBar.setUserFooter(getUserHeaderFooter(false));
 313         htmlTree.add(navBar.getContent(false));
 314         addBottom(htmlTree);
 315         bodyContents.setFooter(htmlTree);
 316     }
 317 
 318     /**
 319      * {@inheritDoc}
 320      */
 321     @Override
 322     public void printDocument(Content contentTree) throws DocFileIOException {
 323         String description = getDescription("declaration", packageElement);
 324         List<DocPath> localStylesheets = getLocalStylesheets(packageElement);
 325         contentTree.add(bodyContents.toContent());
 326         printHtmlDocument(configuration.metakeywords.getMetaKeywords(packageElement),
 327                 description, localStylesheets, contentTree);
 328     }
 329 
 330     /**
 331      * {@inheritDoc}
 332      */
 333     @Override
 334     public Content getPackageSummary(Content summaryContentTree) {
 335         return HtmlTree.SECTION(HtmlStyle.summary, summaryContentTree);
 336     }
 337 }