1/* 2 * Copyright (c) 1997, 2017, 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 26package jdk.javadoc.internal.doclets.formats.html; 27 28import java.util.ArrayList; 29import java.util.EnumMap; 30import java.util.List; 31import java.util.SortedSet; 32 33import javax.lang.model.element.Element; 34import javax.lang.model.element.ModuleElement; 35import javax.lang.model.element.PackageElement; 36 37import com.sun.source.doctree.DocTree; 38import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants; 39import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; 40import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; 41import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; 42import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; 43import jdk.javadoc.internal.doclets.toolkit.Content; 44import jdk.javadoc.internal.doclets.toolkit.util.DeprecatedAPIListBuilder; 45import jdk.javadoc.internal.doclets.toolkit.util.DeprecatedAPIListBuilder.DeprElementKind; 46import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException; 47import jdk.javadoc.internal.doclets.toolkit.util.DocPath; 48import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; 49 50/** 51 * Generate File to list all the deprecated classes and class members with the 52 * appropriate links. 53 * 54 * <p><b>This is NOT part of any supported API. 55 * If you write code that depends on this, you do so at your own risk. 56 * This code and its internal interfaces are subject to change or 57 * deletion without notice.</b> 58 * 59 * @see java.util.List 60 * @author Atul M Dambalkar 61 * @author Bhavesh Patel (Modified) 62 */ 63public class DeprecatedListWriter extends SubWriterHolderWriter { 64 65 private String getAnchorName(DeprElementKind kind) { 66 switch (kind) { 67 case REMOVAL: 68 return "forRemoval"; 69 case MODULE: 70 return "module"; 71 case PACKAGE: 72 return "package"; 73 case INTERFACE: 74 return "interface"; 75 case CLASS: 76 return "class"; 77 case ENUM: 78 return "enum"; 79 case EXCEPTION: 80 return "exception"; 81 case ERROR: 82 return "error"; 83 case ANNOTATION_TYPE: 84 return "annotation.type"; 85 case FIELD: 86 return "field"; 87 case METHOD: 88 return "method"; 89 case CONSTRUCTOR: 90 return "constructor"; 91 case ENUM_CONSTANT: 92 return "enum.constant"; 93 case ANNOTATION_TYPE_MEMBER: 94 return "annotation.type.member"; 95 default: 96 throw new AssertionError("unknown kind: " + kind); 97 } 98 } 99 100 private String getHeadingKey(DeprElementKind kind) { 101 switch (kind) { 102 case REMOVAL: 103 return "doclet.Deprecated_For_Removal"; 104 case MODULE: 105 return "doclet.Deprecated_Modules"; 106 case PACKAGE: 107 return "doclet.Deprecated_Packages"; 108 case INTERFACE: 109 return "doclet.Deprecated_Interfaces"; 110 case CLASS: 111 return "doclet.Deprecated_Classes"; 112 case ENUM: 113 return "doclet.Deprecated_Enums"; 114 case EXCEPTION: 115 return "doclet.Deprecated_Exceptions"; 116 case ERROR: 117 return "doclet.Deprecated_Errors"; 118 case ANNOTATION_TYPE: 119 return "doclet.Deprecated_Annotation_Types"; 120 case FIELD: 121 return "doclet.Deprecated_Fields"; 122 case METHOD: 123 return "doclet.Deprecated_Methods"; 124 case CONSTRUCTOR: 125 return "doclet.Deprecated_Constructors"; 126 case ENUM_CONSTANT: 127 return "doclet.Deprecated_Enum_Constants"; 128 case ANNOTATION_TYPE_MEMBER: 129 return "doclet.Deprecated_Annotation_Type_Members"; 130 default: 131 throw new AssertionError("unknown kind: " + kind); 132 } 133 } 134 135 private String getSummaryKey(DeprElementKind kind) { 136 switch (kind) { 137 case REMOVAL: 138 return "doclet.deprecated_for_removal"; 139 case MODULE: 140 return "doclet.deprecated_modules"; 141 case PACKAGE: 142 return "doclet.deprecated_packages"; 143 case INTERFACE: 144 return "doclet.deprecated_interfaces"; 145 case CLASS: 146 return "doclet.deprecated_classes"; 147 case ENUM: 148 return "doclet.deprecated_enums"; 149 case EXCEPTION: 150 return "doclet.deprecated_exceptions"; 151 case ERROR: 152 return "doclet.deprecated_errors"; 153 case ANNOTATION_TYPE: 154 return "doclet.deprecated_annotation_types"; 155 case FIELD: 156 return "doclet.deprecated_fields"; 157 case METHOD: 158 return "doclet.deprecated_methods"; 159 case CONSTRUCTOR: 160 return "doclet.deprecated_constructors"; 161 case ENUM_CONSTANT: 162 return "doclet.deprecated_enum_constants"; 163 case ANNOTATION_TYPE_MEMBER: 164 return "doclet.deprecated_annotation_type_members"; 165 default: 166 throw new AssertionError("unknown kind: " + kind); 167 } 168 } 169 170 private String getHeaderKey(DeprElementKind kind) { 171 switch (kind) { 172 case REMOVAL: 173 return "doclet.Element"; 174 case MODULE: 175 return "doclet.Module"; 176 case PACKAGE: 177 return "doclet.Package"; 178 case INTERFACE: 179 return "doclet.Interface"; 180 case CLASS: 181 return "doclet.Class"; 182 case ENUM: 183 return "doclet.Enum"; 184 case EXCEPTION: 185 return "doclet.Exceptions"; 186 case ERROR: 187 return "doclet.Errors"; 188 case ANNOTATION_TYPE: 189 return "doclet.AnnotationType"; 190 case FIELD: 191 return "doclet.Field"; 192 case METHOD: 193 return "doclet.Method"; 194 case CONSTRUCTOR: 195 return "doclet.Constructor"; 196 case ENUM_CONSTANT: 197 return "doclet.Enum_Constant"; 198 case ANNOTATION_TYPE_MEMBER: 199 return "doclet.Annotation_Type_Member"; 200 default: 201 throw new AssertionError("unknown kind: " + kind); 202 } 203 } 204 205 private EnumMap<DeprElementKind, AbstractMemberWriter> writerMap; 206 207 private HtmlConfiguration configuration; 208 209 /** 210 * Constructor. 211 * 212 * @param configuration the configuration for this doclet 213 * @param filename the file to be generated 214 */ 215 216 public DeprecatedListWriter(HtmlConfiguration configuration, DocPath filename) { 217 super(configuration, filename); 218 this.configuration = configuration; 219 NestedClassWriterImpl classW = new NestedClassWriterImpl(this); 220 writerMap = new EnumMap<>(DeprElementKind.class); 221 for (DeprElementKind kind : DeprElementKind.values()) { 222 switch (kind) { 223 case REMOVAL: 224 case MODULE: 225 case PACKAGE: 226 case INTERFACE: 227 case CLASS: 228 case ENUM: 229 case EXCEPTION: 230 case ERROR: 231 case ANNOTATION_TYPE: 232 writerMap.put(kind, classW); 233 break; 234 case FIELD: 235 writerMap.put(kind, new FieldWriterImpl(this)); 236 break; 237 case METHOD: 238 writerMap.put(kind, new MethodWriterImpl(this)); 239 break; 240 case CONSTRUCTOR: 241 writerMap.put(kind, new ConstructorWriterImpl(this)); 242 break; 243 case ENUM_CONSTANT: 244 writerMap.put(kind, new EnumConstantWriterImpl(this)); 245 break; 246 case ANNOTATION_TYPE_MEMBER: 247 writerMap.put(kind, new AnnotationTypeOptionalMemberWriterImpl(this, null)); 248 break; 249 default: 250 throw new AssertionError("unknown kind: " + kind); 251 } 252 } 253 } 254 255 /** 256 * Get list of all the deprecated classes and members in all the Packages 257 * specified on the Command Line. 258 * Then instantiate DeprecatedListWriter and generate File. 259 * 260 * @param configuration the current configuration of the doclet. 261 * @throws DocFileIOException if there is a problem writing the deprecated list 262 */ 263 public static void generate(HtmlConfiguration configuration) throws DocFileIOException { 264 DocPath filename = DocPaths.DEPRECATED_LIST; 265 DeprecatedListWriter depr = new DeprecatedListWriter(configuration, filename); 266 depr.generateDeprecatedListFile( 267 new DeprecatedAPIListBuilder(configuration)); 268 } 269 270 /** 271 * Generate the deprecated API list. 272 * 273 * @param deprapi list of deprecated API built already. 274 * @throws DocFileIOException if there is a problem writing the deprecated list 275 */ 276 protected void generateDeprecatedListFile(DeprecatedAPIListBuilder deprapi) 277 throws DocFileIOException { 278 HtmlTree body = getHeader(); 279 HtmlTree htmlTree = (configuration.allowTag(HtmlTag.MAIN)) 280 ? HtmlTree.MAIN() 281 : body; 282 htmlTree.addContent(getContentsList(deprapi)); 283 String memberTableSummary; 284 HtmlTree div = new HtmlTree(HtmlTag.DIV); 285 div.addStyle(HtmlStyle.contentContainer); 286 for (DeprElementKind kind : DeprElementKind.values()) { 287 if (deprapi.hasDocumentation(kind)) { 288 addAnchor(deprapi, kind, div); 289 memberTableSummary 290 = resources.getText("doclet.Member_Table_Summary", 291 resources.getText(getHeadingKey(kind)), 292 resources.getText(getSummaryKey(kind))); 293 List<String> memberTableHeader = new ArrayList<>(); 294 memberTableHeader.add(resources.getText(getHeaderKey(kind))); 295 memberTableHeader.add(resources.getText("doclet.Description")); 296 addDeprecatedAPI(deprapi.getSet(kind), 297 getHeadingKey(kind), memberTableSummary, memberTableHeader, div); 298 } 299 } 300 if (configuration.allowTag(HtmlTag.MAIN)) { 301 htmlTree.addContent(div); 302 body.addContent(htmlTree); 303 } else { 304 body.addContent(div); 305 } 306 htmlTree = (configuration.allowTag(HtmlTag.FOOTER)) 307 ? HtmlTree.FOOTER() 308 : body; 309 addNavLinks(false, htmlTree); 310 addBottom(htmlTree); 311 if (configuration.allowTag(HtmlTag.FOOTER)) { 312 body.addContent(htmlTree); 313 } 314 printHtmlDocument(null, true, body); 315 } 316 317 /** 318 * Add the index link. 319 * 320 * @param builder the deprecated list builder 321 * @param type the type of list being documented 322 * @param contentTree the content tree to which the index link will be added 323 */ 324 private void addIndexLink(DeprecatedAPIListBuilder builder, 325 DeprElementKind kind, Content contentTree) { 326 if (builder.hasDocumentation(kind)) { 327 Content li = HtmlTree.LI(getHyperLink(getAnchorName(kind), 328 contents.getContent(getHeadingKey(kind)))); 329 contentTree.addContent(li); 330 } 331 } 332 333 /** 334 * Get the contents list. 335 * 336 * @param deprapi the deprecated list builder 337 * @return a content tree for the contents list 338 */ 339 public Content getContentsList(DeprecatedAPIListBuilder deprapi) { 340 Content headContent = contents.deprecatedAPI; 341 Content heading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, true, 342 HtmlStyle.title, headContent); 343 Content div = HtmlTree.DIV(HtmlStyle.header, heading); 344 Content headingContent = contents.contentsHeading; 345 div.addContent(HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING, true, 346 headingContent)); 347 Content ul = new HtmlTree(HtmlTag.UL); 348 for (DeprElementKind kind : DeprElementKind.values()) { 349 addIndexLink(deprapi, kind, ul); 350 } 351 div.addContent(ul); 352 return div; 353 } 354 355 /** 356 * Add the anchor. 357 * 358 * @param builder the deprecated list builder 359 * @param type the type of list being documented 360 * @param htmlTree the content tree to which the anchor will be added 361 */ 362 private void addAnchor(DeprecatedAPIListBuilder builder, DeprElementKind kind, Content htmlTree) { 363 if (builder.hasDocumentation(kind)) { 364 htmlTree.addContent(getMarkerAnchor(getAnchorName(kind))); 365 } 366 } 367 368 /** 369 * Get the header for the deprecated API Listing. 370 * 371 * @return a content tree for the header 372 */ 373 public HtmlTree getHeader() { 374 String title = configuration.getText("doclet.Window_Deprecated_List"); 375 HtmlTree bodyTree = getBody(true, getWindowTitle(title)); 376 HtmlTree htmlTree = (configuration.allowTag(HtmlTag.HEADER)) 377 ? HtmlTree.HEADER() 378 : bodyTree; 379 addTop(htmlTree); 380 addNavLinks(true, htmlTree); 381 if (configuration.allowTag(HtmlTag.HEADER)) { 382 bodyTree.addContent(htmlTree); 383 } 384 return bodyTree; 385 } 386 387 /** 388 * Get the deprecated label. 389 * 390 * @return a content tree for the deprecated label 391 */ 392 @Override 393 protected Content getNavLinkDeprecated() { 394 Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, contents.deprecatedLabel); 395 return li; 396 } 397 398 /** 399 * Add deprecated information to the documentation tree 400 * 401 * @param deprList list of deprecated API elements 402 * @param headingKey the caption for the deprecated table 403 * @param tableSummary the summary for the deprecated table 404 * @param tableHeader table headers for the deprecated table 405 * @param contentTree the content tree to which the deprecated table will be added 406 */ 407 protected void addDeprecatedAPI(SortedSet<Element> deprList, String headingKey, 408 String tableSummary, List<String> tableHeader, Content contentTree) { 409 if (deprList.size() > 0) { 410 Content caption = getTableCaption(configuration.getContent(headingKey)); 411 Content table = (configuration.isOutputHtml5()) 412 ? HtmlTree.TABLE(HtmlStyle.deprecatedSummary, caption) 413 : HtmlTree.TABLE(HtmlStyle.deprecatedSummary, tableSummary, caption); 414 table.addContent(getSummaryTableHeader(tableHeader, "col")); 415 Content tbody = new HtmlTree(HtmlTag.TBODY); 416 boolean altColor = true; 417 for (Element e : deprList) { 418 HtmlTree thRow; 419 switch (e.getKind()) { 420 case MODULE: 421 ModuleElement m = (ModuleElement)e; 422 thRow = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, 423 getModuleLink(m, new StringContent(m.getQualifiedName()))); 424 break; 425 case PACKAGE: 426 PackageElement pkg = (PackageElement)e; 427 thRow = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, 428 getPackageLink(pkg, getPackageName(pkg))); 429 break; 430 default: 431 thRow = getDeprecatedLink(e); 432 } 433 HtmlTree tr = HtmlTree.TR(thRow); 434 HtmlTree tdDesc = new HtmlTree(HtmlTag.TD); 435 tdDesc.addStyle(HtmlStyle.colLast); 436 List<? extends DocTree> tags = utils.getDeprecatedTrees(e); 437 if (!tags.isEmpty()) { 438 addInlineDeprecatedComment(e, tags.get(0), tdDesc); 439 } 440 tr.addContent(tdDesc); 441 tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor); 442 altColor = !altColor; 443 tbody.addContent(tr); 444 } 445 table.addContent(tbody); 446 Content li = HtmlTree.LI(HtmlStyle.blockList, table); 447 Content ul = HtmlTree.UL(HtmlStyle.blockList, li); 448 contentTree.addContent(ul); 449 } 450 } 451 452 protected HtmlTree getDeprecatedLink(Element e) { 453 AbstractMemberWriter writer; 454 switch (e.getKind()) { 455 case INTERFACE: 456 case CLASS: 457 case ENUM: 458 case ANNOTATION_TYPE: 459 writer = new NestedClassWriterImpl(this); 460 break; 461 case FIELD: 462 writer = new FieldWriterImpl(this); 463 break; 464 case METHOD: 465 writer = new MethodWriterImpl(this); 466 break; 467 case CONSTRUCTOR: 468 writer = new ConstructorWriterImpl(this); 469 break; 470 case ENUM_CONSTANT: 471 writer = new EnumConstantWriterImpl(this); 472 break; 473 default: 474 writer = new AnnotationTypeOptionalMemberWriterImpl(this, null); 475 } 476 return HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, writer.getDeprecatedLink(e)); 477 } 478} 479