src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/SerializedFormBuilder.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, 2009, 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 serialized form.
    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 SerializedFormBuilder extends AbstractBuilder {
    47     /**
    48      * The root element of the serialized form XML is {@value}.
    49      */
    50     public static final String NAME = "SerializedForm";
    52     /**
    53      * The writer for this builder.
    54      */
    55     private SerializedFormWriter writer;
    57     /**
    58      * The writer for serializable fields.
    59      */
    60     private SerializedFormWriter.SerialFieldWriter fieldWriter;
    62     /**
    63      * The writer for serializable method documentation.
    64      */
    65     private SerializedFormWriter.SerialMethodWriter methodWriter;
    67     /**
    68      * The header for the serial version UID.  Save the string
    69      * here instead of the properties file because we do not want
    70      * this string to be localized.
    71      */
    72     private static final String SERIAL_VERSION_UID_HEADER = "serialVersionUID:";
    74     /**
    75      * The current package being documented.
    76      */
    77     private PackageDoc currentPackage;
    79     /**
    80      * The current class being documented.
    81      */
    82     private ClassDoc currentClass;
    84     /**
    85      * The current member being documented.
    86      */
    87     protected MemberDoc currentMember;
    89     /**
    90      * The content that will be added to the serialized form documentation tree.
    91      */
    92     private Content contentTree;
    94     private SerializedFormBuilder(Configuration configuration) {
    95         super(configuration);
    96     }
    98     /**
    99      * Construct a new SerializedFormBuilder.
   100      * @param configuration the current configuration of the doclet.
   101      */
   102     public static SerializedFormBuilder getInstance(Configuration configuration) {
   103         SerializedFormBuilder builder = new SerializedFormBuilder(configuration);
   104         return builder;
   105     }
   107     /**
   108      * Build the serialized form.
   109      */
   110     public void build() throws IOException {
   111         if (! serialClassFoundToDocument(configuration.root.classes())) {
   112             //Nothing to document.
   113             return;
   114         }
   115         try {
   116             writer = configuration.getWriterFactory().getSerializedFormWriter();
   117             if (writer == null) {
   118                 //Doclet does not support this output.
   119                 return;
   120             }
   121         } catch (Exception e) {
   122             throw new DocletAbortException();
   123         }
   124         build(LayoutParser.getInstance(configuration).parseXML(NAME), contentTree);
   125         writer.close();
   126     }
   128     /**
   129      * {@inheritDoc}
   130      */
   131     public String getName() {
   132         return NAME;
   133     }
   135     /**
   136      * Build the serialized form.
   137      *
   138      * @param node the XML element that specifies which components to document
   139      * @param serializedTree content tree to which the documentation will be added
   140      */
   141     public void buildSerializedForm(XMLNode node, Content serializedTree) throws Exception {
   142         serializedTree = writer.getHeader(configuration.getText(
   143                 "doclet.Serialized_Form"));
   144         buildChildren(node, serializedTree);
   145         writer.addFooter(serializedTree);
   146         writer.printDocument(serializedTree);
   147         writer.close();
   148     }
   150     /**
   151      * Build the serialized form summaries.
   152      *
   153      * @param node the XML element that specifies which components to document
   154      * @param serializedTree content tree to which the documentation will be added
   155      */
   156     public void buildSerializedFormSummaries(XMLNode node, Content serializedTree) {
   157         Content serializedSummariesTree = writer.getSerializedSummariesHeader();
   158         PackageDoc[] packages = configuration.packages;
   159         for (int i = 0; i < packages.length; i++) {
   160             currentPackage = packages[i];
   161             buildChildren(node, serializedSummariesTree);
   162         }
   163         serializedTree.addContent(writer.getSerializedContent(
   164                 serializedSummariesTree));
   165     }
   167     /**
   168      * Build the package serialized form for the current package being processed.
   169      *
   170      * @param node the XML element that specifies which components to document
   171      * @param serializedSummariesTree content tree to which the documentation will be added
   172      */
   173     public void buildPackageSerializedForm(XMLNode node, Content serializedSummariesTree) {
   174         Content packageSerializedTree = writer.getPackageSerializedHeader();
   175         String foo = currentPackage.name();
   176         ClassDoc[] classes = currentPackage.allClasses(false);
   177         if (classes == null || classes.length == 0) {
   178             return;
   179         }
   180         if (!serialInclude(currentPackage)) {
   181             return;
   182         }
   183         if (!serialClassFoundToDocument(classes)) {
   184             return;
   185         }
   186         buildChildren(node, packageSerializedTree);
   187         serializedSummariesTree.addContent(packageSerializedTree);
   188     }
   190     /**
   191      * Build the package header.
   192      *
   193      * @param node the XML element that specifies which components to document
   194      * @param packageSerializedTree content tree to which the documentation will be added
   195      */
   196     public void buildPackageHeader(XMLNode node, Content packageSerializedTree) {
   197         packageSerializedTree.addContent(writer.getPackageHeader(
   198                 Util.getPackageName(currentPackage)));
   199     }
   201     /**
   202      * Build the class serialized form.
   203      *
   204      * @param node the XML element that specifies which components to document
   205      * @param packageSerializedTree content tree to which the documentation will be added
   206      */
   207     public void buildClassSerializedForm(XMLNode node, Content packageSerializedTree) {
   208         Content classSerializedTree = writer.getClassSerializedHeader();
   209         ClassDoc[] classes = currentPackage.allClasses(false);
   210         Arrays.sort(classes);
   211         for (int j = 0; j < classes.length; j++) {
   212             currentClass = classes[j];
   213             fieldWriter = writer.getSerialFieldWriter(currentClass);
   214             methodWriter = writer.getSerialMethodWriter(currentClass);
   215             if(currentClass.isClass() && currentClass.isSerializable()) {
   216                 if(!serialClassInclude(currentClass)) {
   217                     continue;
   218                 }
   219                 Content classTree = writer.getClassHeader(currentClass);
   220                 buildChildren(node, classTree);
   221                 classSerializedTree.addContent(classTree);
   222             }
   223         }
   224         packageSerializedTree.addContent(classSerializedTree);
   225     }
   227     /**
   228      * Build the serial UID information for the given class.
   229      *
   230      * @param node the XML element that specifies which components to document
   231      * @param classTree content tree to which the serial UID information will be added
   232      */
   233     public void buildSerialUIDInfo(XMLNode node, Content classTree) {
   234         Content serialUidTree = writer.getSerialUIDInfoHeader();
   235         FieldDoc[] fields = currentClass.fields(false);
   236         for (int i = 0; i < fields.length; i++) {
   237             if (fields[i].name().equals("serialVersionUID") &&
   238                 fields[i].constantValueExpression() != null) {
   239                 writer.addSerialUIDInfo(SERIAL_VERSION_UID_HEADER,
   240                         fields[i].constantValueExpression(), serialUidTree);
   241                 break;
   242             }
   243         }
   244         classTree.addContent(serialUidTree);
   245     }
   247     /**
   248      * Build the summaries for the methods and fields.
   249      *
   250      * @param node the XML element that specifies which components to document
   251      * @param classTree content tree to which the documentation will be added
   252      */
   253     public void buildClassContent(XMLNode node, Content classTree) {
   254         Content classContentTree = writer.getClassContentHeader();
   255         buildChildren(node, classContentTree);
   256         classTree.addContent(classContentTree);
   257     }
   259     /**
   260      * Build the summaries for the methods that belong to the given
   261      * class.
   262      *
   263      * @param node the XML element that specifies which components to document
   264      * @param classContentTree content tree to which the documentation will be added
   265      */
   266     public void buildSerializableMethods(XMLNode node, Content classContentTree) {
   267         Content serializableMethodTree = methodWriter.getSerializableMethodsHeader();
   268         MemberDoc[] members = currentClass.serializationMethods();
   269         int membersLength = members.length;
   270         if (membersLength > 0) {
   271             for (int i = 0; i < membersLength; i++) {
   272                 currentMember = members[i];
   273                 Content methodsContentTree = methodWriter.getMethodsContentHeader(
   274                         (i == membersLength - 1));
   275                 buildChildren(node, methodsContentTree);
   276                 serializableMethodTree.addContent(methodsContentTree);
   277             }
   278         }
   279         if (currentClass.serializationMethods().length > 0) {
   280             classContentTree.addContent(methodWriter.getSerializableMethods(
   281                     configuration.getText("doclet.Serialized_Form_methods"),
   282                     serializableMethodTree));
   283             if (currentClass.isSerializable() && !currentClass.isExternalizable()) {
   284                 if (currentClass.serializationMethods().length == 0) {
   285                     Content noCustomizationMsg = methodWriter.getNoCustomizationMsg(
   286                             configuration.getText(
   287                             "doclet.Serializable_no_customization"));
   288                     classContentTree.addContent(methodWriter.getSerializableMethods(
   289                     configuration.getText("doclet.Serialized_Form_methods"),
   290                     noCustomizationMsg));
   291                 }
   292             }
   293         }
   294     }
   296     /**
   297      * Build the method sub header.
   298      *
   299      * @param node the XML element that specifies which components to document
   300      * @param methodsContentTree content tree to which the documentation will be added
   301      */
   302     public void buildMethodSubHeader(XMLNode node, Content methodsContentTree)  {
   303         methodWriter.addMemberHeader((MethodDoc)currentMember, methodsContentTree);
   304     }
   306     /**
   307      * Build the deprecated method description.
   308      *
   309      * @param node the XML element that specifies which components to document
   310      * @param methodsContentTree content tree to which the documentation will be added
   311      */
   312     public void buildDeprecatedMethodInfo(XMLNode node, Content methodsContentTree) {
   313         methodWriter.addDeprecatedMemberInfo((MethodDoc) currentMember, methodsContentTree);
   314     }
   316     /**
   317      * Build the information for the method.
   318      *
   319      * @param node the XML element that specifies which components to document
   320      * @param methodsContentTree content tree to which the documentation will be added
   321      */
   322     public void buildMethodInfo(XMLNode node, Content methodsContentTree)  {
   323         if(configuration.nocomment){
   324             return;
   325         }
   326         buildChildren(node, methodsContentTree);
   327     }
   329     /**
   330      * Build method description.
   331      *
   332      * @param node the XML element that specifies which components to document
   333      * @param methodsContentTree content tree to which the documentation will be added
   334      */
   335     public void buildMethodDescription(XMLNode node, Content methodsContentTree) {
   336         methodWriter.addMemberDescription((MethodDoc) currentMember, methodsContentTree);
   337     }
   339     /**
   340      * Build the method tags.
   341      *
   342      * @param node the XML element that specifies which components to document
   343      * @param methodsContentTree content tree to which the documentation will be added
   344      */
   345     public void buildMethodTags(XMLNode node, Content methodsContentTree) {
   346         methodWriter.addMemberTags((MethodDoc) currentMember, methodsContentTree);
   347         MethodDoc method = (MethodDoc)currentMember;
   348         if (method.name().compareTo("writeExternal") == 0
   349                 && method.tags("serialData").length == 0) {
   350             if (configuration.serialwarn) {
   351                 configuration.getDocletSpecificMsg().warning(
   352                         currentMember.position(), "doclet.MissingSerialDataTag",
   353                         method.containingClass().qualifiedName(), method.name());
   354             }
   355         }
   356     }
   358     /**
   359      * Build the field header.
   360      *
   361      * @param node the XML element that specifies which components to document
   362      * @param classContentTree content tree to which the documentation will be added
   363      */
   364     public void buildFieldHeader(XMLNode node, Content classContentTree) {
   365         if (currentClass.serializableFields().length > 0) {
   366             buildFieldSerializationOverview(currentClass, classContentTree);
   367         }
   368     }
   370     /**
   371      * Build the serialization overview for the given class.
   372      *
   373      * @param classDoc the class to print the overview for.
   374      * @param classContentTree content tree to which the documentation will be added
   375      */
   376     public void buildFieldSerializationOverview(ClassDoc classDoc, Content classContentTree) {
   377         if (classDoc.definesSerializableFields()) {
   378             FieldDoc serialPersistentField =
   379                 Util.asList(classDoc.serializableFields()).get(0);
   380             // Check to see if there are inline comments, tags or deprecation
   381             // information to be printed.
   382             if (fieldWriter.shouldPrintOverview(serialPersistentField)) {
   383                 Content serializableFieldsTree = fieldWriter.getSerializableFieldsHeader();
   384                 Content fieldsOverviewContentTree = fieldWriter.getFieldsContentHeader(true);
   385                 fieldWriter.addMemberDeprecatedInfo(serialPersistentField,
   386                         fieldsOverviewContentTree);
   387                 if (!configuration.nocomment) {
   388                     fieldWriter.addMemberDescription(serialPersistentField,
   389                             fieldsOverviewContentTree);
   390                     fieldWriter.addMemberTags(serialPersistentField,
   391                             fieldsOverviewContentTree);
   392                 }
   393                 serializableFieldsTree.addContent(fieldsOverviewContentTree);
   394                 classContentTree.addContent(fieldWriter.getSerializableFields(
   395                         configuration.getText("doclet.Serialized_Form_class"),
   396                         serializableFieldsTree));
   397             }
   398         }
   399     }
   401     /**
   402      * Build the summaries for the fields that belong to the given class.
   403      *
   404      * @param node the XML element that specifies which components to document
   405      * @param classContentTree content tree to which the documentation will be added
   406      */
   407     public void buildSerializableFields(XMLNode node, Content classContentTree) {
   408         MemberDoc[] members = currentClass.serializableFields();
   409         int membersLength = members.length;
   410         if (membersLength > 0) {
   411             Content serializableFieldsTree = fieldWriter.getSerializableFieldsHeader();
   412             for (int i = 0; i < membersLength; i++) {
   413                 currentMember = members[i];
   414                 if (!currentClass.definesSerializableFields()) {
   415                     Content fieldsContentTree = fieldWriter.getFieldsContentHeader(
   416                             (i == membersLength - 1));
   417                     buildChildren(node, fieldsContentTree);
   418                     serializableFieldsTree.addContent(fieldsContentTree);
   419                 }
   420                 else {
   421                     buildSerialFieldTagsInfo(serializableFieldsTree);
   422                 }
   423             }
   424             classContentTree.addContent(fieldWriter.getSerializableFields(
   425                     configuration.getText("doclet.Serialized_Form_fields"),
   426                     serializableFieldsTree));
   427         }
   428     }
   430     /**
   431      * Build the field sub header.
   432      *
   433      * @param node the XML element that specifies which components to document
   434      * @param fieldsContentTree content tree to which the documentation will be added
   435      */
   436     public void buildFieldSubHeader(XMLNode node, Content fieldsContentTree) {
   437         if (!currentClass.definesSerializableFields()) {
   438             FieldDoc field = (FieldDoc) currentMember;
   439             fieldWriter.addMemberHeader(field.type().asClassDoc(),
   440                     field.type().typeName(), field.type().dimension(), field.name(),
   441                     fieldsContentTree);
   442         }
   443     }
   445     /**
   446      * Build the field deprecation information.
   447      *
   448      * @param node the XML element that specifies which components to document
   449      * @param fieldsContentTree content tree to which the documentation will be added
   450      */
   451     public void buildFieldDeprecationInfo(XMLNode node, Content fieldsContentTree) {
   452         if (!currentClass.definesSerializableFields()) {
   453             FieldDoc field = (FieldDoc)currentMember;
   454             fieldWriter.addMemberDeprecatedInfo(field, fieldsContentTree);
   455         }
   456     }
   458     /**
   459      * Build the serial field tags information.
   460      *
   461      * @param serializableFieldsTree content tree to which the documentation will be added
   462      */
   463     public void buildSerialFieldTagsInfo(Content serializableFieldsTree) {
   464         if(configuration.nocomment){
   465             return;
   466         }
   467         FieldDoc field = (FieldDoc)currentMember;
   468         // Process Serializable Fields specified as array of
   469         // ObjectStreamFields. Print a member for each serialField tag.
   470         // (There should be one serialField tag per ObjectStreamField
   471         // element.)
   472         SerialFieldTag[] tags = field.serialFieldTags();
   473         Arrays.sort(tags);
   474         int tagsLength = tags.length;
   475         for (int i = 0; i < tagsLength; i++) {
   476             Content fieldsContentTree = fieldWriter.getFieldsContentHeader(
   477                     (i == tagsLength - 1));
   478             fieldWriter.addMemberHeader(tags[i].fieldTypeDoc(),
   479                     tags[i].fieldType(), "", tags[i].fieldName(), fieldsContentTree);
   480             fieldWriter.addMemberDescription(tags[i], fieldsContentTree);
   481             serializableFieldsTree.addContent(fieldsContentTree);
   482         }
   483     }
   485     /**
   486      * Build the field information.
   487      *
   488      * @param node the XML element that specifies which components to document
   489      * @param fieldsContentTree content tree to which the documentation will be added
   490      */
   491     public void buildFieldInfo(XMLNode node, Content fieldsContentTree) {
   492         if(configuration.nocomment){
   493             return;
   494         }
   495         FieldDoc field = (FieldDoc)currentMember;
   496         ClassDoc cd = field.containingClass();
   497         // Process default Serializable field.
   498         if ((field.tags("serial").length == 0) && ! field.isSynthetic()
   499                 && configuration.serialwarn) {
   500             configuration.message.warning(field.position(),
   501                     "doclet.MissingSerialTag", cd.qualifiedName(),
   502                     field.name());
   503         }
   504         fieldWriter.addMemberDescription(field, fieldsContentTree);
   505         fieldWriter.addMemberTags(field, fieldsContentTree);
   506     }
   508     /**
   509      * Return true if the given Doc should be included
   510      * in the serialized form.
   511      *
   512      * @param doc the Doc object to check for serializability.
   513      */
   514     public static boolean serialInclude(Doc doc) {
   515         if (doc == null) {
   516             return false;
   517         }
   518         return doc.isClass() ?
   519             serialClassInclude((ClassDoc)doc) :
   520             serialDocInclude(doc);
   521     }
   523     /**
   524      * Return true if the given ClassDoc should be included
   525      * in the serialized form.
   526      *
   527      * @param cd the ClassDoc object to check for serializability.
   528      */
   529     private static boolean serialClassInclude(ClassDoc cd) {
   530         if (cd.isEnum()) {
   531             return false;
   532         }
   533         try {
   534             cd.superclassType();
   535         } catch (NullPointerException e) {
   536             //Workaround for null pointer bug in ClassDoc.superclassType().
   537             return false;
   538         }
   539         if (cd.isSerializable()) {
   540             if (cd.tags("serial").length > 0) {
   541                 return serialDocInclude(cd);
   542             } else if (cd.isPublic() || cd.isProtected()) {
   543                 return true;
   544             } else {
   545                 return false;
   546             }
   547         }
   548         return false;
   549     }
   551     /**
   552      * Return true if the given Doc should be included
   553      * in the serialized form.
   554      *
   555      * @param doc the Doc object to check for serializability.
   556      */
   557     private static boolean serialDocInclude(Doc doc) {
   558         if (doc.isEnum()) {
   559             return false;
   560         }
   561         Tag[] serial = doc.tags("serial");
   562         if (serial.length > 0) {
   563             String serialtext = serial[0].text().toLowerCase();
   564             if (serialtext.indexOf("exclude") >= 0) {
   565                 return false;
   566             } else if (serialtext.indexOf("include") >= 0) {
   567                 return true;
   568             }
   569         }
   570         return true;
   571     }
   573     /**
   574      * Return true if any of the given classes have a @serialinclude tag.
   575      *
   576      * @param classes the classes to check.
   577      * @return true if any of the given classes have a @serialinclude tag.
   578      */
   579     private boolean serialClassFoundToDocument(ClassDoc[] classes) {
   580         for (int i = 0; i < classes.length; i++) {
   581             if (serialClassInclude(classes[i])) {
   582                 return true;
   583             }
   584         }
   585         return false;
   586     }
   587 }

mercurial