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 jdk.javadoc.internal.doclets.formats.html.markup.Table;
  29 import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
  30 
  31 import java.util.*;
  32 
  33 import javax.lang.model.element.ModuleElement;
  34 import javax.lang.model.element.PackageElement;
  35 import javax.lang.model.element.TypeElement;
  36 
  37 import com.sun.source.doctree.DocTree;
  38 import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
  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.Content;
  46 import jdk.javadoc.internal.doclets.toolkit.PackageSummaryWriter;
  47 import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper;
  48 import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
  49 import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
  50 import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
  51 
  52 /**
  53  * Class to generate file for each package contents in the right-hand
  54  * frame. This will list all the Class Kinds in the package. A click on any
  55  * class-kind will update the frame with the clicked class-kind page.
  56  *
  57  *  <p><b>This is NOT part of any supported API.
  58  *  If you write code that depends on this, you do so at your own risk.
  59  *  This code and its internal interfaces are subject to change or
  60  *  deletion without notice.</b>
  61  *
  62  * @author Atul M Dambalkar
  63  * @author Bhavesh Patel (Modified)
  64  */
  65 public class PackageWriterImpl extends HtmlDocletWriter
  66     implements PackageSummaryWriter {
  67 
  68     /**
  69      * The prev package name in the alpha-order list.
  70      */
  71     protected PackageElement prev;
  72 
  73     /**
  74      * The next package name in the alpha-order list.
  75      */
  76     protected PackageElement next;
  77 
  78     /**
  79      * The package being documented.
  80      */
  81     protected PackageElement packageElement;
  82 
  83     /**
  84      * The HTML tree for main tag.
  85      */
  86     protected HtmlTree mainTree = HtmlTree.MAIN();
  87 
  88     /**
  89      * The HTML tree for section tag.
  90      */
  91     protected HtmlTree sectionTree = HtmlTree.SECTION();
  92 
  93     /**
  94      * Constructor to construct PackageWriter object and to generate
  95      * "package-summary.html" file in the respective package directory.
  96      * For example for package "java.lang" this will generate file
  97      * "package-summary.html" file in the "java/lang" directory. It will also
  98      * create "java/lang" directory in the current or the destination directory
  99      * if it doesn't exist.
 100      *
 101      * @param configuration the configuration of the doclet.
 102      * @param packageElement    PackageElement under consideration.
 103      * @param prev          Previous package in the sorted array.
 104      * @param next            Next package in the sorted array.
 105      */
 106     public PackageWriterImpl(HtmlConfiguration configuration,
 107             PackageElement packageElement, PackageElement prev, PackageElement next) {
 108         super(configuration, 
 109                 configuration.docPaths.forPackage(packageElement)
 110                 .resolve(DocPaths.PACKAGE_SUMMARY));
 111         this.prev = prev;
 112         this.next = next;
 113         this.packageElement = packageElement;
 114     }
 115 
 116     /**
 117      * {@inheritDoc}
 118      */
 119     @Override
 120     public Content getPackageHeader(String heading) {
 121         HtmlTree bodyTree = getBody(true, getWindowTitle(utils.getPackageName(packageElement)));
 122         HtmlTree htmlTree = (configuration.allowTag(HtmlTag.HEADER))
 123                 ? HtmlTree.HEADER()
 124                 : bodyTree;
 125         addTop(htmlTree);
 126         addNavLinks(true, htmlTree);
 127         if (configuration.allowTag(HtmlTag.HEADER)) {
 128             bodyTree.addContent(htmlTree);
 129         }
 130         HtmlTree div = new HtmlTree(HtmlTag.DIV);
 131         div.setStyle(HtmlStyle.header);
 132         if (configuration.showModules) {
 133             ModuleElement mdle = configuration.docEnv.getElementUtils().getModuleOf(packageElement);
 134             Content classModuleLabel = HtmlTree.SPAN(HtmlStyle.moduleLabelInPackage, contents.moduleLabel);
 135             Content moduleNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, classModuleLabel);
 136             moduleNameDiv.addContent(Contents.SPACE);
 137             moduleNameDiv.addContent(getModuleLink(mdle,
 138                     new StringContent(mdle.getQualifiedName().toString())));
 139             div.addContent(moduleNameDiv);
 140         }
 141         Content annotationContent = new HtmlTree(HtmlTag.P);
 142         addAnnotationInfo(packageElement, annotationContent);
 143         div.addContent(annotationContent);
 144         Content tHeading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, true,
 145                 HtmlStyle.title, contents.packageLabel);
 146         tHeading.addContent(Contents.SPACE);
 147         Content packageHead = new StringContent(heading);
 148         tHeading.addContent(packageHead);
 149         div.addContent(tHeading);
 150         if (configuration.allowTag(HtmlTag.MAIN)) {
 151             mainTree.addContent(div);
 152         } else {
 153             bodyTree.addContent(div);
 154         }
 155         return bodyTree;
 156     }
 157 
 158     /**
 159      * {@inheritDoc}
 160      */
 161     @Override
 162     public Content getContentHeader() {
 163         HtmlTree div = new HtmlTree(HtmlTag.DIV);
 164         div.setStyle(HtmlStyle.contentContainer);
 165         return div;
 166     }
 167 
 168     /**
 169      * Add the package deprecation information to the documentation tree.
 170      *
 171      * @param div the content tree to which the deprecation information will be added
 172      */
 173     public void addDeprecationInfo(Content div) {
 174         List<? extends DocTree> deprs = utils.getBlockTags(packageElement, DocTree.Kind.DEPRECATED);
 175         if (utils.isDeprecated(packageElement)) {
 176             CommentHelper ch = utils.getCommentHelper(packageElement);
 177             HtmlTree deprDiv = new HtmlTree(HtmlTag.DIV);
 178             deprDiv.setStyle(HtmlStyle.deprecationBlock);
 179             Content deprPhrase = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, getDeprecatedPhrase(packageElement));
 180             deprDiv.addContent(deprPhrase);
 181             if (!deprs.isEmpty()) {
 182                 List<? extends DocTree> commentTags = ch.getDescription(configuration, deprs.get(0));
 183                 if (!commentTags.isEmpty()) {
 184                     addInlineDeprecatedComment(packageElement, deprs.get(0), deprDiv);
 185                 }
 186             }
 187             div.addContent(deprDiv);
 188         }
 189     }
 190 
 191     /**
 192      * {@inheritDoc}
 193      */
 194     @Override
 195     public Content getSummaryHeader() {
 196         HtmlTree ul = new HtmlTree(HtmlTag.UL);
 197         ul.setStyle(HtmlStyle.blockList);
 198         return ul;
 199     }
 200 
 201     /**
 202      * {@inheritDoc}
 203      */
 204     @Override
 205     public void addInterfaceSummary(SortedSet<TypeElement> interfaces, Content summaryContentTree) {
 206         String label = resources.getText("doclet.Interface_Summary");
 207         String tableSummary = resources.getText("doclet.Member_Table_Summary",
 208                         resources.getText("doclet.Interface_Summary"),
 209                         resources.getText("doclet.interfaces"));
 210         TableHeader tableHeader= new TableHeader(contents.interfaceLabel, contents.descriptionLabel);
 211 
 212         addClassesSummary(interfaces, label, tableSummary, tableHeader, summaryContentTree);
 213     }
 214 
 215     /**
 216      * {@inheritDoc}
 217      */
 218     @Override
 219     public void addClassSummary(SortedSet<TypeElement> classes, Content summaryContentTree) {
 220         String label = resources.getText("doclet.Class_Summary");
 221         String tableSummary = resources.getText("doclet.Member_Table_Summary",
 222                         resources.getText("doclet.Class_Summary"),
 223                         resources.getText("doclet.classes"));
 224         TableHeader tableHeader= new TableHeader(contents.classLabel, contents.descriptionLabel);
 225 
 226         addClassesSummary(classes, label, tableSummary, tableHeader, summaryContentTree);
 227     }
 228 
 229     /**
 230      * {@inheritDoc}
 231      */
 232     @Override
 233     public void addEnumSummary(SortedSet<TypeElement> enums, Content summaryContentTree) {
 234         String label = resources.getText("doclet.Enum_Summary");
 235         String tableSummary = resources.getText("doclet.Member_Table_Summary",
 236                         resources.getText("doclet.Enum_Summary"),
 237                         resources.getText("doclet.enums"));
 238         TableHeader tableHeader= new TableHeader(contents.enum_, contents.descriptionLabel);
 239 
 240         addClassesSummary(enums, label, tableSummary, tableHeader, summaryContentTree);
 241     }
 242 
 243     /**
 244      * {@inheritDoc}
 245      */
 246     @Override
 247     public void addExceptionSummary(SortedSet<TypeElement> exceptions, Content summaryContentTree) {
 248         String label = resources.getText("doclet.Exception_Summary");
 249         String tableSummary = resources.getText("doclet.Member_Table_Summary",
 250                         resources.getText("doclet.Exception_Summary"),
 251                         resources.getText("doclet.exceptions"));
 252         TableHeader tableHeader= new TableHeader(contents.exception, contents.descriptionLabel);
 253 
 254         addClassesSummary(exceptions, label, tableSummary, tableHeader, summaryContentTree);
 255     }
 256 
 257     /**
 258      * {@inheritDoc}
 259      */
 260     @Override
 261     public void addErrorSummary(SortedSet<TypeElement> errors, Content summaryContentTree) {
 262         String label = resources.getText("doclet.Error_Summary");
 263         String tableSummary = resources.getText("doclet.Member_Table_Summary",
 264                         resources.getText("doclet.Error_Summary"),
 265                         resources.getText("doclet.errors"));
 266         TableHeader tableHeader= new TableHeader(contents.error, contents.descriptionLabel);
 267 
 268         addClassesSummary(errors, label, tableSummary, tableHeader, summaryContentTree);
 269     }
 270 
 271     /**
 272      * {@inheritDoc}
 273      */
 274     @Override
 275     public void addAnnotationTypeSummary(SortedSet<TypeElement> annoTypes, Content summaryContentTree) {
 276         String label = resources.getText("doclet.Annotation_Types_Summary");
 277         String tableSummary = resources.getText("doclet.Member_Table_Summary",
 278                         resources.getText("doclet.Annotation_Types_Summary"),
 279                         resources.getText("doclet.annotationtypes"));
 280         TableHeader tableHeader= new TableHeader(contents.annotationType, contents.descriptionLabel);
 281 
 282         addClassesSummary(annoTypes, label, tableSummary, tableHeader, summaryContentTree);
 283     }
 284 
 285     public void addClassesSummary(SortedSet<TypeElement> classes, String label,
 286             String tableSummary, TableHeader tableHeader, Content summaryContentTree) {
 287         if(!classes.isEmpty()) {
 288             Table table = new Table(configuration.htmlVersion, HtmlStyle.typeSummary)
 289                     .setSummary(tableSummary)
 290                     .setCaption(getTableCaption(new StringContent(label)))
 291                     .setHeader(tableHeader)
 292                     .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colLast);
 293 
 294             for (TypeElement klass : classes) {
 295                 if (!utils.isCoreClass(klass) || !configuration.isGeneratedDoc(klass)) {
 296                     continue;
 297                 }
 298                 Content classLink = getLink(new LinkInfoImpl(
 299                         configuration, LinkInfoImpl.Kind.PACKAGE, klass));
 300                 ContentBuilder description = new ContentBuilder();
 301                 if (utils.isDeprecated(klass)) {
 302                     description.addContent(getDeprecatedPhrase(klass));
 303                     List<? extends DocTree> tags = utils.getDeprecatedTrees(klass);
 304                     if (!tags.isEmpty()) {
 305                         addSummaryDeprecatedComment(klass, tags.get(0), description);
 306                     }
 307                 } else {
 308                     addSummaryComment(klass, description);
 309                 }
 310                 table.addRow(classLink, description);
 311             }
 312             Content li = HtmlTree.LI(HtmlStyle.blockList, table.toContent());
 313             summaryContentTree.addContent(li);
 314         }
 315     }
 316 
 317     /**
 318      * {@inheritDoc}
 319      */
 320     @Override
 321     public void addPackageDescription(Content packageContentTree) {
 322         if (!utils.getBody(packageElement).isEmpty()) {
 323             Content tree = configuration.allowTag(HtmlTag.SECTION) ? sectionTree : packageContentTree;
 324             tree.addContent(links.createAnchor(SectionName.PACKAGE_DESCRIPTION));
 325             addDeprecationInfo(tree);
 326             addInlineComment(packageElement, tree);
 327         }
 328     }
 329 
 330     /**
 331      * {@inheritDoc}
 332      */
 333     @Override
 334     public void addPackageTags(Content packageContentTree) {
 335         Content htmlTree = (configuration.allowTag(HtmlTag.SECTION))
 336                 ? sectionTree
 337                 : packageContentTree;
 338         addTagsInfo(packageElement, htmlTree);
 339         if (configuration.allowTag(HtmlTag.SECTION)) {
 340             packageContentTree.addContent(sectionTree);
 341         }
 342     }
 343 
 344     /**
 345      * {@inheritDoc}
 346      */
 347     @Override
 348     public void addPackageContent(Content contentTree, Content packageContentTree) {
 349         if (configuration.allowTag(HtmlTag.MAIN)) {
 350             mainTree.addContent(packageContentTree);
 351             contentTree.addContent(mainTree);
 352         } else {
 353             contentTree.addContent(packageContentTree);
 354         }
 355     }
 356 
 357     /**
 358      * {@inheritDoc}
 359      */
 360     @Override
 361     public void addPackageFooter(Content contentTree) {
 362         Content htmlTree = (configuration.allowTag(HtmlTag.FOOTER))
 363                 ? HtmlTree.FOOTER()
 364                 : contentTree;
 365         addNavLinks(false, htmlTree);
 366         addBottom(htmlTree);
 367         if (configuration.allowTag(HtmlTag.FOOTER)) {
 368             contentTree.addContent(htmlTree);
 369         }
 370     }
 371 
 372     /**
 373      * {@inheritDoc}
 374      */
 375     @Override
 376     public void printDocument(Content contentTree) throws DocFileIOException {
 377         printHtmlDocument(configuration.metakeywords.getMetaKeywords(packageElement),
 378                 true, contentTree);
 379     }
 380 
 381     /**
 382      * Get "Use" link for this pacakge in the navigation bar.
 383      *
 384      * @return a content tree for the class use link
 385      */
 386     @Override
 387     protected Content getNavLinkClassUse() {
 388         Content useLink = links.createLink(DocPaths.PACKAGE_USE,
 389                 contents.useLabel, "", "");
 390         Content li = HtmlTree.LI(useLink);
 391         return li;
 392     }
 393 
 394     /**
 395      * Get "PREV PACKAGE" link in the navigation bar.
 396      *
 397      * @return a content tree for the previous link
 398      */
 399     @Override
 400     public Content getNavLinkPrevious() {
 401         Content li;
 402         if (prev == null) {
 403             li = HtmlTree.LI(contents.prevPackageLabel);
 404         } else {
 405             DocPath p = docPaths.relativePath(packageElement, prev);
 406             li = HtmlTree.LI(links.createLink(p.resolve(DocPaths.PACKAGE_SUMMARY),
 407                 contents.prevPackageLabel, "", ""));
 408         }
 409         return li;
 410     }
 411 
 412     /**
 413      * Get "NEXT PACKAGE" link in the navigation bar.
 414      *
 415      * @return a content tree for the next link
 416      */
 417     @Override
 418     public Content getNavLinkNext() {
 419         Content li;
 420         if (next == null) {
 421             li = HtmlTree.LI(contents.nextPackageLabel);
 422         } else {
 423             DocPath p = docPaths.relativePath(packageElement, next);
 424             li = HtmlTree.LI(links.createLink(p.resolve(DocPaths.PACKAGE_SUMMARY),
 425                 contents.nextPackageLabel, "", ""));
 426         }
 427         return li;
 428     }
 429 
 430     /**
 431      * Get "Tree" link in the navigation bar. This will be link to the package
 432      * tree file.
 433      *
 434      * @return a content tree for the tree link
 435      */
 436     @Override
 437     protected Content getNavLinkTree() {
 438         Content useLink = links.createLink(DocPaths.PACKAGE_TREE,
 439                 contents.treeLabel, "", "");
 440         Content li = HtmlTree.LI(useLink);
 441         return li;
 442     }
 443 
 444     /**
 445      * Get the module link.
 446      *
 447      * @return a content tree for the module link
 448      */
 449     @Override
 450     protected Content getNavLinkModule() {
 451         Content linkContent = getModuleLink(utils.elementUtils.getModuleOf(packageElement),
 452                 contents.moduleLabel);
 453         Content li = HtmlTree.LI(linkContent);
 454         return li;
 455     }
 456 
 457     /**
 458      * Highlight "Package" in the navigation bar, as this is the package page.
 459      *
 460      * @return a content tree for the package link
 461      */
 462     @Override
 463     protected Content getNavLinkPackage() {
 464         Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, contents.packageLabel);
 465         return li;
 466     }
 467 }