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 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 }