KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > aspectj > tools > doclets > standard > AbstractStandard


1 /* -*- Mode: JDE; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2  *
3  * This file is part of the debugger and core tools for the AspectJ(tm)
4  * programming language; see http://aspectj.org
5  *
6  * The contents of this file are subject to the Mozilla Public License
7  * Version 1.1 (the "License"); you may not use this file except in
8  * compliance with the License. You may obtain a copy of the License at
9  * either http://www.mozilla.org/MPL/ or http://aspectj.org/MPL/.
10  *
11  * Software distributed under the License is distributed on an "AS IS" basis,
12  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13  * for the specific language governing rights and limitations under the
14  * License.
15  *
16  * The Original Code is AspectJ.
17  *
18  * The Initial Developer of the Original Code is Xerox Corporation. Portions
19  * created by Xerox Corporation are Copyright (C) 1999-2002 Xerox Corporation.
20  * All Rights Reserved.
21  */

22 package org.aspectj.tools.doclets.standard;
23
24 import org.aspectj.ajdoc.AspectDoc;
25
26 import com.sun.javadoc.ClassDoc;
27 import com.sun.javadoc.DocErrorReporter;
28 import com.sun.javadoc.PackageDoc;
29 import com.sun.javadoc.RootDoc;
30 import com.sun.tools.doclets.ClassTree;
31 import com.sun.tools.doclets.DocletAbortException;
32 import com.sun.tools.doclets.HtmlDocWriter;
33 import com.sun.tools.doclets.IndexBuilder;
34
35 import java.io.IOException JavaDoc;
36 import java.lang.reflect.Constructor JavaDoc;
37 import java.util.Arrays JavaDoc;
38
39 /**
40  * An abstract allowing one to customize the writers
41  * used in ajdoc. Subclasses should define the three
42  * generate methods to specify the documentation made.
43  *
44  * @see #preGenerationClasses()
45  * @see #postGenerationClasses()
46  * @see #checkClasses()
47  * @author Jeff Palm
48  */

49 public abstract class AbstractStandard
50     extends com.sun.tools.doclets.standard.Standard {
51
52     // todo wes removed restriction, but implemented Standard as singleton via proxy
53
private static int refCount = 0;
54     {
55         if (refCount > 0) {
56             System.err.println("Warning: " + refCount + " AbstractStandard already ");
57         }
58         refCount++;
59     }
60
61     /**
62      * The ClassTree that is available to subclasses and it gaurateed
63      * to be created before pre-generating classes.
64      */

65     protected ClassTree classtree;
66     
67     protected static boolean start(AbstractStandard as,
68                                    RootDoc root) throws IOException JavaDoc {
69         try {
70             as.getConfiguration().setOptions(root);
71             as.startGeneration(root);
72         } catch (DocletAbortException exc) {
73             return false;
74         }
75         return true;
76     }
77
78     /**
79      * Returns the types of {@link Pass}es that will
80      * run before generating classes.
81      *
82      * @return an array of Class, where each entry
83      * is a subclass of {@link Pass}, ordered
84      * to run directly before generating the
85      * classes.
86      */

87     protected abstract Class JavaDoc[] preGenerationClasses();
88
89     /**
90      * Returns the types of {@link Pass}es that will
91      * run after generating classes.
92      *
93      * @return an array of Class, where each entry
94      * is a subclass of {@link Pass}, ordered
95      * to run directly after generating the
96      * classes.
97      */

98     protected abstract Class JavaDoc[] postGenerationClasses();
99
100     /**
101      * Returns the types of {@link CheckPass}es that will
102      * run to check the classes.
103      *
104      * @return an array of Class, where each entry
105      * is a subclass of {@link CheckPass}, ordered
106      * to run in order to check the classes passed
107      * into the class generation phase.
108      */

109     protected abstract Class JavaDoc[] checkClasses();
110
111     /**
112      * Return the configuration used by a subclass. This
113      * allows the subclass to specify it's own kind.
114      *
115      * @return a customized configuration.
116      */

117     public abstract ConfigurationStandard getConfiguration();
118
119     protected ConfigurationStandard makeConfiguration() {
120         return new ConfigurationStandard();
121     }
122
123
124     /**
125      * Returns the configuration, and ensures that
126      * HtmlDocWriter.configuration is of the type used by
127      * this class.
128      *
129      * @return the current instanceof ConfigurationStandard being
130      * used and creates one if needed. This will <b>not</b>
131      * be null.
132      */

133     // todo these are the heinous globals that impose one process per classloader
134
public static com.sun.tools.doclets.standard.ConfigurationStandard
135         configuration() {
136         if (HtmlDocWriter.configuration == null ||
137             !(HtmlDocWriter.configuration instanceof ConfigurationStandard)) {
138             HtmlDocWriter.configuration = new ConfigurationStandard();
139             //TODO: change to makeConfiguration()
140
}
141         return (ConfigurationStandard)HtmlDocWriter.configuration;
142     }
143
144     /**
145      * Creates and returns an IndexBuilder that includes aspects.
146      *
147      * @param root RootDoc to pass the new IndexBuilder.
148      * @param classesOnly <code>true</code> if only classes
149      * should be included.
150      * @return an IndexBuilder that includes aspects.
151      */

152     protected IndexBuilder indexBuilder(RootDoc root, boolean classesOnly) {
153         class MyIndexBuilder extends IndexBuilder {
154             public MyIndexBuilder(RootDoc r, boolean n) {
155                 super(r, n);
156             }
157             public MyIndexBuilder(RootDoc r, boolean n, boolean b) {
158                 super(r, n, b);
159             }
160             protected void putMembersInIndexMap(ClassDoc classdoc) {
161                 super.putMembersInIndexMap(classdoc);
162                 if (classdoc instanceof org.aspectj.ajdoc.ClassDoc) {
163                     org.aspectj.ajdoc.ClassDoc cd =
164                         (org.aspectj.ajdoc.ClassDoc)classdoc;
165                     adjustIndexMap(cd.pointcuts());
166                     if (cd instanceof AspectDoc) {
167                         adjustIndexMap(((AspectDoc)cd).advice());
168                     }
169                 }
170             }
171         }
172         return new MyIndexBuilder(root, configuration().nodeprecated, classesOnly);
173     }
174
175
176     /**
177      * Does the work in generating the documentation.
178      * First, call all the passes return from {@link #generateCheckPasses}
179      * them perform some copying. Second build the classtree, run the
180      * pre-classgeneration passes, generate the packages, generate the
181      * classes, then call all the postGenerationClasses.
182      *
183      * @param root the root of the documentation.
184      */

185     protected void startGeneration(RootDoc root) throws DocletAbortException {
186
187         if (!generateCheckPasses(getConfiguration(), root)) return;
188
189         performCopy(getConfiguration().destdirname,
190                     getConfiguration().helpfile);
191         performCopy(getConfiguration().destdirname,
192                     getConfiguration().stylesheetfile);
193
194         classtree = new ClassTree(root, getConfiguration().nodeprecated);
195
196         generatePrePasses(getConfiguration(), root);
197
198         generatePackageCycle(getConfiguration().packages,
199                              getConfiguration().createtree,
200                              getConfiguration().nodeprecated);
201          generateClassFiles(root, classtree);
202         generatePostPasses(getConfiguration(), root);
203     }
204
205     /**
206      * A class representing a single pass in the generation cycles. It
207      * does some of the dirty work for you.
208      */

209     public static abstract class Pass {
210
211         /** The root available to this pass. */
212         protected RootDoc root;
213
214         /** The configuration available to this pass. */
215         protected ConfigurationStandard cs;
216
217         /** The doclet available to this pass. */
218         protected AbstractStandard std;
219         
220         public Pass() {}
221
222         /**
223          * Returns the title of the pass for logging.
224          *
225          * @return the unique title of this pass. This can
226          * be <code>null</code> to disable display.
227          */

228         public abstract String JavaDoc title();
229
230         /**
231          * Do the generation work. All instance variables
232          * are guaranteed to be set.
233          */

234         protected abstract void gen() throws DocletAbortException;
235
236         /**
237          * Do the actual generation if {@link #cond} returns
238          * <code>true</code>. Do some other logging, too.
239          *
240          * @param std the AbstractStandard to use.
241          * @param cs the ConfigurationStandard to use.
242          * @param root the RootDoc to use.
243          */

244         public final void generate(AbstractStandard std,
245                                    ConfigurationStandard cs,
246                                    RootDoc root)
247             throws DocletAbortException {
248             this.std = std;
249             this.cs = cs;
250             this.root = root;
251             if (cond()) {
252                 String JavaDoc title = title();
253                 long start = System.currentTimeMillis();
254                 if (cs.log && title != null) {
255                     cs.standardmessage.notice("doclet.pass_msg", title);
256                 }
257                 gen();
258                 if (cs.log && title != null) {
259                     long stop = System.currentTimeMillis();
260                     cs.standardmessage.notice("doclet.done_msg",
261                                               title, (stop-start)+"");
262                 }
263             }
264         }
265
266         /**
267          * Returns whether the generation should proceed. Override
268          * this method for conditional passes.
269          *
270          * @return <code>true</code> is this pass shoulud proceed.
271          */

272         protected boolean cond() {
273             return true;
274         }
275     }
276
277     /**
278      * A convenience class for doing checks.
279      */

280     public abstract static class Check extends Pass {
281
282         /**
283          * Returns the error message if check fails.
284          *
285          * @return error message if check fails.
286          */

287         protected abstract String JavaDoc message();
288
289         /**
290          * Returns whether check has failed or not.
291          *
292          * @return <code>true</code> is check fails.
293          */

294         protected abstract boolean cond();
295
296         /**
297          * Prints message, because we've failed and throws
298          * a DocletAbortException to notify the doclet
299          * that we've failed.
300          */

301         protected void gen() throws DocletAbortException {
302             cs.standardmessage.error(message());
303             throw new DocletAbortException();
304         }
305
306         /**
307          * Returns null, because we don't want to be displayed.
308          *
309          * @return <code>null</code>.
310          */

311         public String JavaDoc title() { return null; }
312     }
313
314     /**
315      * Generates the passes to run before generating the classes.
316      */

317     private final void generatePrePasses(ConfigurationStandard cs,
318                                          RootDoc root)
319         throws DocletAbortException {
320         generatePasses(cs, root, preGenerationClasses());
321     }
322
323     /**
324      * Generates the passes to run after generating the classes.
325      */

326     private final void generatePostPasses(ConfigurationStandard cs,
327                                           RootDoc root)
328         throws DocletAbortException {
329         generatePasses(cs, root, postGenerationClasses());
330     }
331
332     /**
333      * Generates the passes that run before doing anything. These
334      * passes check that it's OK to do anything.
335      */

336     private final boolean generateCheckPasses(ConfigurationStandard cs,
337                                               RootDoc root)
338         throws DocletAbortException {
339         try {
340             generatePasses(cs, root, checkClasses());
341         } catch (DocletAbortException e) {
342             return false;
343         }
344         return true;
345     }
346
347     /**
348      * Generates passes from <code>classes</code>. For each
349      * class found in <code>classes</code> a constructor taking zero
350      * or one-argument is called. Then the generate method is
351      * called on that Pass passing it <code>this</code>, the
352      * configuration, and root.
353      *
354      * @param cs configuration to use.
355      * @param root root we're documenting.
356      * @param classes list of subtypes of {@link Pass} that
357      * will be run.
358      */

359     private final void generatePasses(ConfigurationStandard cs,
360                                       RootDoc root,
361                                       Class JavaDoc[] classes)
362         throws DocletAbortException {
363         if (classes == null) return;
364         nextClass:
365         for (int i = 0; i < classes.length; i++) {
366             try {
367                 Constructor JavaDoc[] ctrs = classes[i].getConstructors();
368             nextCtr:
369                 for (int j = 0; j < ctrs.length; j++) {
370                     Pass pass = null;
371                     if (ctrs[j].getParameterTypes().length == 0) {
372                         pass = (Pass)ctrs[j].newInstance(new Object JavaDoc[]{});
373                     } else if (ctrs[j].getParameterTypes().length == 1) {
374                         pass = (Pass)ctrs[j].newInstance(new Object JavaDoc[]{this});
375                     }
376                     if (pass != null) {
377                         pass.generate(this,cs,root);
378                         continue nextClass;
379                     }
380                 }
381                 throw new Exception JavaDoc("Can't create pass for class " + classes[i]);
382             } catch (Exception JavaDoc e) {
383                 e.printStackTrace();
384                 Standard.configuration().standardmessage.
385                     error("doclet.exception", e+"");
386                 throw new DocletAbortException();
387             }
388         }
389     }
390
391
392     /**
393      * Generates the packages.
394      */

395     protected void generatePackageCycle(PackageDoc[] pkgs,
396                                         boolean createtree,
397                                         boolean nodeprecated)
398         throws DocletAbortException {
399         Arrays.sort(pkgs);
400         for (int i = 0; i < pkgs.length; i++) {
401             PackageDoc prev = i == 0 ? null : pkgs[i-1];
402             PackageDoc curr = pkgs[i];
403             PackageDoc next = i == pkgs.length-1 ? null : pkgs[i+1];
404             generatePackages(prev, curr, next,
405                              createtree, nodeprecated);
406         }
407     }
408
409     /**
410      * Generates a package doc for the three PackageDocs passed.
411      */

412     protected void generatePackages(PackageDoc prev,
413                                     PackageDoc curr,
414                                     PackageDoc next,
415                                     boolean createtree,
416                                     boolean nodeprecated)
417         throws DocletAbortException {
418         PackageWriter.generate(curr, prev, next);
419         if (createtree) {
420             PackageTreeWriter.generate(curr, prev,
421                                        next, nodeprecated);
422         }
423         PackageFrameWriter.generate(curr);
424     }
425
426     /**
427      * Generates all the classes.
428      */

429     protected void generateClassCycle(ClassDoc[] cs,
430                                       ClassTree classtree,
431                                       boolean nopackage)
432         throws DocletAbortException {
433         Arrays.sort(cs);
434         for(int i = 0; i < cs.length; i++) {
435             if (configuration().nodeprecated &&
436                 cs[i].tags("deprecated").length > 0) {
437                 continue;
438             }
439             ClassDoc prev = i == 0 ? null : cs[i-1];
440             ClassDoc curr = cs[i];
441             ClassDoc next = i == cs.length-1 ? null : cs[i+1];
442             generateClasses(prev, curr, next,
443                             classtree, nopackage);
444         }
445     }
446
447     /**
448      * Generates class docs for the three ClassDocs passed.
449      */

450     protected void generateClasses(ClassDoc prev,
451                                    ClassDoc curr,
452                                    ClassDoc next,
453                                    ClassTree classtree,
454                                    boolean nopackage)
455         throws DocletAbortException {
456         ClassWriter.generate(curr, prev, next,
457                              classtree, nopackage);
458     }
459
460     /**
461      * Returns the delegation to {@link #configuration()}.
462      */

463     public static int optionLength(String JavaDoc option) {
464         return configuration().optionLength(option);
465     }
466
467     /**
468      * Returns the delegation to {@link #configuration()}.
469      */

470     public static boolean validOptions(String JavaDoc options[][],
471                                        DocErrorReporter reporter)
472         throws IOException JavaDoc {
473         return configuration().validOptions(options, reporter);
474     }
475 }
476         
477
478
Popular Tags