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