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 
  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 
 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 
 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 
 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 
 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      */
 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      */
 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                 memberTableSummary = resources.getText("doclet.Member_Table_Summary",
 291                         resources.getText(getHeadingKey(kind)),
 292                         resources.getText(getSummaryKey(kind)));
 293                 TableHeader memberTableHeader = new TableHeader(
 294                         contents.getContent(getHeaderKey(kind)), contents.descriptionLabel);
 295                 addDeprecatedAPI(deprapi.getSet(kind), getAnchorName(kind),
 296                             getHeadingKey(kind), memberTableSummary, memberTableHeader, div);
 297             }
 298         }
 299         bodyContents.addMainContent(div);
 300         HtmlTree htmlTree = HtmlTree.FOOTER();
 301         navBar.setUserFooter(getUserHeaderFooter(false));
 302         htmlTree.add(navBar.getContent(false));
 303         addBottom(htmlTree);
 304         bodyContents.setFooter(htmlTree);
 305         String description = "deprecated elements";
 306         body.add(bodyContents.toContent());
 307         printHtmlDocument(null, description, body);
 308     }
 309 
 310     /**
 311      * Add the index link.
 312      *
 313      * @param builder the deprecated list builder
 314      * @param kind the kind of list being documented
 315      * @param contentTree the content tree to which the index link will be added
 316      */
 317     private void addIndexLink(DeprecatedAPIListBuilder builder,
 318             DeprElementKind kind, Content contentTree) {
 319         if (builder.hasDocumentation(kind)) {
 320             Content li = HtmlTree.LI(links.createLink(getAnchorName(kind),
 321                     contents.getContent(getHeadingKey(kind))));
 322             contentTree.add(li);
 323         }
 324     }
 325 
 326     /**
 327      * Get the contents list.
 328      *
 329      * @param deprapi the deprecated list builder
 330      * @return a content tree for the contents list
 331      */
 332     public Content getContentsList(DeprecatedAPIListBuilder deprapi) {
 333         Content headContent = contents.deprecatedAPI;
 334         Content heading = HtmlTree.HEADING(Headings.PAGE_TITLE_HEADING, true,
 335                 HtmlStyle.title, headContent);
 336         Content div = HtmlTree.DIV(HtmlStyle.header, heading);
 337         Content headingContent = contents.contentsHeading;
 338         div.add(HtmlTree.HEADING(Headings.CONTENT_HEADING, true,
 339                 headingContent));
 340         Content ul = new HtmlTree(HtmlTag.UL);
 341         for (DeprElementKind kind : DeprElementKind.values()) {
 342             addIndexLink(deprapi, kind, ul);
 343         }
 344         div.add(ul);
 345         return div;
 346     }
 347 
 348     /**
 349      * Get the header for the deprecated API Listing.
 350      *
 351      * @return a content tree for the header
 352      */
 353     public HtmlTree getHeader() {
 354         String title = resources.getText("doclet.Window_Deprecated_List");
 355         HtmlTree bodyTree = getBody(getWindowTitle(title));
 356         Content headerContent = new ContentBuilder();
 357         addTop(headerContent);
 358         navBar.setUserHeader(getUserHeaderFooter(true));
 359         headerContent.add(navBar.getContent(true));
 360         bodyContents.setHeader(headerContent);
 361         return bodyTree;
 362     }
 363 
 364     /**
 365      * Add deprecated information to the documentation tree
 366      *
 367      * @param deprList list of deprecated API elements
 368      * @param id the id attribute of the table
 369      * @param headingKey the caption for the deprecated table
 370      * @param tableSummary the summary for the deprecated table
 371      * @param tableHeader table headers for the deprecated table
 372      * @param contentTree the content tree to which the deprecated table will be added
 373      */
 374     protected void addDeprecatedAPI(SortedSet<Element> deprList, String id, String headingKey,
 375             String tableSummary, TableHeader tableHeader, Content contentTree) {
 376         if (deprList.size() > 0) {
 377             Content caption = contents.getContent(headingKey);
 378             Table table = new Table(HtmlStyle.deprecatedSummary)
 379                     .setCaption(caption)
 380                     .setHeader(tableHeader)
 381                     .setId(id)
 382                     .setColumnStyles(HtmlStyle.colDeprecatedItemName, HtmlStyle.colLast);
 383             for (Element e : deprList) {
 384                 Content link;
 385                 switch (e.getKind()) {
 386                     case MODULE:
 387                         ModuleElement m = (ModuleElement) e;
 388                         link = getModuleLink(m, new StringContent(m.getQualifiedName()));
 389                         break;
 390                     case PACKAGE:
 391                         PackageElement pkg = (PackageElement) e;
 392                         link = getPackageLink(pkg, getPackageName(pkg));
 393                         break;
 394                     default:
 395                         link = getDeprecatedLink(e);
 396                 }
 397                 Content desc = new ContentBuilder();
 398                 List<? extends DocTree> tags = utils.getDeprecatedTrees(e);
 399                 if (!tags.isEmpty()) {
 400                     addInlineDeprecatedComment(e, tags.get(0), desc);
 401                 } else {
 402                     desc.add(HtmlTree.EMPTY);
 403                 }
 404                 table.addRow(link, desc);
 405             }
 406             Content li = HtmlTree.LI(HtmlStyle.blockList, table.toContent());
 407             Content ul = HtmlTree.UL(HtmlStyle.blockList, li);
 408             contentTree.add(ul);
 409         }
 410     }
 411 
 412     protected Content getDeprecatedLink(Element e) {
 413         AbstractMemberWriter writer;
 414         switch (e.getKind()) {
 415             case INTERFACE:
 416             case CLASS:
 417             case ENUM:
 418             case ANNOTATION_TYPE:
 419                 writer = new NestedClassWriterImpl(this);
 420                 break;
 421             case FIELD:
 422                 writer = new FieldWriterImpl(this);
 423                 break;
 424             case METHOD:
 425                 writer = new MethodWriterImpl(this);
 426                 break;
 427             case CONSTRUCTOR:
 428                 writer = new ConstructorWriterImpl(this);
 429                 break;
 430             case ENUM_CONSTANT:
 431                 writer = new EnumConstantWriterImpl(this);
 432                 break;
 433             default:
 434                 writer = new AnnotationTypeOptionalMemberWriterImpl(this, null);
 435         }
 436         return writer.getDeprecatedLink(e);
 437     }
 438 }