ConstantsSummaryBuilder.java revision 3294:9adfb22ff08f
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 PackageElement abbrevPkg = configuration.workArounds.getAbbreviatedPackageElement(currentPackage); 204 if (!printedPackageHeaders.contains(abbrevPkg)) { 205 writer.addPackageName(currentPackage, summariesTree, first); 206 printedPackageHeaders.add(abbrevPkg); 207 } 208 } 209 210 /** 211 * Build the summary for the current class. 212 * 213 * @param node the XML element that specifies which components to document 214 * @param summariesTree the tree to which the class constant summary will be added 215 */ 216 public void buildClassConstantSummary(XMLNode node, Content summariesTree) { 217 SortedSet<TypeElement> classes = !currentPackage.isUnnamed() 218 ? utils.getAllClasses(currentPackage) 219 : configuration.typeElementCatalog.allUnnamedClasses(); 220 Content classConstantTree = writer.getClassConstantHeader(); 221 for (TypeElement te : classes) { 222 if (!typeElementsWithConstFields.contains(te) || 223 !utils.isIncluded(te)) { 224 continue; 225 } 226 currentClass = te; 227 //Build the documentation for the current class. 228 buildChildren(node, classConstantTree); 229 } 230 writer.addClassConstant(summariesTree, classConstantTree); 231 } 232 233 /** 234 * Build the summary of constant members in the class. 235 * 236 * @param node the XML element that specifies which components to document 237 * @param classConstantTree the tree to which the constant members table 238 * will be added 239 */ 240 public void buildConstantMembers(XMLNode node, Content classConstantTree) { 241 new ConstantFieldBuilder(currentClass).buildMembersSummary(node, classConstantTree); 242 } 243 244 /** 245 * Return true if the given package has constant fields to document. 246 * 247 * @param pkg the package being checked. 248 * @return true if the given package has constant fields to document. 249 */ 250 private boolean hasConstantField(PackageElement pkg) { 251 SortedSet<TypeElement> classes = !pkg.isUnnamed() 252 ? utils.getAllClasses(pkg) 253 : configuration.typeElementCatalog.allUnnamedClasses(); 254 boolean found = false; 255 for (TypeElement te : classes) { 256 if (utils.isIncluded(te) && hasConstantField(te)) { 257 found = true; 258 } 259 } 260 return found; 261 } 262 263 /** 264 * Return true if the given class has constant fields to document. 265 * 266 * @param typeElement the class being checked. 267 * @return true if the given package has constant fields to document. 268 */ 269 private boolean hasConstantField (TypeElement typeElement) { 270 VisibleMemberMap visibleMemberMapFields = new VisibleMemberMap(typeElement, 271 VisibleMemberMap.Kind.FIELDS, configuration); 272 SortedSet<Element> fields = visibleMemberMapFields.getLeafClassMembers(); 273 for (Element f : fields) { 274 VariableElement field = (VariableElement)f; 275 if (field.getConstantValue() != null) { 276 typeElementsWithConstFields.add(typeElement); 277 return true; 278 } 279 } 280 return false; 281 } 282 283 /** 284 * Return true if the given package name has been printed. Also 285 * return true if the root of this package has been printed. 286 * 287 * @param pkgname the name of the package to check. 288 */ 289 private boolean hasPrintedPackageIndex(PackageElement pkg) { 290 for (PackageElement printedPkg : printedPackageHeaders) { 291 if (utils.getPackageName(pkg).startsWith(utils.parsePackageName(printedPkg))) { 292 return true; 293 } 294 } 295 return false; 296 } 297 298 /** 299 * Print the table of constants. 300 * 301 * @author Jamie Ho 302 */ 303 private class ConstantFieldBuilder { 304 305 /** 306 * The map used to get the visible variables. 307 */ 308 protected VisibleMemberMap visibleMemberMapFields = null; 309 310 /** 311 * The map used to get the visible variables. 312 */ 313 protected VisibleMemberMap visibleMemberMapEnumConst = null; 314 315 /** 316 * The typeElement that we are examining constants for. 317 */ 318 protected TypeElement typeElement; 319 320 /** 321 * Construct a ConstantFieldSubWriter. 322 * @param typeElement the typeElement that we are examining constants for. 323 */ 324 public ConstantFieldBuilder(TypeElement typeElement) { 325 this.typeElement = typeElement; 326 visibleMemberMapFields = new VisibleMemberMap(typeElement, 327 VisibleMemberMap.Kind.FIELDS, configuration); 328 visibleMemberMapEnumConst = new VisibleMemberMap(typeElement, 329 VisibleMemberMap.Kind.ENUM_CONSTANTS, configuration); 330 } 331 332 /** 333 * Builds the table of constants for a given class. 334 * 335 * @param node the XML element that specifies which components to document 336 * @param classConstantTree the tree to which the class constants table 337 * will be added 338 */ 339 protected void buildMembersSummary(XMLNode node, Content classConstantTree) { 340 SortedSet<VariableElement> members = members(); 341 if (!members.isEmpty()) { 342 writer.addConstantMembers(typeElement, members, classConstantTree); 343 } 344 } 345 346 /** 347 * Return the list of visible constant fields for the given TypeElement. 348 * @return the list of visible constant fields for the given TypeElement. 349 */ 350 protected SortedSet<VariableElement> members() { 351 SortedSet<Element> list = visibleMemberMapFields.getLeafClassMembers(); 352 list.addAll(visibleMemberMapEnumConst.getLeafClassMembers()); 353 SortedSet<VariableElement> inclList = 354 new TreeSet<>(utils.makeGeneralPurposeComparator()); 355 for (Element element : list) { 356 VariableElement member = (VariableElement)element; 357 if (member.getConstantValue() != null) { 358 inclList.add(member); 359 } 360 } 361 return inclList; 362 } 363 } 364} 365