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 }