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

Sun, 24 Feb 2013 11:36:58 -0800

author
jjg
date
Sun, 24 Feb 2013 11:36:58 -0800
changeset 1606
ccbe7ffdd867
parent 1410
bfec2a1cc869
child 2525
2eb010b6cb22
permissions
-rw-r--r--

7112427: The doclet needs to be able to generate JavaFX documentation.
Reviewed-by: jjg
Contributed-by: jan.valenta@oracle.com

     1 /*
     2  * Copyright (c) 2003, 2013, 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.*;
    31 import com.sun.javadoc.*;
    32 import com.sun.tools.doclets.internal.toolkit.*;
    33 import com.sun.tools.doclets.internal.toolkit.util.*;
    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 {
    49     /**
    50      * The root element of the constant summary XML is {@value}.
    51      */
    52     public static final String ROOT = "ConstantSummary";
    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;
    60     /**
    61      * The writer used to write the results.
    62      */
    63     protected final ConstantsSummaryWriter writer;
    65     /**
    66      * The set of ClassDocs that have constant fields.
    67      */
    68     protected final Set<ClassDoc> classDocsWithConstFields;
    70     /**
    71      * The set of printed package headers.
    72      */
    73     protected Set<String> printedPackageHeaders;
    75     /**
    76      * The current package being documented.
    77      */
    78     private PackageDoc currentPackage;
    80     /**
    81      * The current class being documented.
    82      */
    83     private ClassDoc currentClass;
    85     /**
    86      * The content tree for the constant summary documentation.
    87      */
    88     private Content contentTree;
    90     /**
    91      * Construct a new ConstantsSummaryBuilder.
    92      *
    93      * @param context       the build context.
    94      * @param writer        the writer for the summary.
    95      */
    96     private ConstantsSummaryBuilder(Context context,
    97             ConstantsSummaryWriter writer) {
    98         super(context);
    99         this.writer = writer;
   100         this.classDocsWithConstFields = new HashSet<ClassDoc>();
   101     }
   103     /**
   104      * Construct a ConstantsSummaryBuilder.
   105      *
   106      * @param context       the build context.
   107      * @param writer        the writer for the summary.
   108      */
   109     public static ConstantsSummaryBuilder getInstance(Context context,
   110             ConstantsSummaryWriter writer) {
   111         return new ConstantsSummaryBuilder(context, writer);
   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.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);
   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);
   327             visibleMemberMapEnumConst = new VisibleMemberMap(classdoc,
   328                 VisibleMemberMap.ENUM_CONSTANTS, configuration);
   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          * @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;
   355             if(l != null){
   356                 iter = l.iterator();
   357             } else {
   358                 return null;
   359             }
   360             List<FieldDoc> inclList = new LinkedList<FieldDoc>();
   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     }
   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 }

mercurial