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