1 /* 2 * Copyright (c) 2003, 2015, 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 com.sun.tools.doclets.internal.toolkit.builders; 27 28 import java.io.*; 29 import java.util.*; 30 31 import com.sun.javadoc.*; 32 import com.sun.tools.doclets.internal.toolkit.*; 33 import com.sun.tools.doclets.internal.toolkit.util.*; 34 35 /** 36 * Builds the Constants Summary Page. 37 * 38 * <p><b>This is NOT part of any supported API. 39 * If you write code that depends on this, you do so at your own risk. 40 * This code and its internal interfaces are subject to change or 41 * deletion without notice.</b> 42 * 43 * @author Jamie Ho 44 * @author Bhavesh Patel (Modified) 45 * @since 1.5 46 */ 47 public class ConstantsSummaryBuilder extends AbstractBuilder { 48 49 /** 50 * The root element of the constant summary XML is {@value}. 51 */ 52 public static final String ROOT = "ConstantSummary"; 53 54 /** 55 * The maximum number of package directories shown in the constant 56 * value index. 57 */ 58 public static final int MAX_CONSTANT_VALUE_INDEX_LENGTH = 2; 59 60 /** 61 * The writer used to write the results. 62 */ 63 protected final ConstantsSummaryWriter writer; 64 65 /** 66 * The set of ClassDocs that have constant fields. 67 */ 68 protected final Set<ClassDoc> classDocsWithConstFields; 69 70 /** 71 * The set of printed package headers. 72 */ 73 protected Set<String> printedPackageHeaders; 74 75 /** 76 * The current package being documented. 77 */ 78 private PackageDoc currentPackage; 79 80 /** 81 * The current class being documented. 82 */ 83 private ClassDoc currentClass; 84 85 /** 86 * The content tree for the constant summary documentation. 87 */ 88 private Content contentTree; 89 90 /** 91 * True if first package is listed. 92 */ 93 private boolean first = true; 94 95 /** 96 * Construct a new ConstantsSummaryBuilder. 97 * 98 * @param context the build context. 99 * @param writer the writer for the summary. 100 */ 101 private ConstantsSummaryBuilder(Context context, 102 ConstantsSummaryWriter writer) { 103 super(context); 104 this.writer = writer; 105 this.classDocsWithConstFields = new HashSet<>(); 106 } 107 108 /** 109 * Construct a ConstantsSummaryBuilder. 110 * 111 * @param context the build context. 112 * @param writer the writer for the summary. 113 */ 114 public static ConstantsSummaryBuilder getInstance(Context context, 115 ConstantsSummaryWriter writer) { 116 return new ConstantsSummaryBuilder(context, writer); 117 } 118 119 /** 120 * {@inheritDoc} 121 */ 122 public void build() throws IOException { 123 if (writer == null) { 124 //Doclet does not support this output. 125 return; 126 } 127 build(layoutParser.parseXML(ROOT), contentTree); 128 } 129 130 /** 131 * {@inheritDoc} 132 */ 133 public String getName() { 134 return ROOT; 135 } 136 137 /** 138 * Build the constant summary. 139 * 140 * @param node the XML element that specifies which components to document 141 * @param contentTree the content tree to which the documentation will be added 142 */ 143 public void buildConstantSummary(XMLNode node, Content contentTree) throws Exception { 144 contentTree = writer.getHeader(); 145 buildChildren(node, contentTree); 146 writer.addFooter(contentTree); 147 writer.printDocument(contentTree); 148 writer.close(); 149 } 150 151 /** 152 * Build the list of packages. 153 * 154 * @param node the XML element that specifies which components to document 155 * @param contentTree the content tree to which the content list will be added 156 */ 157 public void buildContents(XMLNode node, Content contentTree) { 158 Content contentListTree = writer.getContentsHeader(); 159 printedPackageHeaders = new HashSet<>(); 160 for (PackageDoc pkg : configuration.packages) { 161 if (hasConstantField(pkg) && !hasPrintedPackageIndex(pkg.name())) { 162 writer.addLinkToPackageContent(pkg, 163 parsePackageName(pkg.name()), 164 printedPackageHeaders, contentListTree); 165 } 166 } 167 writer.addContentsList(contentTree, contentListTree); 168 } 169 170 /** 171 * Build the summary for each documented package. 172 * 173 * @param node the XML element that specifies which components to document 174 * @param contentTree the tree to which the summaries will be added 175 */ 176 public void buildConstantSummaries(XMLNode node, Content contentTree) { 177 printedPackageHeaders = new HashSet<>(); 178 Content summariesTree = writer.getConstantSummaries(); 179 for (PackageDoc aPackage : configuration.packages) { 180 if (hasConstantField(aPackage)) { 181 currentPackage = aPackage; 182 //Build the documentation for the current package. 183 buildChildren(node, summariesTree); 184 first = false; 185 } 186 } 187 writer.addConstantSummaries(contentTree, summariesTree); 188 } 189 190 /** 191 * Build the header for the given package. 192 * 193 * @param node the XML element that specifies which components to document 194 * @param summariesTree the tree to which the package header will be added 195 */ 196 public void buildPackageHeader(XMLNode node, Content summariesTree) { 197 String parsedPackageName = parsePackageName(currentPackage.name()); 198 if (! printedPackageHeaders.contains(parsedPackageName)) { 199 writer.addPackageName(parsePackageName(currentPackage.name()), summariesTree, first); 200 printedPackageHeaders.add(parsedPackageName); 201 } 202 } 203 204 /** 205 * Build the summary for the current class. 206 * 207 * @param node the XML element that specifies which components to document 208 * @param summariesTree the tree to which the class constant summary will be added 209 */ 210 public void buildClassConstantSummary(XMLNode node, Content summariesTree) { 211 ClassDoc[] classes = currentPackage.name().length() > 0 ? 212 currentPackage.allClasses() : 213 configuration.classDocCatalog.allClasses( 214 DocletConstants.DEFAULT_PACKAGE_NAME); 215 Arrays.sort(classes); 216 Content classConstantTree = writer.getClassConstantHeader(); 217 for (ClassDoc doc : classes) { 218 if (!classDocsWithConstFields.contains(doc) || 219 !doc.isIncluded()) { 220 continue; 221 } 222 currentClass = doc; 223 //Build the documentation for the current class. 224 buildChildren(node, classConstantTree); 225 } 226 writer.addClassConstant(summariesTree, classConstantTree); 227 } 228 229 /** 230 * Build the summary of constant members in the class. 231 * 232 * @param node the XML element that specifies which components to document 233 * @param classConstantTree the tree to which the constant members table 234 * will be added 235 */ 236 public void buildConstantMembers(XMLNode node, Content classConstantTree) { 237 new ConstantFieldBuilder(currentClass).buildMembersSummary(node, classConstantTree); 238 } 239 240 /** 241 * Return true if the given package has constant fields to document. 242 * 243 * @param pkg the package being checked. 244 * @return true if the given package has constant fields to document. 245 */ 246 private boolean hasConstantField(PackageDoc pkg) { 247 ClassDoc[] classes 248 = (pkg.name().length() > 0) 249 ? pkg.allClasses() 250 : configuration.classDocCatalog.allClasses(DocletConstants.DEFAULT_PACKAGE_NAME); 251 boolean found = false; 252 for (ClassDoc doc : classes) { 253 if (doc.isIncluded() && hasConstantField(doc)) { 254 found = true; 255 } 256 } 257 return found; 258 } 259 260 /** 261 * Return true if the given class has constant fields to document. 262 * 263 * @param classDoc the class being checked. 264 * @return true if the given package has constant fields to document. 265 */ 266 private boolean hasConstantField (ClassDoc classDoc) { 267 VisibleMemberMap visibleMemberMapFields = new VisibleMemberMap(classDoc, 268 VisibleMemberMap.FIELDS, configuration); 269 List<?> fields = visibleMemberMapFields.getLeafClassMembers(configuration); 270 for (Object f : fields) { 271 FieldDoc field = (FieldDoc) f; 272 if (field.constantValueExpression() != null) { 273 classDocsWithConstFields.add(classDoc); 274 return true; 275 } 276 } 277 return false; 278 } 279 280 /** 281 * Return true if the given package name has been printed. Also 282 * return true if the root of this package has been printed. 283 * 284 * @param pkgname the name of the package to check. 285 */ 286 private boolean hasPrintedPackageIndex(String pkgname) { 287 String[] list = printedPackageHeaders.toArray(new String[] {}); 288 for (String packageHeader : list) { 289 if (pkgname.startsWith(packageHeader)) { 290 return true; 291 } 292 } 293 return false; 294 } 295 296 /** 297 * Print the table of constants. 298 * 299 * @author Jamie Ho 300 * @since 1.4 301 */ 302 private class ConstantFieldBuilder { 303 304 /** 305 * The map used to get the visible variables. 306 */ 307 protected VisibleMemberMap visibleMemberMapFields = null; 308 309 /** 310 * The map used to get the visible variables. 311 */ 312 protected VisibleMemberMap visibleMemberMapEnumConst = null; 313 314 /** 315 * The classdoc that we are examining constants for. 316 */ 317 protected ClassDoc classdoc; 318 319 /** 320 * Construct a ConstantFieldSubWriter. 321 * @param classdoc the classdoc that we are examining constants for. 322 */ 323 public ConstantFieldBuilder(ClassDoc classdoc) { 324 this.classdoc = classdoc; 325 visibleMemberMapFields = new VisibleMemberMap(classdoc, 326 VisibleMemberMap.FIELDS, configuration); 327 visibleMemberMapEnumConst = new VisibleMemberMap(classdoc, 328 VisibleMemberMap.ENUM_CONSTANTS, configuration); 329 } 330 331 /** 332 * Builds the table of constants for a given class. 333 * 334 * @param node the XML element that specifies which components to document 335 * @param classConstantTree the tree to which the class constants table 336 * will be added 337 */ 338 protected void buildMembersSummary(XMLNode node, Content classConstantTree) { 339 List<FieldDoc> members = new ArrayList<>(members()); 340 if (members.size() > 0) { 341 Collections.sort(members); 342 writer.addConstantMembers(classdoc, members, classConstantTree); 343 } 344 } 345 346 /** 347 * Return the list of visible constant fields for the given classdoc. 348 * @return the list of visible constant fields for the given classdoc. 349 */ 350 protected List<FieldDoc> members() { 351 List<ProgramElementDoc> l = visibleMemberMapFields.getLeafClassMembers(configuration); 352 l.addAll(visibleMemberMapEnumConst.getLeafClassMembers(configuration)); 353 Iterator<ProgramElementDoc> iter; 354 355 if(l != null){ 356 iter = l.iterator(); 357 } else { 358 return null; 359 } 360 List<FieldDoc> inclList = new LinkedList<>(); 361 FieldDoc member; 362 while(iter.hasNext()){ 363 member = (FieldDoc)iter.next(); 364 if(member.constantValue() != null){ 365 inclList.add(member); 366 } 367 } 368 return inclList; 369 } 370 } 371 372 /** 373 * Parse the package name. We only want to display package name up to 374 * 2 levels. 375 */ 376 private String parsePackageName(String pkgname) { 377 int index = -1; 378 for (int j = 0; j < MAX_CONSTANT_VALUE_INDEX_LENGTH; j++) { 379 index = pkgname.indexOf(".", index + 1); 380 } 381 if (index != -1) { 382 pkgname = pkgname.substring(0, index); 383 } 384 return pkgname; 385 } 386 } | 1 /* 2 * Copyright (c) 2003, 2016, 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.toolkit.builders; 27 28 import java.io.*; 29 import java.util.*; 30 31 import javax.lang.model.element.Element; 32 import javax.lang.model.element.PackageElement; 33 import javax.lang.model.element.TypeElement; 34 import javax.lang.model.element.VariableElement; 35 36 import jdk.javadoc.internal.doclets.toolkit.ConstantsSummaryWriter; 37 import jdk.javadoc.internal.doclets.toolkit.Content; 38 import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap; 39 40 41 /** 42 * Builds the Constants Summary Page. 43 * 44 * <p><b>This is NOT part of any supported API. 45 * If you write code that depends on this, you do so at your own risk. 46 * This code and its internal interfaces are subject to change or 47 * deletion without notice.</b> 48 * 49 * @author Jamie Ho 50 * @author Bhavesh Patel (Modified) 51 * @since 1.5 52 */ 53 public class ConstantsSummaryBuilder extends AbstractBuilder { 54 55 /** 56 * The root element of the constant summary XML is {@value}. 57 */ 58 public static final String ROOT = "ConstantSummary"; 59 60 /** 61 * The maximum number of package directories shown in the constant 62 * value index. 63 */ 64 public static final int MAX_CONSTANT_VALUE_INDEX_LENGTH = 2; 65 66 /** 67 * The writer used to write the results. 68 */ 69 protected final ConstantsSummaryWriter writer; 70 71 /** 72 * The set of TypeElements that have constant fields. 73 */ 74 protected final Set<TypeElement> typeElementsWithConstFields; 75 76 /** 77 * The set of printed package headers. 78 */ 79 protected final Set<PackageElement> printedPackageHeaders; 80 81 /** 82 * The current package being documented. 83 */ 84 private PackageElement currentPackage; 85 86 /** 87 * The current class being documented. 88 */ 89 private TypeElement currentClass; 90 91 /** 92 * The content tree for the constant summary documentation. 93 */ 94 private Content contentTree; 95 96 /** 97 * True if first package is listed. 98 */ 99 private boolean first = true; 100 101 /** 102 * Construct a new ConstantsSummaryBuilder. 103 * 104 * @param context the build context. 105 * @param writer the writer for the summary. 106 */ 107 private ConstantsSummaryBuilder(Context context, 108 ConstantsSummaryWriter writer) { 109 super(context); 110 this.writer = writer; 111 this.typeElementsWithConstFields = new HashSet<>(); 112 this.printedPackageHeaders = new TreeSet<>(utils.makePackageComparator()); 113 } 114 115 /** 116 * Construct a ConstantsSummaryBuilder. 117 * 118 * @param context the build context. 119 * @param writer the writer for the summary. 120 */ 121 public static ConstantsSummaryBuilder getInstance(Context context, 122 ConstantsSummaryWriter writer) { 123 return new ConstantsSummaryBuilder(context, writer); 124 } 125 126 /** 127 * {@inheritDoc} 128 */ 129 @Override 130 public void build() throws IOException { 131 if (writer == null) { 132 //Doclet does not support this output. 133 return; 134 } 135 build(layoutParser.parseXML(ROOT), contentTree); 136 } 137 138 /** 139 * {@inheritDoc} 140 */ 141 @Override 142 public String getName() { 143 return ROOT; 144 } 145 146 /** 147 * Build the constant summary. 148 * 149 * @param node the XML element that specifies which components to document 150 * @param contentTree the content tree to which the documentation will be added 151 */ 152 public void buildConstantSummary(XMLNode node, Content contentTree) throws Exception { 153 contentTree = writer.getHeader(); 154 buildChildren(node, contentTree); 155 writer.addFooter(contentTree); 156 writer.printDocument(contentTree); 157 writer.close(); 158 } 159 160 /** 161 * Build the list of packages. 162 * 163 * @param node the XML element that specifies which components to document 164 * @param contentTree the content tree to which the content list will be added 165 */ 166 public void buildContents(XMLNode node, Content contentTree) { 167 Content contentListTree = writer.getContentsHeader(); 168 printedPackageHeaders.clear(); 169 for (PackageElement pkg : configuration.packages) { 170 if (hasConstantField(pkg) && !hasPrintedPackageIndex(pkg)) { 171 writer.addLinkToPackageContent(pkg, printedPackageHeaders, contentListTree); 172 } 173 } 174 writer.addContentsList(contentTree, contentListTree); 175 } 176 177 /** 178 * Build the summary for each documented package. 179 * 180 * @param node the XML element that specifies which components to document 181 * @param contentTree the tree to which the summaries will be added 182 */ 183 public void buildConstantSummaries(XMLNode node, Content contentTree) { 184 printedPackageHeaders.clear(); 185 Content summariesTree = writer.getConstantSummaries(); 186 for (PackageElement aPackage : configuration.packages) { 187 if (hasConstantField(aPackage)) { 188 currentPackage = aPackage; 189 //Build the documentation for the current package. 190 buildChildren(node, summariesTree); 191 first = false; 192 } 193 } 194 writer.addConstantSummaries(contentTree, summariesTree); 195 } 196 197 /** 198 * Build the header for the given package. 199 * 200 * @param node the XML element that specifies which components to document 201 * @param summariesTree the tree to which the package header will be added 202 */ 203 public void buildPackageHeader(XMLNode node, Content summariesTree) { 204 String parsedPackageName = utils.parsePackageName(currentPackage); 205 PackageElement p = utils.elementUtils.getPackageElement(parsedPackageName); 206 if (!printedPackageHeaders.contains(p)) { 207 writer.addPackageName(currentPackage, summariesTree, first); 208 printedPackageHeaders.add(p); 209 } 210 } 211 212 /** 213 * Build the summary for the current class. 214 * 215 * @param node the XML element that specifies which components to document 216 * @param summariesTree the tree to which the class constant summary will be added 217 */ 218 public void buildClassConstantSummary(XMLNode node, Content summariesTree) { 219 SortedSet<TypeElement> classes = !currentPackage.isUnnamed() 220 ? utils.getAllClasses(currentPackage) 221 : configuration.classDocCatalog.allUnnamedClasses(); 222 Content classConstantTree = writer.getClassConstantHeader(); 223 for (TypeElement te : classes) { 224 if (!typeElementsWithConstFields.contains(te) || 225 !utils.isIncluded(te)) { 226 continue; 227 } 228 currentClass = te; 229 //Build the documentation for the current class. 230 buildChildren(node, classConstantTree); 231 } 232 writer.addClassConstant(summariesTree, classConstantTree); 233 } 234 235 /** 236 * Build the summary of constant members in the class. 237 * 238 * @param node the XML element that specifies which components to document 239 * @param classConstantTree the tree to which the constant members table 240 * will be added 241 */ 242 public void buildConstantMembers(XMLNode node, Content classConstantTree) { 243 new ConstantFieldBuilder(currentClass).buildMembersSummary(node, classConstantTree); 244 } 245 246 /** 247 * Return true if the given package has constant fields to document. 248 * 249 * @param pkg the package being checked. 250 * @return true if the given package has constant fields to document. 251 */ 252 private boolean hasConstantField(PackageElement pkg) { 253 SortedSet<TypeElement> classes = !pkg.isUnnamed() 254 ? utils.getAllClasses(pkg) 255 : configuration.classDocCatalog.allUnnamedClasses(); 256 boolean found = false; 257 for (TypeElement te : classes) { 258 if (utils.isIncluded(te) && hasConstantField(te)) { 259 found = true; 260 } 261 } 262 return found; 263 } 264 265 /** 266 * Return true if the given class has constant fields to document. 267 * 268 * @param typeElement the class being checked. 269 * @return true if the given package has constant fields to document. 270 */ 271 private boolean hasConstantField (TypeElement typeElement) { 272 VisibleMemberMap visibleMemberMapFields = new VisibleMemberMap(typeElement, 273 VisibleMemberMap.Kind.FIELDS, configuration); 274 SortedSet<Element> fields = visibleMemberMapFields.getLeafClassMembers(); 275 for (Element f : fields) { 276 VariableElement field = (VariableElement)f; 277 if (field.getConstantValue() != null) { 278 typeElementsWithConstFields.add(typeElement); 279 return true; 280 } 281 } 282 return false; 283 } 284 285 /** 286 * Return true if the given package name has been printed. Also 287 * return true if the root of this package has been printed. 288 * 289 * @param pkgname the name of the package to check. 290 */ 291 private boolean hasPrintedPackageIndex(PackageElement pkg) { 292 for (PackageElement printedPkg : printedPackageHeaders) { 293 if (utils.getPackageName(pkg).startsWith(utils.parsePackageName(printedPkg))) { 294 return true; 295 } 296 } 297 return false; 298 } 299 300 /** 301 * Print the table of constants. 302 * 303 * @author Jamie Ho 304 * @since 1.4 305 */ 306 private class ConstantFieldBuilder { 307 308 /** 309 * The map used to get the visible variables. 310 */ 311 protected VisibleMemberMap visibleMemberMapFields = null; 312 313 /** 314 * The map used to get the visible variables. 315 */ 316 protected VisibleMemberMap visibleMemberMapEnumConst = null; 317 318 /** 319 * The typeElement that we are examining constants for. 320 */ 321 protected TypeElement typeElement; 322 323 /** 324 * Construct a ConstantFieldSubWriter. 325 * @param typeElement the typeElement that we are examining constants for. 326 */ 327 public ConstantFieldBuilder(TypeElement typeElement) { 328 this.typeElement = typeElement; 329 visibleMemberMapFields = new VisibleMemberMap(typeElement, 330 VisibleMemberMap.Kind.FIELDS, configuration); 331 visibleMemberMapEnumConst = new VisibleMemberMap(typeElement, 332 VisibleMemberMap.Kind.ENUM_CONSTANTS, configuration); 333 } 334 335 /** 336 * Builds the table of constants for a given class. 337 * 338 * @param node the XML element that specifies which components to document 339 * @param classConstantTree the tree to which the class constants table 340 * will be added 341 */ 342 protected void buildMembersSummary(XMLNode node, Content classConstantTree) { 343 SortedSet<VariableElement> members = members(); 344 if (!members.isEmpty()) { 345 writer.addConstantMembers(typeElement, members, classConstantTree); 346 } 347 } 348 349 /** 350 * Return the list of visible constant fields for the given TypeElement. 351 * @return the list of visible constant fields for the given TypeElement. 352 */ 353 protected SortedSet<VariableElement> members() { 354 SortedSet<Element> list = visibleMemberMapFields.getLeafClassMembers(); 355 list.addAll(visibleMemberMapEnumConst.getLeafClassMembers()); 356 SortedSet<VariableElement> inclList = 357 new TreeSet<>(utils.makeGeneralPurposeComparator()); 358 for (Element element : list) { 359 VariableElement member = (VariableElement)element; 360 if (member.getConstantValue() != null) { 361 inclList.add(member); 362 } 363 } 364 return inclList; 365 } 366 } 367 } |