1 /*
   2  * Copyright (c) 1997, 2016, 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.io.*;
  29 import java.util.*;
  30 
  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.DocPath;
  45 import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
  46 
  47 /**
  48  * Class to generate file for each package contents in the right-hand
  49  * frame. This will list all the Class Kinds in the package. A click on any
  50  * class-kind will update the frame with the clicked class-kind page.
  51  *
  52  *  <p><b>This is NOT part of any supported API.
  53  *  If you write code that depends on this, you do so at your own risk.
  54  *  This code and its internal interfaces are subject to change or
  55  *  deletion without notice.</b>
  56  *
  57  * @author Atul M Dambalkar
  58  * @author Bhavesh Patel (Modified)
  59  */
  60 public class PackageWriterImpl extends HtmlDocletWriter
  61     implements PackageSummaryWriter {
  62 
  63     /**
  64      * The prev package name in the alpha-order list.
  65      */
  66     protected PackageElement prev;
  67 
  68     /**
  69      * The next package name in the alpha-order list.
  70      */
  71     protected PackageElement next;
  72 
  73     /**
  74      * The package being documented.
  75      */
  76     protected PackageElement packageElement;
  77 
  78     /**
  79      * The HTML tree for main tag.
  80      */
  81     protected HtmlTree mainTree = HtmlTree.MAIN();
  82 
  83     /**
  84      * The HTML tree for section tag.
  85      */
  86     protected HtmlTree sectionTree = HtmlTree.SECTION();
  87 
  88     /**
  89      * Constructor to construct PackageWriter object and to generate
  90      * "package-summary.html" file in the respective package directory.
  91      * For example for package "java.lang" this will generate file
  92      * "package-summary.html" file in the "java/lang" directory. It will also
  93      * create "java/lang" directory in the current or the destination directory
  94      * if it doesn't exist.
  95      *
  96      * @param configuration the configuration of the doclet.
  97      * @param packageElement    PackageElement under consideration.
  98      * @param prev          Previous package in the sorted array.
  99      * @param next            Next package in the sorted array.
 100      */
 101     public PackageWriterImpl(ConfigurationImpl configuration,
 102             PackageElement packageElement, PackageElement prev, PackageElement next)
 103             throws IOException {
 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     public Content getPackageHeader(String heading) {
 116         HtmlTree bodyTree = getBody(true, getWindowTitle(utils.getPackageName(packageElement)));
 117         HtmlTree htmlTree = (configuration.allowTag(HtmlTag.HEADER))
 118                 ? HtmlTree.HEADER()
 119                 : bodyTree;
 120         addTop(htmlTree);
 121         addNavLinks(true, htmlTree);
 122         if (configuration.allowTag(HtmlTag.HEADER)) {
 123             bodyTree.addContent(htmlTree);
 124         }
 125         HtmlTree div = new HtmlTree(HtmlTag.DIV);
 126         div.addStyle(HtmlStyle.header);
 127         Content annotationContent = new HtmlTree(HtmlTag.P);
 128         addAnnotationInfo(packageElement, annotationContent);
 129         div.addContent(annotationContent);
 130         Content tHeading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, true,
 131                 HtmlStyle.title, packageLabel);
 132         tHeading.addContent(getSpace());
 133         Content packageHead = new StringContent(heading);
 134         tHeading.addContent(packageHead);
 135         div.addContent(tHeading);
 136         addDeprecationInfo(div);
 137         if (!utils.getBody(packageElement).isEmpty() && !configuration.nocomment) {
 138             HtmlTree docSummaryDiv = new HtmlTree(HtmlTag.DIV);
 139             docSummaryDiv.addStyle(HtmlStyle.docSummary);
 140             addSummaryComment(packageElement, docSummaryDiv);
 141             div.addContent(docSummaryDiv);
 142             Content space = getSpace();
 143             Content descLink = getHyperLink(getDocLink(
 144                     SectionName.PACKAGE_DESCRIPTION),
 145                     descriptionLabel, "", "");
 146             Content descPara = new HtmlTree(HtmlTag.P, seeLabel, space, descLink);
 147             div.addContent(descPara);
 148         }
 149         if (configuration.allowTag(HtmlTag.MAIN)) {
 150             mainTree.addContent(div);
 151         } else {
 152             bodyTree.addContent(div);
 153         }
 154         return bodyTree;
 155     }
 156 
 157     /**
 158      * {@inheritDoc}
 159      */
 160     public Content getContentHeader() {
 161         HtmlTree div = new HtmlTree(HtmlTag.DIV);
 162         div.addStyle(HtmlStyle.contentContainer);
 163         return div;
 164     }
 165 
 166     /**
 167      * Add the package deprecation information to the documentation tree.
 168      *
 169      * @param div the content tree to which the deprecation information will be added
 170      */
 171     public void addDeprecationInfo(Content div) {
 172         List<? extends DocTree> deprs = utils.getBlockTags(packageElement, DocTree.Kind.DEPRECATED);
 173         if (utils.isDeprecated(packageElement)) {
 174             CommentHelper ch = utils.getCommentHelper(packageElement);
 175             HtmlTree deprDiv = new HtmlTree(HtmlTag.DIV);
 176             deprDiv.addStyle(HtmlStyle.deprecatedContent);
 177             Content deprPhrase = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, deprecatedPhrase);
 178             deprDiv.addContent(deprPhrase);
 179             if (!deprs.isEmpty()) {
 180                 List<? extends DocTree> commentTags = ch.getDescription(configuration, deprs.get(0));
 181                 if (!commentTags.isEmpty()) {
 182                     addInlineDeprecatedComment(packageElement, deprs.get(0), deprDiv);
 183                 }
 184             }
 185             div.addContent(deprDiv);
 186         }
 187     }
 188 
 189     /**
 190      * {@inheritDoc}
 191      */
 192     public Content getSummaryHeader() {
 193         HtmlTree ul = new HtmlTree(HtmlTag.UL);
 194         ul.addStyle(HtmlStyle.blockList);
 195         return ul;
 196     }
 197 
 198     /**
 199      * {@inheritDoc}
 200      */
 201     public void addClassesSummary(SortedSet<TypeElement> classes, String label,
 202             String tableSummary, List<String> tableHeader, Content summaryContentTree) {
 203         if(!classes.isEmpty()) {
 204             Content caption = getTableCaption(new RawHtml(label));
 205             Content table = (configuration.isOutputHtml5())
 206                     ? HtmlTree.TABLE(HtmlStyle.typeSummary, caption)
 207                     : HtmlTree.TABLE(HtmlStyle.typeSummary, tableSummary, caption);
 208             table.addContent(getSummaryTableHeader(tableHeader, "col"));
 209             Content tbody = new HtmlTree(HtmlTag.TBODY);
 210             boolean altColor = false;
 211             for (TypeElement klass : classes) {
 212                 altColor = !altColor;
 213                 if (!utils.isCoreClass(klass) ||
 214                     !configuration.isGeneratedDoc(klass)) {
 215                     continue;
 216                 }
 217                 Content classContent = getLink(new LinkInfoImpl(
 218                         configuration, LinkInfoImpl.Kind.PACKAGE, klass));
 219                 Content tdClass = HtmlTree.TD(HtmlStyle.colFirst, classContent);
 220                 HtmlTree tr = HtmlTree.TR(tdClass);
 221                 tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
 222 
 223                 HtmlTree tdClassDescription = new HtmlTree(HtmlTag.TD);
 224                 tdClassDescription.addStyle(HtmlStyle.colLast);
 225                 if (utils.isDeprecated(klass)) {
 226                     tdClassDescription.addContent(deprecatedLabel);
 227                     List<? extends DocTree> tags = utils.getDeprecatedTrees(klass);
 228                     if (!tags.isEmpty()) {
 229                         addSummaryDeprecatedComment(klass, tags.get(0), tdClassDescription);
 230                     }
 231                 } else {
 232                     addSummaryComment(klass, tdClassDescription);
 233                 }
 234                 tr.addContent(tdClassDescription);
 235                 tbody.addContent(tr);
 236             }
 237             table.addContent(tbody);
 238             Content li = HtmlTree.LI(HtmlStyle.blockList, table);
 239             summaryContentTree.addContent(li);
 240         }
 241     }
 242 
 243     /**
 244      * {@inheritDoc}
 245      */
 246     public void addPackageDescription(Content packageContentTree) {
 247         if (!utils.getBody(packageElement).isEmpty()) {
 248             packageContentTree.addContent(
 249                     getMarkerAnchor(SectionName.PACKAGE_DESCRIPTION));
 250             Content h2Content = new StringContent(
 251                     configuration.getText("doclet.Package_Description",
 252                     packageElement.isUnnamed() ? "" : utils.getPackageName(packageElement)));
 253             Content heading = HtmlTree.HEADING(HtmlConstants.PACKAGE_HEADING, true, h2Content);
 254             if (configuration.allowTag(HtmlTag.SECTION)) {
 255                 sectionTree.addContent(heading);
 256                 addInlineComment(packageElement, sectionTree);
 257             } else {
 258                 packageContentTree.addContent(heading);
 259                 addInlineComment(packageElement, packageContentTree);
 260             }
 261         }
 262     }
 263 
 264     /**
 265      * {@inheritDoc}
 266      */
 267     public void addPackageTags(Content packageContentTree) {
 268         Content htmlTree = (configuration.allowTag(HtmlTag.SECTION))
 269                 ? sectionTree
 270                 : packageContentTree;
 271         addTagsInfo(packageElement, htmlTree);
 272     }
 273 
 274     /**
 275      * {@inheritDoc}
 276      */
 277     public void addPackageContent(Content contentTree, Content packageContentTree) {
 278         if (configuration.allowTag(HtmlTag.MAIN)) {
 279             packageContentTree.addContent(sectionTree);
 280             mainTree.addContent(packageContentTree);
 281             contentTree.addContent(mainTree);
 282         } else {
 283             contentTree.addContent(packageContentTree);
 284         }
 285     }
 286 
 287     /**
 288      * {@inheritDoc}
 289      */
 290     public void addPackageFooter(Content contentTree) {
 291         Content htmlTree = (configuration.allowTag(HtmlTag.FOOTER))
 292                 ? HtmlTree.FOOTER()
 293                 : contentTree;
 294         addNavLinks(false, htmlTree);
 295         addBottom(htmlTree);
 296         if (configuration.allowTag(HtmlTag.FOOTER)) {
 297             contentTree.addContent(htmlTree);
 298         }
 299     }
 300 
 301     /**
 302      * {@inheritDoc}
 303      */
 304     public void printDocument(Content contentTree) throws IOException {
 305         printHtmlDocument(configuration.metakeywords.getMetaKeywords(packageElement),
 306                 true, contentTree);
 307     }
 308 
 309     /**
 310      * Get "Use" link for this pacakge in the navigation bar.
 311      *
 312      * @return a content tree for the class use link
 313      */
 314     protected Content getNavLinkClassUse() {
 315         Content useLink = getHyperLink(DocPaths.PACKAGE_USE,
 316                 useLabel, "", "");
 317         Content li = HtmlTree.LI(useLink);
 318         return li;
 319     }
 320 
 321     /**
 322      * Get "PREV PACKAGE" link in the navigation bar.
 323      *
 324      * @return a content tree for the previous link
 325      */
 326     public Content getNavLinkPrevious() {
 327         Content li;
 328         if (prev == null) {
 329             li = HtmlTree.LI(prevpackageLabel);
 330         } else {
 331             DocPath path = DocPath.relativePath(packageElement, prev);
 332             li = HtmlTree.LI(getHyperLink(path.resolve(DocPaths.PACKAGE_SUMMARY),
 333                 prevpackageLabel, "", ""));
 334         }
 335         return li;
 336     }
 337 
 338     /**
 339      * Get "NEXT PACKAGE" link in the navigation bar.
 340      *
 341      * @return a content tree for the next link
 342      */
 343     public Content getNavLinkNext() {
 344         Content li;
 345         if (next == null) {
 346             li = HtmlTree.LI(nextpackageLabel);
 347         } else {
 348             DocPath path = DocPath.relativePath(packageElement, next);
 349             li = HtmlTree.LI(getHyperLink(path.resolve(DocPaths.PACKAGE_SUMMARY),
 350                 nextpackageLabel, "", ""));
 351         }
 352         return li;
 353     }
 354 
 355     /**
 356      * Get "Tree" link in the navigation bar. This will be link to the package
 357      * tree file.
 358      *
 359      * @return a content tree for the tree link
 360      */
 361     protected Content getNavLinkTree() {
 362         Content useLink = getHyperLink(DocPaths.PACKAGE_TREE,
 363                 treeLabel, "", "");
 364         Content li = HtmlTree.LI(useLink);
 365         return li;
 366     }
 367 
 368     /**
 369      * Highlight "Package" in the navigation bar, as this is the package page.
 370      *
 371      * @return a content tree for the package link
 372      */
 373     protected Content getNavLinkPackage() {
 374         Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, packageLabel);
 375         return li;
 376     }
 377 }