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

Tue, 09 Oct 2012 19:10:00 -0700

author
jjg
date
Tue, 09 Oct 2012 19:10:00 -0700
changeset 1357
c75be5bc5283
parent 910
ebf7c13df6c0
child 1359
25e14ad23cef
permissions
-rw-r--r--

8000663: clean up langtools imports
Reviewed-by: darcy

     1 /*
     2  * Copyright (c) 2003, 2012, 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 serialized form.
    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  * @author Bhavesh Patel (Modified)
    44  * @since 1.5
    45  */
    46 public class SerializedFormBuilder extends AbstractBuilder {
    48     /**
    49      * The root element of the serialized form XML is {@value}.
    50      */
    51     public static final String NAME = "SerializedForm";
    53     /**
    54      * The writer for this builder.
    55      */
    56     private SerializedFormWriter writer;
    58     /**
    59      * The writer for serializable fields.
    60      */
    61     private SerializedFormWriter.SerialFieldWriter fieldWriter;
    63     /**
    64      * The writer for serializable method documentation.
    65      */
    66     private SerializedFormWriter.SerialMethodWriter methodWriter;
    68     /**
    69      * The header for the serial version UID.  Save the string
    70      * here instead of the properties file because we do not want
    71      * this string to be localized.
    72      */
    73     private static final String SERIAL_VERSION_UID_HEADER = "serialVersionUID:";
    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 current member being documented.
    87      */
    88     protected MemberDoc currentMember;
    90     /**
    91      * The content that will be added to the serialized form documentation tree.
    92      */
    93     private Content contentTree;
    95     private SerializedFormBuilder(Configuration configuration) {
    96         super(configuration);
    97     }
    99     /**
   100      * Construct a new SerializedFormBuilder.
   101      * @param configuration the current configuration of the doclet.
   102      */
   103     public static SerializedFormBuilder getInstance(Configuration configuration) {
   104         SerializedFormBuilder builder = new SerializedFormBuilder(configuration);
   105         return builder;
   106     }
   108     /**
   109      * Build the serialized form.
   110      */
   111     public void build() throws IOException {
   112         if (! serialClassFoundToDocument(configuration.root.classes())) {
   113             //Nothing to document.
   114             return;
   115         }
   116         try {
   117             writer = configuration.getWriterFactory().getSerializedFormWriter();
   118             if (writer == null) {
   119                 //Doclet does not support this output.
   120                 return;
   121             }
   122         } catch (Exception e) {
   123             throw new DocletAbortException();
   124         }
   125         build(LayoutParser.getInstance(configuration).parseXML(NAME), contentTree);
   126         writer.close();
   127     }
   129     /**
   130      * {@inheritDoc}
   131      */
   132     public String getName() {
   133         return NAME;
   134     }
   136     /**
   137      * Build the serialized form.
   138      *
   139      * @param node the XML element that specifies which components to document
   140      * @param serializedTree content tree to which the documentation will be added
   141      */
   142     public void buildSerializedForm(XMLNode node, Content serializedTree) throws Exception {
   143         serializedTree = writer.getHeader(configuration.getText(
   144                 "doclet.Serialized_Form"));
   145         buildChildren(node, serializedTree);
   146         writer.addFooter(serializedTree);
   147         writer.printDocument(serializedTree);
   148         writer.close();
   149     }
   151     /**
   152      * Build the serialized form summaries.
   153      *
   154      * @param node the XML element that specifies which components to document
   155      * @param serializedTree content tree to which the documentation will be added
   156      */
   157     public void buildSerializedFormSummaries(XMLNode node, Content serializedTree) {
   158         Content serializedSummariesTree = writer.getSerializedSummariesHeader();
   159         PackageDoc[] packages = configuration.packages;
   160         for (int i = 0; i < packages.length; i++) {
   161             currentPackage = packages[i];
   162             buildChildren(node, serializedSummariesTree);
   163         }
   164         serializedTree.addContent(writer.getSerializedContent(
   165                 serializedSummariesTree));
   166     }
   168     /**
   169      * Build the package serialized form for the current package being processed.
   170      *
   171      * @param node the XML element that specifies which components to document
   172      * @param serializedSummariesTree content tree to which the documentation will be added
   173      */
   174     public void buildPackageSerializedForm(XMLNode node, Content serializedSummariesTree) {
   175         Content packageSerializedTree = writer.getPackageSerializedHeader();
   176         String foo = currentPackage.name();
   177         ClassDoc[] classes = currentPackage.allClasses(false);
   178         if (classes == null || classes.length == 0) {
   179             return;
   180         }
   181         if (!serialInclude(currentPackage)) {
   182             return;
   183         }
   184         if (!serialClassFoundToDocument(classes)) {
   185             return;
   186         }
   187         buildChildren(node, packageSerializedTree);
   188         serializedSummariesTree.addContent(packageSerializedTree);
   189     }
   191     /**
   192      * Build the package header.
   193      *
   194      * @param node the XML element that specifies which components to document
   195      * @param packageSerializedTree content tree to which the documentation will be added
   196      */
   197     public void buildPackageHeader(XMLNode node, Content packageSerializedTree) {
   198         packageSerializedTree.addContent(writer.getPackageHeader(
   199                 Util.getPackageName(currentPackage)));
   200     }
   202     /**
   203      * Build the class serialized form.
   204      *
   205      * @param node the XML element that specifies which components to document
   206      * @param packageSerializedTree content tree to which the documentation will be added
   207      */
   208     public void buildClassSerializedForm(XMLNode node, Content packageSerializedTree) {
   209         Content classSerializedTree = writer.getClassSerializedHeader();
   210         ClassDoc[] classes = currentPackage.allClasses(false);
   211         Arrays.sort(classes);
   212         for (int j = 0; j < classes.length; j++) {
   213             currentClass = classes[j];
   214             fieldWriter = writer.getSerialFieldWriter(currentClass);
   215             methodWriter = writer.getSerialMethodWriter(currentClass);
   216             if(currentClass.isClass() && currentClass.isSerializable()) {
   217                 if(!serialClassInclude(currentClass)) {
   218                     continue;
   219                 }
   220                 Content classTree = writer.getClassHeader(currentClass);
   221                 buildChildren(node, classTree);
   222                 classSerializedTree.addContent(classTree);
   223             }
   224         }
   225         packageSerializedTree.addContent(classSerializedTree);
   226     }
   228     /**
   229      * Build the serial UID information for the given class.
   230      *
   231      * @param node the XML element that specifies which components to document
   232      * @param classTree content tree to which the serial UID information will be added
   233      */
   234     public void buildSerialUIDInfo(XMLNode node, Content classTree) {
   235         Content serialUidTree = writer.getSerialUIDInfoHeader();
   236         FieldDoc[] fields = currentClass.fields(false);
   237         for (int i = 0; i < fields.length; i++) {
   238             if (fields[i].name().equals("serialVersionUID") &&
   239                 fields[i].constantValueExpression() != null) {
   240                 writer.addSerialUIDInfo(SERIAL_VERSION_UID_HEADER,
   241                         fields[i].constantValueExpression(), serialUidTree);
   242                 break;
   243             }
   244         }
   245         classTree.addContent(serialUidTree);
   246     }
   248     /**
   249      * Build the summaries for the methods and fields.
   250      *
   251      * @param node the XML element that specifies which components to document
   252      * @param classTree content tree to which the documentation will be added
   253      */
   254     public void buildClassContent(XMLNode node, Content classTree) {
   255         Content classContentTree = writer.getClassContentHeader();
   256         buildChildren(node, classContentTree);
   257         classTree.addContent(classContentTree);
   258     }
   260     /**
   261      * Build the summaries for the methods that belong to the given
   262      * class.
   263      *
   264      * @param node the XML element that specifies which components to document
   265      * @param classContentTree content tree to which the documentation will be added
   266      */
   267     public void buildSerializableMethods(XMLNode node, Content classContentTree) {
   268         Content serializableMethodTree = methodWriter.getSerializableMethodsHeader();
   269         MemberDoc[] members = currentClass.serializationMethods();
   270         int membersLength = members.length;
   271         if (membersLength > 0) {
   272             for (int i = 0; i < membersLength; i++) {
   273                 currentMember = members[i];
   274                 Content methodsContentTree = methodWriter.getMethodsContentHeader(
   275                         (i == membersLength - 1));
   276                 buildChildren(node, methodsContentTree);
   277                 serializableMethodTree.addContent(methodsContentTree);
   278             }
   279         }
   280         if (currentClass.serializationMethods().length > 0) {
   281             classContentTree.addContent(methodWriter.getSerializableMethods(
   282                     configuration.getText("doclet.Serialized_Form_methods"),
   283                     serializableMethodTree));
   284             if (currentClass.isSerializable() && !currentClass.isExternalizable()) {
   285                 if (currentClass.serializationMethods().length == 0) {
   286                     Content noCustomizationMsg = methodWriter.getNoCustomizationMsg(
   287                             configuration.getText(
   288                             "doclet.Serializable_no_customization"));
   289                     classContentTree.addContent(methodWriter.getSerializableMethods(
   290                     configuration.getText("doclet.Serialized_Form_methods"),
   291                     noCustomizationMsg));
   292                 }
   293             }
   294         }
   295     }
   297     /**
   298      * Build the method sub header.
   299      *
   300      * @param node the XML element that specifies which components to document
   301      * @param methodsContentTree content tree to which the documentation will be added
   302      */
   303     public void buildMethodSubHeader(XMLNode node, Content methodsContentTree)  {
   304         methodWriter.addMemberHeader((MethodDoc)currentMember, methodsContentTree);
   305     }
   307     /**
   308      * Build the deprecated method description.
   309      *
   310      * @param node the XML element that specifies which components to document
   311      * @param methodsContentTree content tree to which the documentation will be added
   312      */
   313     public void buildDeprecatedMethodInfo(XMLNode node, Content methodsContentTree) {
   314         methodWriter.addDeprecatedMemberInfo((MethodDoc) currentMember, methodsContentTree);
   315     }
   317     /**
   318      * Build the information for the method.
   319      *
   320      * @param node the XML element that specifies which components to document
   321      * @param methodsContentTree content tree to which the documentation will be added
   322      */
   323     public void buildMethodInfo(XMLNode node, Content methodsContentTree)  {
   324         if(configuration.nocomment){
   325             return;
   326         }
   327         buildChildren(node, methodsContentTree);
   328     }
   330     /**
   331      * Build method description.
   332      *
   333      * @param node the XML element that specifies which components to document
   334      * @param methodsContentTree content tree to which the documentation will be added
   335      */
   336     public void buildMethodDescription(XMLNode node, Content methodsContentTree) {
   337         methodWriter.addMemberDescription((MethodDoc) currentMember, methodsContentTree);
   338     }
   340     /**
   341      * Build the method tags.
   342      *
   343      * @param node the XML element that specifies which components to document
   344      * @param methodsContentTree content tree to which the documentation will be added
   345      */
   346     public void buildMethodTags(XMLNode node, Content methodsContentTree) {
   347         methodWriter.addMemberTags((MethodDoc) currentMember, methodsContentTree);
   348         MethodDoc method = (MethodDoc)currentMember;
   349         if (method.name().compareTo("writeExternal") == 0
   350                 && method.tags("serialData").length == 0) {
   351             if (configuration.serialwarn) {
   352                 configuration.getDocletSpecificMsg().warning(
   353                         currentMember.position(), "doclet.MissingSerialDataTag",
   354                         method.containingClass().qualifiedName(), method.name());
   355             }
   356         }
   357     }
   359     /**
   360      * Build the field header.
   361      *
   362      * @param node the XML element that specifies which components to document
   363      * @param classContentTree content tree to which the documentation will be added
   364      */
   365     public void buildFieldHeader(XMLNode node, Content classContentTree) {
   366         if (currentClass.serializableFields().length > 0) {
   367             buildFieldSerializationOverview(currentClass, classContentTree);
   368         }
   369     }
   371     /**
   372      * Build the serialization overview for the given class.
   373      *
   374      * @param classDoc the class to print the overview for.
   375      * @param classContentTree content tree to which the documentation will be added
   376      */
   377     public void buildFieldSerializationOverview(ClassDoc classDoc, Content classContentTree) {
   378         if (classDoc.definesSerializableFields()) {
   379             FieldDoc serialPersistentField = classDoc.serializableFields()[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