1 /*
2  * Copyright (c) 1997, 2020, 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.TagName;
41 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
42 import jdk.javadoc.internal.doclets.formats.html.Navigation.PageMode;
43 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
44 import jdk.javadoc.internal.doclets.formats.html.markup.Table;
45 import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
46 import jdk.javadoc.internal.doclets.toolkit.Content;
47 import jdk.javadoc.internal.doclets.toolkit.PackageSummaryWriter;
48 import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper;
49 import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
50 import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
51 import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
52 
53 /**
54  * Class to generate file for each package contents in the right-hand
55  * frame. This will list all the Class Kinds in the package. A click on any
56  * class-kind will update the frame with the clicked class-kind page.
57  *
58  *  <p><b>This is NOT part of any supported API.
59  *  If you write code that depends on this, you do so at your own risk.
60  *  This code and its internal interfaces are subject to change or
61  *  deletion without notice.</b>
62  */
63 public class PackageWriterImpl extends HtmlDocletWriter
64     implements PackageSummaryWriter {
65 
66     /**
67      * The package being documented.
68      */
69     protected PackageElement packageElement;
70 
71     /**
72      * The HTML tree for section tag.
73      */
74     protected HtmlTree sectionTree = HtmlTree.SECTION(HtmlStyle.packageDescription, new ContentBuilder());
75 
76     private final Navigation navBar;
77 
78     private final BodyContents bodyContents = new BodyContents();
79 
80     /**
81      * Constructor to construct PackageWriter object and to generate
82      * "package-summary.html" file in the respective package directory.
83      * For example for package "java.lang" this will generate file
84      * "package-summary.html" file in the "java/lang" directory. It will also
85      * create "java/lang" directory in the current or the destination directory
86      * if it doesn't exist.
87      *
88      * @param configuration the configuration of the doclet.
89      * @param packageElement    PackageElement under consideration.
90      */
PackageWriterImpl(HtmlConfiguration configuration, PackageElement packageElement)91     public PackageWriterImpl(HtmlConfiguration configuration, PackageElement packageElement) {
92         super(configuration,
93                 configuration.docPaths.forPackage(packageElement)
94                 .resolve(DocPaths.PACKAGE_SUMMARY));
95         this.packageElement = packageElement;
96         this.navBar = new Navigation(packageElement, configuration, PageMode.PACKAGE, path);
97     }
98 
99     @Override
getPackageHeader(String heading)100     public Content getPackageHeader(String heading) {
101         HtmlTree bodyTree = getBody(getWindowTitle(utils.getPackageName(packageElement)));
102         Content headerContent = new ContentBuilder();
103         addTop(headerContent);
104         Content linkContent = getModuleLink(utils.elementUtils.getModuleOf(packageElement),
105                 contents.moduleLabel);
106         navBar.setNavLinkModule(linkContent);
107         navBar.setUserHeader(getUserHeaderFooter(true));
108         headerContent.add(navBar.getContent(Navigation.Position.TOP));
109         HtmlTree div = new HtmlTree(TagName.DIV);
110         div.setStyle(HtmlStyle.header);
111         if (configuration.showModules) {
112             ModuleElement mdle = configuration.docEnv.getElementUtils().getModuleOf(packageElement);
113             Content classModuleLabel = HtmlTree.SPAN(HtmlStyle.moduleLabelInPackage, contents.moduleLabel);
114             Content moduleNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, classModuleLabel);
115             moduleNameDiv.add(Entity.NO_BREAK_SPACE);
116             moduleNameDiv.add(getModuleLink(mdle,
117                     new StringContent(mdle.getQualifiedName().toString())));
118             div.add(moduleNameDiv);
119         }
120         Content annotationContent = new HtmlTree(TagName.P);
121         addAnnotationInfo(packageElement, annotationContent);
122         div.add(annotationContent);
123         Content tHeading = HtmlTree.HEADING_TITLE(Headings.PAGE_TITLE_HEADING,
124                 HtmlStyle.title, contents.packageLabel);
125         tHeading.add(Entity.NO_BREAK_SPACE);
126         Content packageHead = new StringContent(heading);
127         tHeading.add(packageHead);
128         div.add(tHeading);
129         bodyContents.setHeader(headerContent)
130                 .addMainContent(div);
131         return bodyTree;
132     }
133 
134     @Override
getContentHeader()135     public Content getContentHeader() {
136         return new ContentBuilder();
137     }
138 
139     /**
140      * Add the package deprecation information to the documentation tree.
141      *
142      * @param div the content tree to which the deprecation information will be added
143      */
addDeprecationInfo(Content div)144     public void addDeprecationInfo(Content div) {
145         List<? extends DocTree> deprs = utils.getBlockTags(packageElement, DocTree.Kind.DEPRECATED);
146         if (utils.isDeprecated(packageElement)) {
147             CommentHelper ch = utils.getCommentHelper(packageElement);
148             HtmlTree deprDiv = new HtmlTree(TagName.DIV);
149             deprDiv.setStyle(HtmlStyle.deprecationBlock);
150             Content deprPhrase = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, getDeprecatedPhrase(packageElement));
151             deprDiv.add(deprPhrase);
152             if (!deprs.isEmpty()) {
153                 List<? extends DocTree> commentTags = ch.getDescription(deprs.get(0));
154                 if (!commentTags.isEmpty()) {
155                     addInlineDeprecatedComment(packageElement, deprs.get(0), deprDiv);
156                 }
157             }
158             div.add(deprDiv);
159         }
160     }
161 
162     @Override
getSummariesList()163     public Content getSummariesList() {
164         return new HtmlTree(TagName.UL).setStyle(HtmlStyle.summaryList);
165     }
166 
167     @Override
addInterfaceSummary(SortedSet<TypeElement> interfaces, Content summaryContentTree)168     public void addInterfaceSummary(SortedSet<TypeElement> interfaces, Content summaryContentTree) {
169         TableHeader tableHeader= new TableHeader(contents.interfaceLabel, contents.descriptionLabel);
170         addClassesSummary(interfaces, resources.interfaceSummary, tableHeader, summaryContentTree);
171     }
172 
173     @Override
addClassSummary(SortedSet<TypeElement> classes, Content summaryContentTree)174     public void addClassSummary(SortedSet<TypeElement> classes, Content summaryContentTree) {
175         TableHeader tableHeader= new TableHeader(contents.classLabel, contents.descriptionLabel);
176         addClassesSummary(classes, resources.classSummary, tableHeader, summaryContentTree);
177     }
178 
179     @Override
addEnumSummary(SortedSet<TypeElement> enums, Content summaryContentTree)180     public void addEnumSummary(SortedSet<TypeElement> enums, Content summaryContentTree) {
181         TableHeader tableHeader= new TableHeader(contents.enum_, contents.descriptionLabel);
182         addClassesSummary(enums, resources.enumSummary, tableHeader, summaryContentTree);
183     }
184 
185     @Override
addRecordSummary(SortedSet<TypeElement> records, Content summaryContentTree)186     public void addRecordSummary(SortedSet<TypeElement> records, Content summaryContentTree) {
187         TableHeader tableHeader= new TableHeader(contents.record, contents.descriptionLabel);
188         addClassesSummary(records, resources.recordSummary, tableHeader, summaryContentTree);
189     }
190 
191     @Override
addExceptionSummary(SortedSet<TypeElement> exceptions, Content summaryContentTree)192     public void addExceptionSummary(SortedSet<TypeElement> exceptions, Content summaryContentTree) {
193         TableHeader tableHeader= new TableHeader(contents.exception, contents.descriptionLabel);
194         addClassesSummary(exceptions, resources.exceptionSummary, tableHeader, summaryContentTree);
195     }
196 
197     @Override
addErrorSummary(SortedSet<TypeElement> errors, Content summaryContentTree)198     public void addErrorSummary(SortedSet<TypeElement> errors, Content summaryContentTree) {
199         TableHeader tableHeader= new TableHeader(contents.error, contents.descriptionLabel);
200         addClassesSummary(errors, resources.errorSummary, tableHeader, summaryContentTree);
201     }
202 
203     @Override
addAnnotationTypeSummary(SortedSet<TypeElement> annoTypes, Content summaryContentTree)204     public void addAnnotationTypeSummary(SortedSet<TypeElement> annoTypes, Content summaryContentTree) {
205         TableHeader tableHeader= new TableHeader(contents.annotationType, contents.descriptionLabel);
206         addClassesSummary(annoTypes, resources.annotationTypeSummary, tableHeader, summaryContentTree);
207     }
208 
addClassesSummary(SortedSet<TypeElement> classes, String label, TableHeader tableHeader, Content summaryContentTree)209     public void addClassesSummary(SortedSet<TypeElement> classes, String label,
210             TableHeader tableHeader, Content summaryContentTree) {
211         if(!classes.isEmpty()) {
212             Table table = new Table(HtmlStyle.typeSummary, HtmlStyle.summaryTable)
213                     .setCaption(new StringContent(label))
214                     .setHeader(tableHeader)
215                     .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colLast);
216 
217             for (TypeElement klass : classes) {
218                 if (!utils.isCoreClass(klass) || !configuration.isGeneratedDoc(klass)) {
219                     continue;
220                 }
221                 Content classLink = getLink(new LinkInfoImpl(
222                         configuration, LinkInfoImpl.Kind.PACKAGE, klass));
223                 ContentBuilder description = new ContentBuilder();
224                 if (utils.isDeprecated(klass)) {
225                     description.add(getDeprecatedPhrase(klass));
226                     List<? extends DocTree> tags = utils.getDeprecatedTrees(klass);
227                     if (!tags.isEmpty()) {
228                         addSummaryDeprecatedComment(klass, tags.get(0), description);
229                     }
230                 } else {
231                     addSummaryComment(klass, description);
232                 }
233                 table.addRow(classLink, description);
234             }
235             summaryContentTree.add(HtmlTree.LI(table));
236         }
237     }
238 
239     @Override
addPackageDescription(Content packageContentTree)240     public void addPackageDescription(Content packageContentTree) {
241         if (!utils.getBody(packageElement).isEmpty()) {
242             HtmlTree tree = sectionTree;
243             tree.setId(SectionName.PACKAGE_DESCRIPTION.getName());
244             addDeprecationInfo(tree);
245             addInlineComment(packageElement, tree);
246         }
247     }
248 
249     @Override
addPackageTags(Content packageContentTree)250     public void addPackageTags(Content packageContentTree) {
251         Content htmlTree = sectionTree;
252         addTagsInfo(packageElement, htmlTree);
253         packageContentTree.add(sectionTree);
254     }
255 
256     @Override
addPackageContent(Content packageContentTree)257     public void addPackageContent(Content packageContentTree) {
258         bodyContents.addMainContent(packageContentTree);
259     }
260 
261     @Override
addPackageFooter()262     public void addPackageFooter() {
263         Content htmlTree = HtmlTree.FOOTER();
264         navBar.setUserFooter(getUserHeaderFooter(false));
265         htmlTree.add(navBar.getContent(Navigation.Position.BOTTOM));
266         addBottom(htmlTree);
267         bodyContents.setFooter(htmlTree);
268     }
269 
270     @Override
printDocument(Content contentTree)271     public void printDocument(Content contentTree) throws DocFileIOException {
272         String description = getDescription("declaration", packageElement);
273         List<DocPath> localStylesheets = getLocalStylesheets(packageElement);
274         contentTree.add(bodyContents);
275         printHtmlDocument(configuration.metakeywords.getMetaKeywords(packageElement),
276                 description, localStylesheets, contentTree);
277     }
278 
279     @Override
getPackageSummary(Content summaryContentTree)280     public Content getPackageSummary(Content summaryContentTree) {
281         return HtmlTree.SECTION(HtmlStyle.summary, summaryContentTree);
282     }
283 }
284