src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ConstantsSummaryBuilder.java

Wed, 01 Dec 2010 11:02:38 -0800

author
bpatel
date
Wed, 01 Dec 2010 11:02:38 -0800
changeset 766
90af8d87741f
parent 589
4177f5bdd189
child 798
4868a36f6fd8
permissions
-rw-r--r--

6851834: Javadoc doclet needs a structured approach to generate the output HTML.
Reviewed-by: jjg

     1 /*
     2  * Copyright (c) 2003, 2008, 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  */
    26 package com.sun.tools.doclets.internal.toolkit.builders;
    28 import java.io.*;
    29 import java.util.*;
    30 import com.sun.javadoc.*;
    31 import com.sun.tools.doclets.internal.toolkit.util.*;
    32 import com.sun.tools.doclets.internal.toolkit.*;
    34 /**
    35  * Builds the Constants Summary Page.
    36  *
    37  * This code is not part of an API.
    38  * It is implementation that is subject to change.
    39  * Do not use it as an API
    40  *
    41  * @author Jamie Ho
    42  * @author Bhavesh Patel (Modified)
    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      * The content tree for the constant summary documentation.
    85      */
    86     private Content contentTree;
    88     /**
    89      * Construct a new ConstantsSummaryBuilder.
    90      *
    91      * @param configuration the current configuration of the
    92      *                      doclet.
    93      */
    94     private ConstantsSummaryBuilder(Configuration configuration) {
    95         super(configuration);
    96     }
    98     /**
    99      * Construct a ConstantsSummaryBuilder.
   100      *
   101      * @param configuration the configuration used in this run
   102      *                      of the doclet.
   103      * @param writer        the writer for the summary.
   104      */
   105     public static ConstantsSummaryBuilder getInstance(
   106         Configuration configuration, ConstantsSummaryWriter writer) {
   107         ConstantsSummaryBuilder builder = new ConstantsSummaryBuilder(
   108             configuration);
   109         builder.writer = writer;
   110         builder.classDocsWithConstFields = new HashSet<ClassDoc>();
   111         return builder;
   112     }
   114     /**
   115      * {@inheritDoc}
   116      */
   117     public void build() throws IOException {
   118         if (writer == null) {
   119             //Doclet does not support this output.
   120             return;
   121         }
   122         build(LayoutParser.getInstance(configuration).parseXML(ROOT), contentTree);
   123     }
   125     /**
   126      * {@inheritDoc}
   127      */
   128     public String getName() {
   129         return ROOT;
   130     }
   132     /**
   133      * Build the constant summary.
   134      *
   135      * @param node the XML element that specifies which components to document
   136      * @param contentTree the content tree to which the documentation will be added
   137      */
   138     public void buildConstantSummary(XMLNode node, Content contentTree) throws Exception {
   139         contentTree = writer.getHeader();
   140         buildChildren(node, contentTree);
   141         writer.addFooter(contentTree);
   142         writer.printDocument(contentTree);
   143         writer.close();
   144     }
   146     /**
   147      * Build the list of packages.
   148      *
   149      * @param node the XML element that specifies which components to document
   150      * @param contentTree the content tree to which the content list will be added
   151      */
   152     public void buildContents(XMLNode node, Content contentTree) {
   153         Content contentListTree = writer.getContentsHeader();
   154         PackageDoc[] packages = configuration.packages;
   155         printedPackageHeaders = new HashSet<String>();
   156         for (int i = 0; i < packages.length; i++) {
   157             if (hasConstantField(packages[i]) && ! hasPrintedPackageIndex(packages[i].name())) {
   158                 writer.addLinkToPackageContent(packages[i],
   159                     parsePackageName(packages[i].name()),
   160                     printedPackageHeaders, contentListTree);
   161             }
   162         }
   163         contentTree.addContent(writer.getContentsList(contentListTree));
   164     }
   166     /**
   167      * Build the summary for each documented package.
   168      *
   169      * @param node the XML element that specifies which components to document
   170      * @param contentTree the tree to which the summaries will be added
   171      */
   172     public void buildConstantSummaries(XMLNode node, Content contentTree) {
   173         PackageDoc[] packages = configuration.packages;
   174         printedPackageHeaders = new HashSet<String>();
   175         Content summariesTree = writer.getConstantSummaries();
   176         for (int i = 0; i < packages.length; i++) {
   177             if (hasConstantField(packages[i])) {
   178                 currentPackage = packages[i];
   179                 //Build the documentation for the current package.
   180                 buildChildren(node, summariesTree);
   181             }
   182         }
   183         contentTree.addContent(summariesTree);
   184     }
   186     /**
   187      * Build the header for the given package.
   188      *
   189      * @param node the XML element that specifies which components to document
   190      * @param summariesTree the tree to which the package header will be added
   191      */
   192     public void buildPackageHeader(XMLNode node, Content summariesTree) {
   193         String parsedPackageName = parsePackageName(currentPackage.name());
   194         if (! printedPackageHeaders.contains(parsedPackageName)) {
   195             writer.addPackageName(currentPackage,
   196                 parsePackageName(currentPackage.name()), summariesTree);
   197             printedPackageHeaders.add(parsedPackageName);
   198         }
   199     }
   201     /**
   202      * Build the summary for the current class.
   203      *
   204      * @param node the XML element that specifies which components to document
   205      * @param summariesTree the tree to which the class constant summary will be added
   206      */
   207     public void buildClassConstantSummary(XMLNode node, Content summariesTree) {
   208         ClassDoc[] classes = currentPackage.name().length() > 0 ?
   209             currentPackage.allClasses() :
   210             configuration.classDocCatalog.allClasses(
   211                 DocletConstants.DEFAULT_PACKAGE_NAME);
   212         Arrays.sort(classes);
   213         Content classConstantTree = writer.getClassConstantHeader();
   214         for (int i = 0; i < classes.length; i++) {
   215             if (! classDocsWithConstFields.contains(classes[i]) ||
   216                 ! classes[i].isIncluded()) {
   217                 continue;
   218             }
   219             currentClass = classes[i];
   220             //Build the documentation for the current class.
   221             buildChildren(node, classConstantTree);
   222         }
   223         summariesTree.addContent(classConstantTree);
   224     }
   226     /**
   227      * Build the summary of constant members in the class.
   228      *
   229      * @param node the XML element that specifies which components to document
   230      * @param classConstantTree the tree to which the constant members table
   231      *                          will be added
   232      */
   233     public void buildConstantMembers(XMLNode node, Content classConstantTree) {
   234         new ConstantFieldBuilder(currentClass).buildMembersSummary(node, classConstantTree);
   235     }
   237     /**
   238      * Return true if the given package has constant fields to document.
   239      *
   240      * @param pkg   the package being checked.
   241      * @return true if the given package has constant fields to document.
   242      */
   243     private boolean hasConstantField(PackageDoc pkg) {
   244         ClassDoc[] classes;
   245         if (pkg.name().length() > 0) {
   246             classes = pkg.allClasses();
   247         } else {
   248             classes = configuration.classDocCatalog.allClasses(
   249                 DocletConstants.DEFAULT_PACKAGE_NAME);
   250         }
   251         boolean found = false;
   252         for (int j = 0; j < classes.length; j++){
   253             if (classes[j].isIncluded() && hasConstantField(classes[j])) {
   254                 found = true;
   255             }
   256         }
   257         return found;
   258     }
   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.nodeprecated);
   269         List<?> fields = visibleMemberMapFields.getLeafClassMembers(configuration);
   270         for (Iterator<?> iter = fields.iterator(); iter.hasNext(); ) {
   271             FieldDoc field = (FieldDoc) iter.next();
   272             if (field.constantValueExpression() != null) {
   273                 classDocsWithConstFields.add(classDoc);
   274                 return true;
   275             }
   276         }
   277         return false;
   278     }
   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 (int i = 0; i < list.length; i++) {
   289             if (pkgname.startsWith(list[i])) {
   290                 return true;
   291             }
   292         }
   293         return false;
   294     }
   296     /**
   297      * Print the table of constants.
   298      *
   299      * @author Jamie Ho
   300      * @since 1.4
   301      */
   302     private class ConstantFieldBuilder {
   304         /**
   305          * The map used to get the visible variables.
   306          */
   307         protected VisibleMemberMap visibleMemberMapFields = null;
   309         /**
   310          * The map used to get the visible variables.
   311          */
   312         protected VisibleMemberMap visibleMemberMapEnumConst = null;
   314         /**
   315          * The classdoc that we are examining constants for.
   316          */
   317         protected ClassDoc classdoc;
   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.nodeprecated);
   327             visibleMemberMapEnumConst = new VisibleMemberMap(classdoc,
   328                 VisibleMemberMap.ENUM_CONSTANTS, configuration.nodeprecated);
   329         }
   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<FieldDoc>(members());
   340             if (members.size() > 0) {
   341                 Collections.sort(members);
   342                 writer.addConstantMembers(classdoc, members, classConstantTree);
   343             }
   344         }
   346         /**
   347          * Return the list of visible constant fields for the given classdoc.
   348          * @param cd the classdoc to examine.
   349          * @return the list of visible constant fields for the given classdoc.
   350          */
   351         protected List<FieldDoc> members() {
   352             List<ProgramElementDoc> l = visibleMemberMapFields.getLeafClassMembers(configuration);
   353             l.addAll(visibleMemberMapEnumConst.getLeafClassMembers(configuration));
   354             Iterator<ProgramElementDoc> iter;
   356             if(l != null){
   357                 iter = l.iterator();
   358             } else {
   359                 return null;
   360             }
   361             List<FieldDoc> inclList = new LinkedList<FieldDoc>();
   362             FieldDoc member;
   363             while(iter.hasNext()){
   364                 member = (FieldDoc)iter.next();
   365                 if(member.constantValue() != null){
   366                     inclList.add(member);
   367                 }
   368             }
   369             return inclList;
   370         }
   371     }
   373     /**
   374      * Parse the package name.  We only want to display package name up to
   375      * 2 levels.
   376      */
   377     private String parsePackageName(String pkgname) {
   378         int index = -1;
   379         for (int j = 0; j < MAX_CONSTANT_VALUE_INDEX_LENGTH; j++) {
   380             index = pkgname.indexOf(".", index + 1);
   381         }
   382         if (index != -1) {
   383             pkgname = pkgname.substring(0, index);
   384         }
   385         return pkgname;
   386     }
   387 }

mercurial