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