Thu, 02 Oct 2008 19:58:40 -0700
6754988: Update copyright year
Summary: Update for files that have been modified starting July 2008
Reviewed-by: ohair, tbell
1 /*
2 * Copyright 2003-2008 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
26 package com.sun.tools.doclets.internal.toolkit.builders;
28 import com.sun.tools.doclets.internal.toolkit.util.*;
29 import com.sun.tools.doclets.internal.toolkit.*;
30 import com.sun.javadoc.*;
31 import java.io.*;
32 import java.util.*;
33 import java.lang.reflect.*;
35 /**
36 * Builds the Constants Summary Page.
37 *
38 * This code is not part of an API.
39 * It is implementation that is subject to change.
40 * Do not use it as an API
41 *
42 * @author Jamie Ho
43 * @since 1.5
44 */
45 public class ConstantsSummaryBuilder extends AbstractBuilder {
47 /**
48 * The root element of the constant summary XML is {@value}.
49 */
50 public static final String ROOT = "ConstantSummary";
52 /**
53 * The maximum number of package directories shown in the constant
54 * value index.
55 */
56 public static final int MAX_CONSTANT_VALUE_INDEX_LENGTH = 2;
58 /**
59 * The writer used to write the results.
60 */
61 protected ConstantsSummaryWriter writer;
63 /**
64 * The set of ClassDocs that have constant fields.
65 */
66 protected Set<ClassDoc> classDocsWithConstFields;
68 /**
69 * The set of printed package headers.
70 */
71 protected Set<String> printedPackageHeaders;
73 /**
74 * The current package being documented.
75 */
76 private PackageDoc currentPackage;
78 /**
79 * The current class being documented.
80 */
81 private ClassDoc currentClass;
83 /**
84 * Construct a new ConstantsSummaryBuilder.
85 *
86 * @param configuration the current configuration of the
87 * doclet.
88 */
89 private ConstantsSummaryBuilder(Configuration configuration) {
90 super(configuration);
91 }
93 /**
94 * Construct a ConstantsSummaryBuilder.
95 *
96 * @param configuration the configuration used in this run
97 * of the doclet.
98 * @param writer the writer for the summary.
99 */
100 public static ConstantsSummaryBuilder getInstance(
101 Configuration configuration, ConstantsSummaryWriter writer) {
102 ConstantsSummaryBuilder builder = new ConstantsSummaryBuilder(
103 configuration);
104 builder.writer = writer;
105 builder.classDocsWithConstFields = new HashSet<ClassDoc>();
106 return builder;
107 }
109 /**
110 * {@inheritDoc}
111 */
112 public void invokeMethod(String methodName, Class[] paramClasses,
113 Object[] params)
114 throws Exception {
115 if (DEBUG) {
116 configuration.root.printError("DEBUG: " + this.getClass().getName()
117 + "." + methodName);
118 }
119 Method method = this.getClass().getMethod(methodName, paramClasses);
120 method.invoke(this, params);
121 }
123 /**
124 * {@inheritDoc}
125 */
126 public void build() throws IOException {
127 if (writer == null) {
128 //Doclet does not support this output.
129 return;
130 }
131 build(LayoutParser.getInstance(configuration).parseXML(ROOT));
132 }
134 /**
135 * {@inheritDoc}
136 */
137 public String getName() {
138 return ROOT;
139 }
141 /**
142 * Build the constant summary.
143 *
144 * @param elements the list of elements describing constant summary
145 * documentation.
146 */
147 public void buildConstantSummary(List elements) throws Exception {
148 build(elements);
149 writer.close();
150 }
152 /**
153 * Build the header.
154 */
155 public void buildHeader() {
156 writer.writeHeader();
157 }
159 /**
160 * Build the footer.
161 */
162 public void buildFooter() {
163 writer.writeFooter();
164 }
166 /**
167 * Build the table of contents.
168 */
169 public void buildContents() {
170 writer.writeContentsHeader();
171 PackageDoc[] packages = configuration.packages;
172 printedPackageHeaders = new HashSet<String>();
173 for (int i = 0; i < packages.length; i++) {
174 if (hasConstantField(packages[i]) && ! hasPrintedPackageIndex(packages[i].name())) {
175 writer.writeLinkToPackageContent(packages[i],
176 parsePackageName(packages[i].name()),
177 printedPackageHeaders);
178 }
179 }
180 writer.writeContentsFooter();
181 }
183 /**
184 * Build the summary for each documented package.
185 *
186 * @param elements the XML elements that represent the components
187 * of documentation for each package.
188 */
189 public void buildConstantSummaries(List elements) {
190 PackageDoc[] packages = configuration.packages;
191 printedPackageHeaders = new HashSet<String>();
192 for (int i = 0; i < packages.length; i++) {
193 if (hasConstantField(packages[i])) {
194 currentPackage = packages[i];
195 //Build the documentation for the current package.
196 build(elements);
197 }
198 }
199 }
201 /**
202 * Build the summary for the current package.
203 *
204 * @param elements the list of XML elements that make up package
205 * documentation.
206 */
207 public void buildPackageConstantSummary(List elements) {
208 build(elements);
209 }
211 /**
212 * Build the summary for the current class.
213 *
214 * @param elements the list of XML elements that make up the class
215 * constant summary.
216 */
217 public void buildClassConstantSummary(List elements) {
218 ClassDoc[] classes = currentPackage.name().length() > 0 ?
219 currentPackage.allClasses() :
220 configuration.classDocCatalog.allClasses(
221 DocletConstants.DEFAULT_PACKAGE_NAME);
222 Arrays.sort(classes);
223 for (int i = 0; i < classes.length; i++) {
224 if (! classDocsWithConstFields.contains(classes[i]) ||
225 ! classes[i].isIncluded()) {
226 continue;
227 }
228 currentClass = classes[i];
229 //Build the documentation for the current class.
230 build(elements);
231 }
232 }
234 /**
235 * Build the header for the given class.
236 */
237 public void buildPackageHeader() {
238 String parsedPackageName = parsePackageName(currentPackage.name());
239 if (! printedPackageHeaders.contains(parsedPackageName)) {
240 writer.writePackageName(currentPackage,
241 parsePackageName(currentPackage.name()));
242 printedPackageHeaders.add(parsedPackageName);
243 }
244 }
246 /**
247 * Build the header for the given class.
248 */
249 public void buildClassHeader() {
250 writer.writeConstantMembersHeader(currentClass);
251 }
253 /**
254 * Print summary of constant members in the
255 * class.
256 */
257 public void buildConstantMembers() {
258 new ConstantFieldBuilder(currentClass).buildMembersSummary();
259 }
261 /**
262 * Build the footer for the given class.
263 */
264 public void buildClassFooter() {
265 writer.writeConstantMembersFooter(currentClass);
266 }
268 /**
269 * Return true if the given package has constant fields to document.
270 *
271 * @param pkg the package being checked.
272 * @return true if the given package has constant fields to document.
273 */
274 private boolean hasConstantField(PackageDoc pkg) {
275 ClassDoc[] classes;
276 if (pkg.name().length() > 0) {
277 classes = pkg.allClasses();
278 } else {
279 classes = configuration.classDocCatalog.allClasses(
280 DocletConstants.DEFAULT_PACKAGE_NAME);
281 }
282 boolean found = false;
283 for (int j = 0; j < classes.length; j++){
284 if (classes[j].isIncluded() && hasConstantField(classes[j])) {
285 found = true;
286 }
287 }
288 return found;
289 }
291 /**
292 * Return true if the given class has constant fields to document.
293 *
294 * @param classDoc the class being checked.
295 * @return true if the given package has constant fields to document.
296 */
297 private boolean hasConstantField (ClassDoc classDoc) {
298 VisibleMemberMap visibleMemberMapFields = new VisibleMemberMap(classDoc,
299 VisibleMemberMap.FIELDS, configuration.nodeprecated);
300 List fields = visibleMemberMapFields.getLeafClassMembers(configuration);
301 for (Iterator iter = fields.iterator(); iter.hasNext(); ) {
302 FieldDoc field = (FieldDoc) iter.next();
303 if (field.constantValueExpression() != null) {
304 classDocsWithConstFields.add(classDoc);
305 return true;
306 }
307 }
308 return false;
309 }
311 /**
312 * Return true if the given package name has been printed. Also
313 * return true if the root of this package has been printed.
314 *
315 * @param pkgname the name of the package to check.
316 */
317 private boolean hasPrintedPackageIndex(String pkgname) {
318 String[] list = printedPackageHeaders.toArray(new String[] {});
319 for (int i = 0; i < list.length; i++) {
320 if (pkgname.startsWith(list[i])) {
321 return true;
322 }
323 }
324 return false;
325 }
327 /**
328 * Print the table of constants.
329 *
330 * @author Jamie Ho
331 * @since 1.4
332 */
333 private class ConstantFieldBuilder {
335 /**
336 * The map used to get the visible variables.
337 */
338 protected VisibleMemberMap visibleMemberMapFields = null;
340 /**
341 * The map used to get the visible variables.
342 */
343 protected VisibleMemberMap visibleMemberMapEnumConst = null;
345 /**
346 * The classdoc that we are examining constants for.
347 */
348 protected ClassDoc classdoc;
350 /**
351 * Construct a ConstantFieldSubWriter.
352 * @param classdoc the classdoc that we are examining constants for.
353 */
354 public ConstantFieldBuilder(ClassDoc classdoc) {
355 this.classdoc = classdoc;
356 visibleMemberMapFields = new VisibleMemberMap(classdoc,
357 VisibleMemberMap.FIELDS, configuration.nodeprecated);
358 visibleMemberMapEnumConst = new VisibleMemberMap(classdoc,
359 VisibleMemberMap.ENUM_CONSTANTS, configuration.nodeprecated);
360 }
362 /**
363 * Builds the table of constants for a given class.
364 */
365 protected void buildMembersSummary() {
366 List<FieldDoc> members = new ArrayList<FieldDoc>(members());
367 if (members.size() > 0) {
368 Collections.sort(members);
369 writer.writeConstantMembers(classdoc, members);
370 }
371 }
373 /**
374 * Return the list of visible constant fields for the given classdoc.
375 * @param cd the classdoc to examine.
376 * @return the list of visible constant fields for the given classdoc.
377 */
378 protected List<FieldDoc> members() {
379 List<ProgramElementDoc> l = visibleMemberMapFields.getLeafClassMembers(configuration);
380 l.addAll(visibleMemberMapEnumConst.getLeafClassMembers(configuration));
381 Iterator<ProgramElementDoc> iter;
383 if(l != null){
384 iter = l.iterator();
385 } else {
386 return null;
387 }
388 List<FieldDoc> inclList = new LinkedList<FieldDoc>();
389 FieldDoc member;
390 while(iter.hasNext()){
391 member = (FieldDoc)iter.next();
392 if(member.constantValue() != null){
393 inclList.add(member);
394 }
395 }
396 return inclList;
397 }
398 }
400 /**
401 * Parse the package name. We only want to display package name up to
402 * 2 levels.
403 */
404 private String parsePackageName(String pkgname) {
405 int index = -1;
406 for (int j = 0; j < MAX_CONSTANT_VALUE_INDEX_LENGTH; j++) {
407 index = pkgname.indexOf(".", index + 1);
408 }
409 if (index != -1) {
410 pkgname = pkgname.substring(0, index);
411 }
412 return pkgname;
413 }
414 }