KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > aspectj > tools > ajdoc > RootDocImpl


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.ajdoc;
23
24 import org.aspectj.compiler.base.ast.TypeDec;
25 import org.aspectj.compiler.base.ast.World;
26
27 import com.sun.javadoc.ClassDoc;
28 import com.sun.javadoc.PackageDoc;
29
30 import java.util.ArrayList JavaDoc;
31 import java.util.Collection JavaDoc;
32 import java.util.Collections JavaDoc;
33 import java.util.HashSet JavaDoc;
34 import java.util.Iterator JavaDoc;
35 import java.util.List JavaDoc;
36 import java.util.Set JavaDoc;
37
38 /**
39  * This is responsible for constituting the world
40  * of specified[classes|packages] and all classes.
41  * It ensures that any classes compiled are included (if appropriate)
42  * but does not ensure that linked classes are.
43  */

44 public class RootDocImpl
45     extends DocImpl
46     implements org.aspectj.ajdoc.RootDoc,
47                Quietable {
48
49     /** The collection of packages specified to be documented. */
50     private final Set JavaDoc specifiedPackages;
51
52     /** The collection of types specified to be documented. */
53     private final Set JavaDoc specifiedClasses;
54
55     /** The collection of packages visible in this world. */
56     private final Set JavaDoc packages = new HashSet JavaDoc();
57
58     /** The collection of classes visible in this world. */
59     private final Set JavaDoc classes = new HashSet JavaDoc();
60
61     /** The documentation options. */
62     private final String JavaDoc[][] options;
63
64     /** The World delegate. */
65     private final World world;
66
67     /** Determines whether items are included */
68     private final AccessChecker filter;
69
70     public RootDocImpl(World world, String JavaDoc[][] options,
71                        Collection JavaDoc pkgnames, Collection JavaDoc classnames,
72                        AccessChecker filter) {
73         this.world = world;
74         this.options = options;
75         this.filter = (null != filter ? filter : AccessChecker.PUBLIC);
76         Set JavaDoc set = createSpecifiedPackages(pkgnames);
77         specifiedPackages = set; // modifiable to prune empty packages
78
set = createSpecifiedClasses(classnames);
79         specifiedClasses = Collections.unmodifiableSet(set);
80         // adds all world classes and packages for classes and packages
81
// addWorldTypes(); // todo re-enable as needed
82
// make sure specified are added - should duplicate world
83
// but should come after since packages are removed if empty
84
addSpecifiedPackages();
85         addSpecifiedClasses();
86         setupDominatesRelations();
87         ensureWorldInclusion();
88     }
89     /* ------------------------------------------------------------
90      * Implementation of RootDoc
91      * ------------------------------------------------------------
92      */

93
94     /**
95      * Returns the classes visible in this world.
96      *
97      * @return an array of ClassDoc representing the visible
98      * classes in this world.
99      */

100     public ClassDoc[] classes() {
101         return (ClassDoc[])classes.toArray
102             (new org.aspectj.ajdoc.ClassDoc[classes.size()]);
103     }
104     
105     /**
106      * Returns a type visible in this world
107      * for the name <code>className</code>. If there is
108      * no visible package, this method will return
109      * <code>null</code>.
110      *
111      * @return an instance of ClassDoc in this world
112      * that corresponds to <code>className</code>.
113      * <code>null</code> is returned if there exists
114      * no such visible type named <code>className</code>.
115      */

116     public ClassDoc classNamed(String JavaDoc className) {
117         ClassDoc[] docs = classes();
118         for (int i = 0; i < docs.length; i++) {
119             ClassDoc doc = docs[i];
120             if (doc.name().equals(className)) {
121                 return doc;
122             }
123         }
124         return null;
125     }
126
127     /**
128      * Returns a package visible in this world
129      * for the name <code>packageName</code>. If there is
130      * no visible package, this method will return
131      * <code>null</code>.
132      *
133      * @return an instance of PackageDoc in this world
134      * that corresponds to <code>packageName</code>.
135      * <code>null</code> is returned if there exists
136      * no such visible package named <code>packageName</code>.
137      */

138     public PackageDoc packageNamed(String JavaDoc packageName) {
139         for (Iterator JavaDoc i = packages.iterator(); i.hasNext();) {
140             PackageDoc doc = (PackageDoc)i.next();
141             if (doc.name().equals(packageName)) {
142                 return doc;
143             }
144         }
145         return null;
146     }
147
148     /**
149      * Returns the underlying world.
150      *
151      * @return an instance of World representing all
152      * the CompilationUnits.
153      */

154     public World world() {
155         return world;
156     }
157
158     /**
159      * Returns the documentation options.
160      *
161      * @return the documentation options.
162      */

163     public String JavaDoc[][] options() {
164         return options;
165     }
166
167     /**
168      * Returns the types specified to be documented.
169      *
170      * @return an array of ClassDoc representing the
171      * specified types.
172      */

173     public ClassDoc[] specifiedClasses() {
174         return (ClassDoc[])specifiedClasses.toArray
175             (new org.aspectj.ajdoc.ClassDoc[specifiedClasses.size()]);
176     }
177
178     /**
179      * Returns the packages specified to be documented.
180      *
181      * @return an array of PackageDoc representing the
182      * specified packages.
183      */

184     public PackageDoc[] specifiedPackages() {
185         return (PackageDoc[])specifiedPackages.toArray
186             (new org.aspectj.ajdoc.PackageDoc[specifiedPackages.size()]);
187     }
188
189
190     /* ------------------------------------------------------------
191      * Implementation of Quietable
192      * ------------------------------------------------------------
193      */

194
195     /** <code>true</code> when notices should be printed. */
196     private boolean notice = true;
197
198     /** Supresses output notices. */
199     public void quiet() { notice = false; }
200
201     /** Allows output notices. */
202     public void speak() { notice = true; }
203
204
205     /* ------------------------------------------------------------
206      * Implementation of DocErrReporter
207      * ------------------------------------------------------------
208      */

209
210     /**
211      * Prints the error message <code>msg</code> using
212      * the current error handler.
213      *
214      * @param msg the error message.
215      */

216     public void printError(String JavaDoc msg) {
217         err().printError(msg);
218     }
219
220     /**
221      * Prints the notice message <code>msg</code> using
222      * the current error handler.
223      *
224      * @param msg the notice message.
225      */

226     public void printNotice(String JavaDoc msg) {
227         if (notice) err().printNotice(msg);
228     }
229
230     /**
231      * Prints the warning message <code>msg</code> using
232      * the current error handler.
233      *
234      * @param msg the warning message.
235      */

236     public void printWarning(String JavaDoc msg) {
237         err().printWarning(msg);
238     }
239
240
241     /* ------------------------------------------------------------
242      * Implementation of Doc
243      * ------------------------------------------------------------
244      */

245
246     /**
247      * Returns <code>null</code>.
248      *
249      * @return <code>null</code>.
250      */

251     public String JavaDoc name() {
252         return "who knows???";
253     }
254
255
256     /* ------------------------------------------------------------
257      * Helper methods
258      * ------------------------------------------------------------
259      */

260     
261     /**
262      * Creates only PackageDocs that were included on the command
263      * line, even if they are empty. Should be used only for
264      * specifiedPackages.
265      */

266     private HashSet JavaDoc createSpecifiedPackages(Collection JavaDoc pkgnames) {
267         HashSet JavaDoc result = new HashSet JavaDoc();
268         for (Iterator JavaDoc i = pkgnames.iterator(); i.hasNext();) {
269             String JavaDoc pkgname = (String JavaDoc)i.next();
270             PackageDocImpl pkgdoc = PackageDocImpl.getPackageDoc(pkgname);
271             pkgdoc.setIncluded(true);
272             result.add(pkgdoc);
273         }
274         return result;
275     }
276     private void addWorldTypes() {
277         for (Iterator JavaDoc i = world.getTypes().iterator(); i.hasNext();) {
278             TypeDec td = (TypeDec)i.next();
279             ClassDocImpl cd = ClassDocImpl.getInstance(td);
280             addClass(cd);
281             cd.setIncluded(filter.canAccess(td));
282         }
283     }
284
285     /**
286      * Creates only ClassDocs that were included on the command
287      * line, and then only if they pass the filter.
288      * Should be used only for specifiedClasses.
289      * todo: createClasses uses to use all classes if no names
290      */

291     private HashSet JavaDoc createSpecifiedClasses(Collection JavaDoc classnames) {
292         HashSet JavaDoc result = new HashSet JavaDoc();
293         if (classnames != null) {
294             for (Iterator JavaDoc i = classnames.iterator(); i.hasNext();) {
295                 String JavaDoc classname = (String JavaDoc)i.next();
296                 for (Iterator JavaDoc j = world.getTypes().iterator(); j.hasNext();) {
297                     TypeDec td = (TypeDec)j.next();
298                     if (filter.canAccess(td)) {
299                         ClassDoc cd = ClassDocImpl.getInstance(td);
300                         if (cd.qualifiedName().equals(classname)) {
301                             result.add(cd);
302                             // add inner classes since not specified explicitly
303
ClassDoc[] inners = cd.innerClasses(); // no cycles, right?
304
if (null != inners) {
305                                 for (int l = 0; l < inners.length; l++) {
306                                     result.add(inners[l]);
307                                 }
308                             }
309                             break;
310                         }
311                     }
312                 }
313                 // todo: warn if class specified but not in world?
314
}
315         }
316         return result;
317     }
318
319     private void addSpecifiedClasses() {
320         for (Iterator JavaDoc i = new ArrayList JavaDoc(specifiedClasses).iterator(); i.hasNext();) {
321             ClassDoc cd = (ClassDoc)i.next();
322             addClass(cd);
323         }
324     }
325
326     private void addSpecifiedPackages() {
327         for (Iterator JavaDoc i = new ArrayList JavaDoc(specifiedPackages).iterator(); i.hasNext();) {
328             PackageDoc pd = (PackageDoc)i.next();
329             ClassDoc[] allClasses = pd.allClasses();
330             if (allClasses.length == 0) {
331                 specifiedPackages.remove(pd);
332             } else {
333                 for (int j = 0; j < allClasses.length; j++) {
334                     addClass(allClasses[j]);
335                 }
336             }
337         }
338     }
339
340     /**
341      * If filter accepts this ClassDoc,
342      * Add it and and inner classes to classes
343      * and add package to packages.
344      */

345     private void addClass(ClassDoc cd) {
346         if (null == cd) return;
347         ClassDocImpl impl = (ClassDocImpl) cd;
348         if (filter.canAccess(impl.typeDec())
349             && (!classes.contains(impl))) {
350             impl.setIncluded(true);
351             classes.add(impl);
352             packages.add(impl.containingPackage());
353             ClassDoc[] inners = impl.innerClasses();
354             for (int i = 0; i < inners.length; i++) {
355                 addClass(inners[i]);
356             }
357         } // todo: flag classes not added?
358
}
359
360     /** Read all classes to find any dominates relations */
361     private void setupDominatesRelations() {
362         // Find just the aspects
363
List JavaDoc aspects = new ArrayList JavaDoc();
364         ClassDoc[] classes = classes();
365         for (int i = 0; i < classes.length; i++) {
366             ClassDocImpl cd = (ClassDocImpl)classes[i];
367             if (cd.isAspect()) {
368                 aspects.add(cd);
369             }
370         }
371
372         // Iterate over the aspects, if
373
for (Iterator JavaDoc i = aspects.iterator(); i.hasNext();) {
374             AspectDocImpl aspect1 = (AspectDocImpl)i.next();
375             for (Iterator JavaDoc j = aspects.iterator(); j.hasNext();) {
376                 AspectDocImpl aspect2 = (AspectDocImpl)j.next();
377                 if (aspect1.dominates(aspect2)) {
378                     aspect1.addDominatee(aspect2);
379                     aspect2.addDominator(aspect1);
380                 }
381             }
382         }
383     }
384
385     /**
386      * Ensure compiled classes are included if they pass the filter
387      * and excluded otherwise.
388      * todo: The set of types available includes the world plus reachable
389      * types from there; I would like to exclude the reachable ones,
390      * but do not know how.
391      */

392     private void ensureWorldInclusion() {
393         for (Iterator JavaDoc i = world.getTypes().iterator(); i.hasNext();) {
394             TypeDec td = (TypeDec)i.next();
395             ClassDocImpl cd = ClassDocImpl.getInstance(td);
396             boolean isIncluded = cd.isIncluded();
397             // todo: update to consider enclosing class privileges
398
boolean shouldInclude = filter.canAccess(td);
399             if (shouldInclude != isIncluded) {
400                 cd.setIncluded(shouldInclude);
401             }
402         }
403     }
404 }
405
Popular Tags