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 jdk.javadoc.internal.doclets.formats.html.markup.Table;
29 import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
30 
31 import java.util.EnumMap;
32 import java.util.List;
33 import java.util.SortedSet;
34 
35 import javax.lang.model.element.Element;
36 import javax.lang.model.element.ModuleElement;
37 import javax.lang.model.element.PackageElement;
38 
39 import com.sun.source.doctree.DocTree;
40 import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
41 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
42 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
43 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
44 import jdk.javadoc.internal.doclets.formats.html.markup.Navigation;
45 import jdk.javadoc.internal.doclets.formats.html.markup.Navigation.PageMode;
46 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
47 import jdk.javadoc.internal.doclets.toolkit.Content;
48 import jdk.javadoc.internal.doclets.toolkit.util.DeprecatedAPIListBuilder;
49 import jdk.javadoc.internal.doclets.toolkit.util.DeprecatedAPIListBuilder.DeprElementKind;
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  * Generate File to list all the deprecated classes and class members with the
56  * appropriate links.
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  * @see java.util.List
64  */
65 public class DeprecatedListWriter extends SubWriterHolderWriter {
66 
getAnchorName(DeprElementKind kind)67     private String getAnchorName(DeprElementKind kind) {
68         switch (kind) {
69             case REMOVAL:
70                 return "forRemoval";
71             case MODULE:
72                 return "module";
73             case PACKAGE:
74                 return "package";
75             case INTERFACE:
76                 return "interface";
77             case CLASS:
78                 return "class";
79             case ENUM:
80                 return "enum";
81             case EXCEPTION:
82                 return "exception";
83             case ERROR:
84                 return "error";
85             case ANNOTATION_TYPE:
86                 return "annotation.type";
87             case FIELD:
88                 return "field";
89             case METHOD:
90                 return "method";
91             case CONSTRUCTOR:
92                 return "constructor";
93             case ENUM_CONSTANT:
94                 return "enum.constant";
95             case ANNOTATION_TYPE_MEMBER:
96                 return "annotation.type.member";
97             default:
98                 throw new AssertionError("unknown kind: " + kind);
99         }
100     }
101 
getHeadingKey(DeprElementKind kind)102     private String getHeadingKey(DeprElementKind kind) {
103         switch (kind) {
104             case REMOVAL:
105                 return "doclet.For_Removal";
106             case MODULE:
107                 return "doclet.Modules";
108             case PACKAGE:
109                 return "doclet.Packages";
110             case INTERFACE:
111                 return "doclet.Interfaces";
112             case CLASS:
113                 return "doclet.Classes";
114             case ENUM:
115                 return "doclet.Enums";
116             case EXCEPTION:
117                 return "doclet.Exceptions";
118             case ERROR:
119                 return "doclet.Errors";
120             case ANNOTATION_TYPE:
121                 return "doclet.Annotation_Types";
122             case FIELD:
123                 return "doclet.Fields";
124             case METHOD:
125                 return "doclet.Methods";
126             case CONSTRUCTOR:
127                 return "doclet.Constructors";
128             case ENUM_CONSTANT:
129                 return "doclet.Enum_Constants";
130             case ANNOTATION_TYPE_MEMBER:
131                 return "doclet.Annotation_Type_Members";
132             default:
133                 throw new AssertionError("unknown kind: " + kind);
134         }
135     }
136 
getSummaryKey(DeprElementKind kind)137     private String getSummaryKey(DeprElementKind kind) {
138         switch (kind) {
139             case REMOVAL:
140                 return "doclet.for_removal";
141             case MODULE:
142                 return "doclet.modules";
143             case PACKAGE:
144                 return "doclet.packages";
145             case INTERFACE:
146                 return "doclet.interfaces";
147             case CLASS:
148                 return "doclet.classes";
149             case ENUM:
150                 return "doclet.enums";
151             case EXCEPTION:
152                 return "doclet.exceptions";
153             case ERROR:
154                 return "doclet.errors";
155             case ANNOTATION_TYPE:
156                 return "doclet.annotation_types";
157             case FIELD:
158                 return "doclet.fields";
159             case METHOD:
160                 return "doclet.methods";
161             case CONSTRUCTOR:
162                 return "doclet.constructors";
163             case ENUM_CONSTANT:
164                 return "doclet.enum_constants";
165             case ANNOTATION_TYPE_MEMBER:
166                 return "doclet.annotation_type_members";
167             default:
168                 throw new AssertionError("unknown kind: " + kind);
169         }
170     }
171 
getHeaderKey(DeprElementKind kind)172     private String getHeaderKey(DeprElementKind kind) {
173         switch (kind) {
174             case REMOVAL:
175                 return "doclet.Element";
176             case MODULE:
177                 return "doclet.Module";
178             case PACKAGE:
179                 return "doclet.Package";
180             case INTERFACE:
181                 return "doclet.Interface";
182             case CLASS:
183                 return "doclet.Class";
184             case ENUM:
185                 return "doclet.Enum";
186             case EXCEPTION:
187                 return "doclet.Exceptions";
188             case ERROR:
189                 return "doclet.Errors";
190             case ANNOTATION_TYPE:
191                 return "doclet.AnnotationType";
192             case FIELD:
193                 return "doclet.Field";
194             case METHOD:
195                 return "doclet.Method";
196             case CONSTRUCTOR:
197                 return "doclet.Constructor";
198             case ENUM_CONSTANT:
199                 return "doclet.Enum_Constant";
200             case ANNOTATION_TYPE_MEMBER:
201                 return "doclet.Annotation_Type_Member";
202             default:
203                 throw new AssertionError("unknown kind: " + kind);
204         }
205     }
206 
207     private EnumMap<DeprElementKind, AbstractMemberWriter> writerMap;
208 
209     private HtmlConfiguration configuration;
210 
211     private final Navigation navBar;
212 
213     /**
214      * Constructor.
215      *
216      * @param configuration the configuration for this doclet
217      * @param filename the file to be generated
218      */
219 
DeprecatedListWriter(HtmlConfiguration configuration, DocPath filename)220     public DeprecatedListWriter(HtmlConfiguration configuration, DocPath filename) {
221         super(configuration, filename);
222         this.configuration = configuration;
223         this.navBar = new Navigation(null, configuration, PageMode.DEPRECATED, path);
224         NestedClassWriterImpl classW = new NestedClassWriterImpl(this);
225         writerMap = new EnumMap<>(DeprElementKind.class);
226         for (DeprElementKind kind : DeprElementKind.values()) {
227             switch (kind) {
228                 case REMOVAL:
229                 case MODULE:
230                 case PACKAGE:
231                 case INTERFACE:
232                 case CLASS:
233                 case ENUM:
234                 case EXCEPTION:
235                 case ERROR:
236                 case ANNOTATION_TYPE:
237                     writerMap.put(kind, classW);
238                     break;
239                 case FIELD:
240                     writerMap.put(kind, new FieldWriterImpl(this));
241                     break;
242                 case METHOD:
243                     writerMap.put(kind, new MethodWriterImpl(this));
244                     break;
245                 case CONSTRUCTOR:
246                     writerMap.put(kind, new ConstructorWriterImpl(this));
247                     break;
248                 case ENUM_CONSTANT:
249                     writerMap.put(kind, new EnumConstantWriterImpl(this));
250                     break;
251                 case ANNOTATION_TYPE_MEMBER:
252                     writerMap.put(kind, new AnnotationTypeOptionalMemberWriterImpl(this, null));
253                     break;
254                 default:
255                    throw new AssertionError("unknown kind: " + kind);
256             }
257         }
258     }
259 
260     /**
261      * Get list of all the deprecated classes and members in all the Packages
262      * specified on the Command Line.
263      * Then instantiate DeprecatedListWriter and generate File.
264      *
265      * @param configuration the current configuration of the doclet.
266      * @throws DocFileIOException if there is a problem writing the deprecated list
267      */
generate(HtmlConfiguration configuration)268     public static void generate(HtmlConfiguration configuration) throws DocFileIOException {
269         DocPath filename = DocPaths.DEPRECATED_LIST;
270         DeprecatedListWriter depr = new DeprecatedListWriter(configuration, filename);
271         depr.generateDeprecatedListFile(
272                new DeprecatedAPIListBuilder(configuration));
273     }
274 
275     /**
276      * Generate the deprecated API list.
277      *
278      * @param deprapi list of deprecated API built already.
279      * @throws DocFileIOException if there is a problem writing the deprecated list
280      */
generateDeprecatedListFile(DeprecatedAPIListBuilder deprapi)281     protected void generateDeprecatedListFile(DeprecatedAPIListBuilder deprapi)
282             throws DocFileIOException {
283         HtmlTree body = getHeader();
284         bodyContents.addMainContent(getContentsList(deprapi));
285         String memberTableSummary;
286         HtmlTree div = new HtmlTree(HtmlTag.DIV);
287         div.setStyle(HtmlStyle.contentContainer);
288         for (DeprElementKind kind : DeprElementKind.values()) {
289             if (deprapi.hasDocumentation(kind)) {
290                 addAnchor(deprapi, kind, div);
291                 memberTableSummary = resources.getText("doclet.Member_Table_Summary",
292                         resources.getText(getHeadingKey(kind)),
293                         resources.getText(getSummaryKey(kind)));
294                 TableHeader memberTableHeader = new TableHeader(
295                         contents.getContent(getHeaderKey(kind)), contents.descriptionLabel);
296                 addDeprecatedAPI(deprapi.getSet(kind),
297                             getHeadingKey(kind), memberTableSummary, memberTableHeader, div);
298             }
299         }
300         bodyContents.addMainContent(div);
301         HtmlTree htmlTree = HtmlTree.FOOTER();
302         navBar.setUserFooter(getUserHeaderFooter(false));
303         htmlTree.add(navBar.getContent(false));
304         addBottom(htmlTree);
305         bodyContents.setFooter(htmlTree);
306         String description = "deprecated elements";
307         body.add(bodyContents.toContent());
308         printHtmlDocument(null, description, body);
309     }
310 
311     /**
312      * Add the index link.
313      *
314      * @param builder the deprecated list builder
315      * @param kind the kind of list being documented
316      * @param contentTree the content tree to which the index link will be added
317      */
addIndexLink(DeprecatedAPIListBuilder builder, DeprElementKind kind, Content contentTree)318     private void addIndexLink(DeprecatedAPIListBuilder builder,
319             DeprElementKind kind, Content contentTree) {
320         if (builder.hasDocumentation(kind)) {
321             Content li = HtmlTree.LI(links.createLink(getAnchorName(kind),
322                     contents.getContent(getHeadingKey(kind))));
323             contentTree.add(li);
324         }
325     }
326 
327     /**
328      * Get the contents list.
329      *
330      * @param deprapi the deprecated list builder
331      * @return a content tree for the contents list
332      */
getContentsList(DeprecatedAPIListBuilder deprapi)333     public Content getContentsList(DeprecatedAPIListBuilder deprapi) {
334         Content headContent = contents.deprecatedAPI;
335         Content heading = HtmlTree.HEADING(Headings.PAGE_TITLE_HEADING, true,
336                 HtmlStyle.title, headContent);
337         Content div = HtmlTree.DIV(HtmlStyle.header, heading);
338         Content headingContent = contents.contentsHeading;
339         div.add(HtmlTree.HEADING(Headings.CONTENT_HEADING, true,
340                 headingContent));
341         Content ul = new HtmlTree(HtmlTag.UL);
342         for (DeprElementKind kind : DeprElementKind.values()) {
343             addIndexLink(deprapi, kind, ul);
344         }
345         div.add(ul);
346         return div;
347     }
348 
349     /**
350      * Add the anchor.
351      *
352      * @param builder the deprecated list builder
353      * @param kind the kind of list being documented
354      * @param htmlTree the content tree to which the anchor will be added
355      */
addAnchor(DeprecatedAPIListBuilder builder, DeprElementKind kind, Content htmlTree)356     private void addAnchor(DeprecatedAPIListBuilder builder, DeprElementKind kind, Content htmlTree) {
357         if (builder.hasDocumentation(kind)) {
358             htmlTree.add(links.createAnchor(getAnchorName(kind)));
359         }
360     }
361 
362     /**
363      * Get the header for the deprecated API Listing.
364      *
365      * @return a content tree for the header
366      */
getHeader()367     public HtmlTree getHeader() {
368         String title = resources.getText("doclet.Window_Deprecated_List");
369         HtmlTree bodyTree = getBody(getWindowTitle(title));
370         Content headerContent = new ContentBuilder();
371         addTop(headerContent);
372         navBar.setUserHeader(getUserHeaderFooter(true));
373         headerContent.add(navBar.getContent(true));
374         bodyContents.setHeader(headerContent);
375         return bodyTree;
376     }
377 
378     /**
379      * Add deprecated information to the documentation tree
380      *
381      * @param deprList list of deprecated API elements
382      * @param headingKey the caption for the deprecated table
383      * @param tableSummary the summary for the deprecated table
384      * @param tableHeader table headers for the deprecated table
385      * @param contentTree the content tree to which the deprecated table will be added
386      */
addDeprecatedAPI(SortedSet<Element> deprList, String headingKey, String tableSummary, TableHeader tableHeader, Content contentTree)387     protected void addDeprecatedAPI(SortedSet<Element> deprList, String headingKey,
388             String tableSummary, TableHeader tableHeader, Content contentTree) {
389         if (deprList.size() > 0) {
390             Content caption = contents.getContent(headingKey);
391             Table table = new Table(HtmlStyle.deprecatedSummary)
392                     .setCaption(caption)
393                     .setHeader(tableHeader)
394                     .setColumnStyles(HtmlStyle.colDeprecatedItemName, HtmlStyle.colLast);
395             for (Element e : deprList) {
396                 Content link;
397                 switch (e.getKind()) {
398                     case MODULE:
399                         ModuleElement m = (ModuleElement) e;
400                         link = getModuleLink(m, new StringContent(m.getQualifiedName()));
401                         break;
402                     case PACKAGE:
403                         PackageElement pkg = (PackageElement) e;
404                         link = getPackageLink(pkg, getPackageName(pkg));
405                         break;
406                     default:
407                         link = getDeprecatedLink(e);
408                 }
409                 Content desc = new ContentBuilder();
410                 List<? extends DocTree> tags = utils.getDeprecatedTrees(e);
411                 if (!tags.isEmpty()) {
412                     addInlineDeprecatedComment(e, tags.get(0), desc);
413                 } else {
414                     desc.add(HtmlTree.EMPTY);
415                 }
416                 table.addRow(link, desc);
417             }
418             Content li = HtmlTree.LI(HtmlStyle.blockList, table.toContent());
419             Content ul = HtmlTree.UL(HtmlStyle.blockList, li);
420             contentTree.add(ul);
421         }
422     }
423 
getDeprecatedLink(Element e)424     protected Content getDeprecatedLink(Element e) {
425         AbstractMemberWriter writer;
426         switch (e.getKind()) {
427             case INTERFACE:
428             case CLASS:
429             case ENUM:
430             case ANNOTATION_TYPE:
431                 writer = new NestedClassWriterImpl(this);
432                 break;
433             case FIELD:
434                 writer = new FieldWriterImpl(this);
435                 break;
436             case METHOD:
437                 writer = new MethodWriterImpl(this);
438                 break;
439             case CONSTRUCTOR:
440                 writer = new ConstructorWriterImpl(this);
441                 break;
442             case ENUM_CONSTANT:
443                 writer = new EnumConstantWriterImpl(this);
444                 break;
445             default:
446                 writer = new AnnotationTypeOptionalMemberWriterImpl(this, null);
447         }
448         return writer.getDeprecatedLink(e);
449     }
450 }
451