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

Fri, 18 Jun 2010 21:13:56 -0700

author
jjg
date
Fri, 18 Jun 2010 21:13:56 -0700
changeset 589
4177f5bdd189
parent 554
9d9f26857129
child 766
90af8d87741f
permissions
-rw-r--r--

6961178: Allow doclet.xml to contain XML attributes
Reviewed-by: bpatel

     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.*;
    31 import com.sun.javadoc.*;
    32 import com.sun.tools.doclets.internal.toolkit.util.*;
    33 import com.sun.tools.doclets.internal.toolkit.*;
    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     private SerializedFormBuilder(Configuration configuration) {
    91         super(configuration);
    92     }
    94     /**
    95      * Construct a new SerializedFormBuilder.
    96      * @param configuration the current configuration of the doclet.
    97      */
    98     public static SerializedFormBuilder getInstance(Configuration configuration) {
    99         SerializedFormBuilder builder = new SerializedFormBuilder(configuration);
   100         return builder;
   101     }
   103     /**
   104      * Build the serialized form.
   105      */
   106     public void build() throws IOException {
   107         if (! serialClassFoundToDocument(configuration.root.classes())) {
   108             //Nothing to document.
   109             return;
   110         }
   111         try {
   112             writer = configuration.getWriterFactory().getSerializedFormWriter();
   113             if (writer == null) {
   114                 //Doclet does not support this output.
   115                 return;
   116             }
   117         } catch (Exception e) {
   118             throw new DocletAbortException();
   119         }
   120         build(LayoutParser.getInstance(configuration).parseXML(NAME));
   121         writer.close();
   122     }
   124     /**
   125      * {@inheritDoc}
   126      */
   127     public String getName() {
   128         return NAME;
   129     }
   131     /**
   132      * Build the serialized form.
   133      */
   134     public void buildSerializedForm(XMLNode node) throws Exception {
   135         buildChildren(node);
   136         writer.close();
   137     }
   139     /**
   140      * Build the header.
   141      */
   142     public void buildHeader(XMLNode node) {
   143         writer.writeHeader(configuration.getText("doclet.Serialized_Form"));
   144     }
   146     /**
   147      * Build the contents.
   148      */
   149     public void buildSerializedFormSummaries(XMLNode node) {
   150         PackageDoc[] packages = configuration.packages;
   151         for (int i = 0; i < packages.length; i++) {
   152             currentPackage = packages[i];
   153             buildChildren(node);
   154         }
   155     }
   157     /**
   158      * Build the package serialized for for the current package being processed.
   159      */
   160     public void buildPackageSerializedForm(XMLNode node) {
   161         String foo = currentPackage.name();
   162         ClassDoc[] classes = currentPackage.allClasses(false);
   163         if (classes == null || classes.length == 0) {
   164             return;
   165         }
   166         if (!serialInclude(currentPackage)) {
   167             return;
   168         }
   169         if (!serialClassFoundToDocument(classes)) {
   170             return;
   171         }
   172         buildChildren(node);
   173     }
   175     public void buildPackageHeader(XMLNode node) {
   176         writer.writePackageHeader(Util.getPackageName(currentPackage));
   177     }
   179     public void buildClassSerializedForm(XMLNode node) {
   180         ClassDoc[] classes = currentPackage.allClasses(false);
   181         Arrays.sort(classes);
   182         for (int j = 0; j < classes.length; j++) {
   183             currentClass = classes[j];
   184             fieldWriter = writer.getSerialFieldWriter(currentClass);
   185             methodWriter = writer.getSerialMethodWriter(currentClass);
   186             if(currentClass.isClass() && currentClass.isSerializable()) {
   187                 if(!serialClassInclude(currentClass)) {
   188                     continue;
   189                 }
   190                 buildChildren(node);
   191             }
   192         }
   193     }
   195     public void buildClassHeader(XMLNode node) {
   196         writer.writeClassHeader(currentClass);
   197     }
   199     /**
   200      * Build the serial UID information for the given class.
   201      */
   202     public void buildSerialUIDInfo(XMLNode node) {
   203         FieldDoc[] fields = currentClass.fields(false);
   204         for (int i = 0; i < fields.length; i++) {
   205             if (fields[i].name().equals("serialVersionUID") &&
   206                 fields[i].constantValueExpression() != null) {
   207                 writer.writeSerialUIDInfo(SERIAL_VERSION_UID_HEADER,
   208                     fields[i].constantValueExpression());
   209                 return;
   210             }
   211         }
   212     }
   214     /**
   215      * Build the footer.
   216      */
   217     public void buildFooter(XMLNode node) {
   218         writer.writeFooter();
   219     }
   221     /**
   222      * Return true if the given Doc should be included
   223      * in the serialized form.
   224      *
   225      * @param doc the Doc object to check for serializability.
   226      */
   227     public static boolean serialInclude(Doc doc) {
   228         if (doc == null) {
   229             return false;
   230         }
   231         return doc.isClass() ?
   232             serialClassInclude((ClassDoc)doc) :
   233             serialDocInclude(doc);
   234     }
   236     /**
   237      * Return true if the given ClassDoc should be included
   238      * in the serialized form.
   239      *
   240      * @param cd the ClassDoc object to check for serializability.
   241      */
   242     private static boolean serialClassInclude(ClassDoc cd) {
   243         if (cd.isEnum()) {
   244             return false;
   245         }
   246         try {
   247             cd.superclassType();
   248         } catch (NullPointerException e) {
   249             //Workaround for null pointer bug in ClassDoc.superclassType().
   250             return false;
   251         }
   252         if (cd.isSerializable()) {
   253             if (cd.tags("serial").length > 0) {
   254                 return serialDocInclude(cd);
   255             } else if (cd.isPublic() || cd.isProtected()) {
   256                 return true;
   257             } else {
   258                 return false;
   259             }
   260         }
   261         return false;
   262     }
   264     /**
   265      * Return true if the given Doc should be included
   266      * in the serialized form.
   267      *
   268      * @param doc the Doc object to check for serializability.
   269      */
   270     private static boolean serialDocInclude(Doc doc) {
   271         if (doc.isEnum()) {
   272             return false;
   273         }
   274         Tag[] serial = doc.tags("serial");
   275         if (serial.length > 0) {
   276             String serialtext = serial[0].text().toLowerCase();
   277             if (serialtext.indexOf("exclude") >= 0) {
   278                 return false;
   279             } else if (serialtext.indexOf("include") >= 0) {
   280                 return true;
   281             }
   282         }
   283         return true;
   284     }
   286     /**
   287      * Return true if any of the given classes have a @serialinclude tag.
   288      *
   289      * @param classes the classes to check.
   290      * @return true if any of the given classes have a @serialinclude tag.
   291      */
   292     private boolean serialClassFoundToDocument(ClassDoc[] classes) {
   293         for (int i = 0; i < classes.length; i++) {
   294             if (serialClassInclude(classes[i])) {
   295                 return true;
   296             }
   297         }
   298         return false;
   299     }
   301     /**
   302      * Build the method header.
   303      */
   304     public void buildMethodHeader(XMLNode node) {
   305         if (currentClass.serializationMethods().length > 0) {
   306             methodWriter.writeHeader(
   307                 configuration.getText("doclet.Serialized_Form_methods"));
   308             if (currentClass.isSerializable() && !currentClass.isExternalizable()) {
   309                 if (currentClass.serializationMethods().length == 0) {
   310                     methodWriter.writeNoCustomizationMsg(
   311                         configuration.getText(
   312                             "doclet.Serializable_no_customization"));
   313                 }
   314             }
   315         }
   316     }
   318     /**
   319      * Build the method sub header.
   320      */
   321     public void buildMethodSubHeader(XMLNode node)  {
   322         methodWriter.writeMemberHeader((MethodDoc) currentMember);
   323     }
   325     /**
   326      * Build the deprecated method description.
   327      */
   328     public void buildDeprecatedMethodInfo(XMLNode node) {
   329         methodWriter.writeDeprecatedMemberInfo((MethodDoc) currentMember);
   330     }
   332     /**
   333      * Build method tags.
   334      */
   335     public void buildMethodDescription(XMLNode node) {
   336         methodWriter.writeMemberDescription((MethodDoc) currentMember);
   337     }
   339     /**
   340      * Build the method tags.
   341      */
   342     public void buildMethodTags(XMLNode node) {
   343         methodWriter.writeMemberTags((MethodDoc) currentMember);
   344         MethodDoc method = (MethodDoc)currentMember;
   345         if (method.name().compareTo("writeExternal") == 0
   346             && method.tags("serialData").length == 0) {
   347             if (configuration.serialwarn) {
   348                 configuration.getDocletSpecificMsg().warning(
   349                     currentMember.position(), "doclet.MissingSerialDataTag",
   350                     method.containingClass().qualifiedName(), method.name());
   351             }
   352         }
   353     }
   355     /**
   356      * build the information for the method.
   357      */
   358     public void buildMethodInfo(XMLNode node)  {
   359         if(configuration.nocomment){
   360             return;
   361         }
   362         buildChildren(node);
   363     }
   365     /**
   366      * Build the method footer.
   367      */
   368     public void buildMethodFooter(XMLNode node) {
   369         methodWriter.writeMemberFooter();
   370     }
   372     /**
   373      * Build the field header.
   374      */
   375     public void buildFieldHeader(XMLNode node) {
   376         if (currentClass.serializableFields().length > 0) {
   377             buildFieldSerializationOverview(currentClass);
   378             fieldWriter.writeHeader(configuration.getText(
   379                 "doclet.Serialized_Form_fields"));
   380         }
   381     }
   383     /**
   384      * If possible, build the serialization overview for the given
   385      * class.
   386      *
   387      * @param classDoc the class to print the overview for.
   388      */
   389     public void buildFieldSerializationOverview(ClassDoc classDoc) {
   390         if (classDoc.definesSerializableFields()) {
   391             FieldDoc serialPersistentField =
   392                 Util.asList(classDoc.serializableFields()).get(0);
   393             // Check to see if there are inline comments, tags or deprecation
   394             // information to be printed.
   395             if (fieldWriter.shouldPrintOverview(serialPersistentField)) {
   396                 fieldWriter.writeHeader(
   397                         configuration.getText("doclet.Serialized_Form_class"));
   398                 fieldWriter.writeMemberDeprecatedInfo(serialPersistentField);
   399                 if (!configuration.nocomment) {
   400                     fieldWriter.writeMemberDescription(serialPersistentField);
   401                     fieldWriter.writeMemberTags(serialPersistentField);
   402                 }
   403                 // Footer required to close the definition list tag
   404                 // for serialization overview.
   405                 fieldWriter.writeFooter(
   406                         configuration.getText("doclet.Serialized_Form_class"));
   407             }
   408         }
   409     }
   411     /**
   412      * Build the field sub header.
   413      */
   414     public void buildFieldSubHeader(XMLNode node) {
   415         if (! currentClass.definesSerializableFields() ){
   416             FieldDoc field = (FieldDoc) currentMember;
   417             fieldWriter.writeMemberHeader(field.type().asClassDoc(),
   418                 field.type().typeName(), field.type().dimension(), field.name());
   419         }
   420     }
   422     /**
   423      * Build the field deprecation information.
   424      */
   425     public void buildFieldDeprecationInfo(XMLNode node) {
   426         if (!currentClass.definesSerializableFields()) {
   427             FieldDoc field = (FieldDoc)currentMember;
   428             fieldWriter.writeMemberDeprecatedInfo(field);
   429         }
   430     }
   432     /**
   433      * Build the field information.
   434      */
   435     public void buildFieldInfo(XMLNode node) {
   436         if(configuration.nocomment){
   437             return;
   438         }
   439         FieldDoc field = (FieldDoc)currentMember;
   440         ClassDoc cd = field.containingClass();
   441         if (cd.definesSerializableFields()) {
   442             // Process Serializable Fields specified as array of
   443             // ObjectStreamFields. Print a member for each serialField tag.
   444             // (There should be one serialField tag per ObjectStreamField
   445             // element.)
   446             SerialFieldTag[] tags = field.serialFieldTags();
   447             Arrays.sort(tags);
   448             for (int i = 0; i < tags.length; i++) {
   449                 fieldWriter.writeMemberHeader(tags[i].fieldTypeDoc(),
   450                         tags[i].fieldType(), "", tags[i].fieldName());
   451                 fieldWriter.writeMemberDescription(tags[i]);
   453             }
   454         } else {
   456             // Process default Serializable field.
   457             if ((field.tags("serial").length == 0) && ! field.isSynthetic()
   458                 && configuration.serialwarn) {
   459                 configuration.message.warning(field.position(),
   460                         "doclet.MissingSerialTag", cd.qualifiedName(),
   461                         field.name());
   462             }
   463             fieldWriter.writeMemberDescription(field);
   464             fieldWriter.writeMemberTags(field);
   465         }
   466     }
   468     /**
   469      * Build the field sub footer.
   470      */
   471     public void buildFieldSubFooter(XMLNode node) {
   472         if (! currentClass.definesSerializableFields()) {
   473             fieldWriter.writeMemberFooter();
   474         }
   475     }
   477     /**
   478      * Build the summaries for the methods that belong to the given
   479      * class.
   480      */
   481     public void buildSerializableMethods(XMLNode node) {
   482         MemberDoc[] members = currentClass.serializationMethods();
   483         if (members.length > 0) {
   484             for (int i = 0; i < members.length; i++) {
   485                 currentMember = members[i];
   486                 buildChildren(node);
   487             }
   488         }
   489     }
   491     /**
   492      * Build the summaries for the fields that belong to the given
   493      * class.
   494      */
   495     public void buildSerializableFields(XMLNode node) {
   496         MemberDoc[] members = currentClass.serializableFields();
   497         if (members.length > 0) {
   498             for (int i = 0; i < members.length; i++) {
   499                 currentMember = members[i];
   500                 buildChildren(node);
   501             }
   502         }
   503     }
   504 }

mercurial