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