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

changeset 1
9a66ca7c79fa
child 184
905e151a185a
equal deleted inserted replaced
-1:000000000000 1:9a66ca7c79fa
1 /*
2 * Copyright 2003 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26 package com.sun.tools.doclets.internal.toolkit.builders;
27
28 import com.sun.tools.doclets.internal.toolkit.util.*;
29 import com.sun.tools.doclets.internal.toolkit.*;
30 import com.sun.javadoc.*;
31 import java.io.*;
32 import java.lang.reflect.*;
33 import java.util.*;
34
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 * @since 1.5
44 */
45 public class SerializedFormBuilder extends AbstractBuilder {
46
47 /**
48 * The root element of the serialized form XML is {@value}.
49 */
50 public static final String NAME = "SerializedForm";
51
52 /**
53 * The writer for this builder.
54 */
55 private SerializedFormWriter writer;
56
57 /**
58 * The writer for serializable fields.
59 */
60 private SerializedFormWriter.SerialFieldWriter fieldWriter;
61
62 /**
63 * The writer for serializable method documentation.
64 */
65 private SerializedFormWriter.SerialMethodWriter methodWriter;
66
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:";
73
74 /**
75 * The current package being documented.
76 */
77 private PackageDoc currentPackage;
78
79 /**
80 * The current class being documented.
81 */
82 private ClassDoc currentClass;
83
84 /**
85 * The current member being documented.
86 */
87 protected MemberDoc currentMember;
88
89 private SerializedFormBuilder(Configuration configuration) {
90 super(configuration);
91 }
92
93 /**
94 * Construct a new SerializedFormBuilder.
95 * @param configuration the current configuration of the doclet.
96 */
97 public static SerializedFormBuilder getInstance(Configuration configuration) {
98 SerializedFormBuilder builder = new SerializedFormBuilder(configuration);
99 return builder;
100 }
101
102 /**
103 * Build the serialized form.
104 */
105 public void build() throws IOException {
106 if (! serialClassFoundToDocument(configuration.root.classes())) {
107 //Nothing to document.
108 return;
109 }
110 try {
111 writer = configuration.getWriterFactory().getSerializedFormWriter();
112 if (writer == null) {
113 //Doclet does not support this output.
114 return;
115 }
116 } catch (Exception e) {
117 throw new DocletAbortException();
118 }
119 build(LayoutParser.getInstance(configuration).parseXML(NAME));
120 writer.close();
121 }
122
123 /**
124 * {@inheritDoc}
125 */
126 public String getName() {
127 return NAME;
128 }
129
130 /**
131 * Build the serialized form.
132 */
133 public void buildSerializedForm(List elements) throws Exception {
134 build(elements);
135 writer.close();
136 }
137
138 /**
139 * {@inheritDoc}
140 */
141 public void invokeMethod(String methodName, Class[] paramClasses,
142 Object[] params)
143 throws Exception {
144 if (DEBUG) {
145 configuration.root.printError("DEBUG: " + this.getClass().getName()
146 + "." + methodName);
147 }
148 Method method = this.getClass().getMethod(methodName, paramClasses);
149 method.invoke(this, params);
150 }
151
152 /**
153 * Build the header.
154 */
155 public void buildHeader() {
156 writer.writeHeader(configuration.getText("doclet.Serialized_Form"));
157 }
158
159 /**
160 * Build the contents.
161 */
162 public void buildSerializedFormSummaries(List elements) {
163 PackageDoc[] packages = configuration.packages;
164 for (int i = 0; i < packages.length; i++) {
165 currentPackage = packages[i];
166 build(elements);
167 }
168 }
169
170 /**
171 * Build the package serialized for for the current package being processed.
172 */
173 public void buildPackageSerializedForm(List elements) {
174 String foo = currentPackage.name();
175 ClassDoc[] classes = currentPackage.allClasses(false);
176 if (classes == null || classes.length == 0) {
177 return;
178 }
179 if (!serialInclude(currentPackage)) {
180 return;
181 }
182 if (!serialClassFoundToDocument(classes)) {
183 return;
184 }
185 build(elements);
186 }
187
188 public void buildPackageHeader() {
189 writer.writePackageHeader(Util.getPackageName(currentPackage));
190 }
191
192 public void buildClassSerializedForm(List elements) {
193 ClassDoc[] classes = currentPackage.allClasses(false);
194 Arrays.sort(classes);
195 for (int j = 0; j < classes.length; j++) {
196 currentClass = classes[j];
197 fieldWriter = writer.getSerialFieldWriter(currentClass);
198 methodWriter = writer.getSerialMethodWriter(currentClass);
199 if(currentClass.isClass() && currentClass.isSerializable()) {
200 if(!serialClassInclude(currentClass)) {
201 continue;
202 }
203 build(elements);
204 }
205 }
206 }
207
208 public void buildClassHeader() {
209 writer.writeClassHeader(currentClass);
210 }
211
212 /**
213 * Build the serial UID information for the given class.
214 */
215 public void buildSerialUIDInfo() {
216 FieldDoc[] fields = currentClass.fields(false);
217 for (int i = 0; i < fields.length; i++) {
218 if (fields[i].name().equals("serialVersionUID") &&
219 fields[i].constantValueExpression() != null) {
220 writer.writeSerialUIDInfo(SERIAL_VERSION_UID_HEADER,
221 fields[i].constantValueExpression());
222 return;
223 }
224 }
225 }
226
227 /**
228 * Build the footer.
229 */
230 public void buildFooter() {
231 writer.writeFooter();
232 }
233
234 /**
235 * Return true if the given Doc should be included
236 * in the serialized form.
237 *
238 * @param doc the Doc object to check for serializability.
239 */
240 public static boolean serialInclude(Doc doc) {
241 if (doc == null) {
242 return false;
243 }
244 return doc.isClass() ?
245 serialClassInclude((ClassDoc)doc) :
246 serialDocInclude(doc);
247 }
248
249 /**
250 * Return true if the given ClassDoc should be included
251 * in the serialized form.
252 *
253 * @param cd the ClassDoc object to check for serializability.
254 */
255 private static boolean serialClassInclude(ClassDoc cd) {
256 if (cd.isEnum()) {
257 return false;
258 }
259 try {
260 cd.superclassType();
261 } catch (NullPointerException e) {
262 //Workaround for null pointer bug in ClassDoc.superclassType().
263 return false;
264 }
265 if (cd.isSerializable()) {
266 if (cd.tags("serial").length > 0) {
267 return serialDocInclude(cd);
268 } else if (cd.isPublic() || cd.isProtected()) {
269 return true;
270 } else {
271 return false;
272 }
273 }
274 return false;
275 }
276
277 /**
278 * Return true if the given Doc should be included
279 * in the serialized form.
280 *
281 * @param doc the Doc object to check for serializability.
282 */
283 private static boolean serialDocInclude(Doc doc) {
284 if (doc.isEnum()) {
285 return false;
286 }
287 Tag[] serial = doc.tags("serial");
288 if (serial.length > 0) {
289 String serialtext = serial[0].text().toLowerCase();
290 if (serialtext.indexOf("exclude") >= 0) {
291 return false;
292 } else if (serialtext.indexOf("include") >= 0) {
293 return true;
294 }
295 }
296 return true;
297 }
298
299 /**
300 * Return true if any of the given classes have a @serialinclude tag.
301 *
302 * @param classes the classes to check.
303 * @return true if any of the given classes have a @serialinclude tag.
304 */
305 private boolean serialClassFoundToDocument(ClassDoc[] classes) {
306 for (int i = 0; i < classes.length; i++) {
307 if (serialClassInclude(classes[i])) {
308 return true;
309 }
310 }
311 return false;
312 }
313
314 /**
315 * Build the method header.
316 */
317 public void buildMethodHeader() {
318 if (currentClass.serializationMethods().length > 0) {
319 methodWriter.writeHeader(
320 configuration.getText("doclet.Serialized_Form_methods"));
321 if (currentClass.isSerializable() && !currentClass.isExternalizable()) {
322 if (currentClass.serializationMethods().length == 0) {
323 methodWriter.writeNoCustomizationMsg(
324 configuration.getText(
325 "doclet.Serializable_no_customization"));
326 }
327 }
328 }
329 }
330
331 /**
332 * Build the method sub header.
333 */
334 public void buildMethodSubHeader() {
335 methodWriter.writeMemberHeader((MethodDoc) currentMember);
336 }
337
338 /**
339 * Build the deprecated method description.
340 */
341 public void buildDeprecatedMethodInfo() {
342 methodWriter.writeDeprecatedMemberInfo((MethodDoc) currentMember);
343 }
344
345 /**
346 * Build method tags.
347 */
348 public void buildMethodDescription() {
349 methodWriter.writeMemberDescription((MethodDoc) currentMember);
350 }
351
352 /**
353 * Build the method tags.
354 */
355 public void buildMethodTags() {
356 methodWriter.writeMemberTags((MethodDoc) currentMember);
357 MethodDoc method = (MethodDoc)currentMember;
358 if (method.name().compareTo("writeExternal") == 0
359 && method.tags("serialData").length == 0) {
360 if (configuration.serialwarn) {
361 configuration.getDocletSpecificMsg().warning(
362 currentMember.position(), "doclet.MissingSerialDataTag",
363 method.containingClass().qualifiedName(), method.name());
364 }
365 }
366 }
367
368 /**
369 * build the information for the method.
370 */
371 public void buildMethodInfo(List elements) {
372 if(configuration.nocomment){
373 return;
374 }
375 build(elements);
376 }
377
378 /**
379 * Build the method footer.
380 */
381 public void buildMethodFooter() {
382 methodWriter.writeMemberFooter((MethodDoc) currentMember);
383 }
384
385 /**
386 * Build the field header.
387 */
388 public void buildFieldHeader() {
389 if (currentClass.serializableFields().length > 0) {
390 buildFieldSerializationOverview(currentClass);
391 fieldWriter.writeHeader(configuration.getText(
392 "doclet.Serialized_Form_fields"));
393 }
394 }
395
396 /**
397 * If possible, build the serialization overview for the given
398 * class.
399 *
400 * @param classDoc the class to print the overview for.
401 */
402 public void buildFieldSerializationOverview(ClassDoc classDoc) {
403 if (classDoc.definesSerializableFields()) {
404 FieldDoc serialPersistentField =
405 (FieldDoc)((Util.asList(classDoc.serializableFields()).get(0)));
406 String comment = serialPersistentField.commentText();
407 if (comment.length() > 0) {
408 fieldWriter.writeHeader(
409 configuration.getText("doclet.Serialized_Form_class"));
410 if (!configuration.nocomment) {
411 fieldWriter.writeMemberDeprecatedInfo(serialPersistentField);
412 fieldWriter.writeMemberDescription(serialPersistentField);
413 fieldWriter.writeMemberTags(serialPersistentField);
414 fieldWriter.writeMemberFooter(serialPersistentField);
415 }
416 }
417 }
418 }
419
420 /**
421 * Build the field sub header.
422 */
423 public void buildFieldSubHeader() {
424 if (! currentClass.definesSerializableFields() ){
425 FieldDoc field = (FieldDoc) currentMember;
426 fieldWriter.writeMemberHeader(field.type().asClassDoc(),
427 field.type().typeName(), field.type().dimension(), field.name());
428 }
429 }
430
431 /**
432 * Build the field information.
433 */
434 public void buildFieldInfo() {
435 if(configuration.nocomment){
436 return;
437 }
438 FieldDoc field = (FieldDoc)currentMember;
439 ClassDoc cd = field.containingClass();
440 if (cd.definesSerializableFields()) {
441 // Process Serializable Fields specified as array of
442 // ObjectStreamFields. Print a member for each serialField tag.
443 // (There should be one serialField tag per ObjectStreamField
444 // element.)
445 SerialFieldTag[] tags = field.serialFieldTags();
446 Arrays.sort(tags);
447 for (int i = 0; i < tags.length; i++) {
448 fieldWriter.writeMemberHeader(tags[i].fieldTypeDoc(),
449 tags[i].fieldType(), "", tags[i].fieldName());
450 fieldWriter.writeMemberDescription(tags[i]);
451
452 }
453 } else {
454
455 // Process default Serializable field.
456 if ((field.tags("serial").length == 0) && ! field.isSynthetic()
457 && configuration.serialwarn) {
458 configuration.message.warning(field.position(),
459 "doclet.MissingSerialTag", cd.qualifiedName(),
460 field.name());
461 }
462 fieldWriter.writeMemberDeprecatedInfo(field);
463 fieldWriter.writeMemberDescription(field);
464 fieldWriter.writeMemberTags(field);
465 }
466 }
467
468 /**
469 * Build the field footer.
470 */
471 public void buildFieldFooter() {
472 if (! currentClass.definesSerializableFields()) {
473 fieldWriter.writeMemberFooter((FieldDoc) currentMember);
474 }
475 }
476
477 /**
478 * Build the summaries for the methods that belong to the given
479 * class.
480 */
481 public void buildSerializableMethods(List elements) {
482 MemberDoc[] members = currentClass.serializationMethods();
483 if (members.length > 0) {
484 for (int i = 0; i < members.length; i++) {
485 currentMember = members[i];
486 build(elements);
487 }
488 }
489 }
490
491 /**
492 * Build the summaries for the fields that belong to the given
493 * class.
494 */
495 public void buildSerializableFields(List elements) {
496 MemberDoc[] members = currentClass.serializableFields();
497 if (members.length > 0) {
498 for (int i = 0; i < members.length; i++) {
499 currentMember = members[i];
500 build(elements);
501 }
502 }
503 }
504 }

mercurial