KickJava   Java API By Example, From Geeks To Geeks.

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


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.ajdoc.IntroducedSuperDoc;
25 import org.aspectj.ajdoc.PointcutDoc;
26 import org.aspectj.compiler.base.ast.ClassDec;
27 import org.aspectj.compiler.base.ast.CodeDec;
28 import org.aspectj.compiler.base.ast.CompilationUnit;
29 import org.aspectj.compiler.base.ast.Constructor;
30 import org.aspectj.compiler.base.ast.ConstructorDec;
31 import org.aspectj.compiler.base.ast.Dec;
32 import org.aspectj.compiler.base.ast.Field;
33 import org.aspectj.compiler.base.ast.FieldDec;
34 import org.aspectj.compiler.base.ast.Import;
35 import org.aspectj.compiler.base.ast.Imports;
36 import org.aspectj.compiler.base.ast.InterfaceDec;
37 import org.aspectj.compiler.base.ast.Method;
38 import org.aspectj.compiler.base.ast.NameType;
39 import org.aspectj.compiler.base.ast.SourceLocation;
40 import org.aspectj.compiler.base.ast.TextSourceLocation;
41 import org.aspectj.compiler.base.ast.Type;
42 import org.aspectj.compiler.base.ast.TypeDec;
43 import org.aspectj.compiler.crosscuts.AspectJCompiler;
44 import org.aspectj.compiler.crosscuts.ast.AspectDec;
45 import org.aspectj.compiler.crosscuts.ast.IntroducedSuperDec;
46 import org.aspectj.compiler.crosscuts.ast.PointcutSO;
47
48 import org.aspectj.ajdoc.ClassDoc;
49 import com.sun.javadoc.ConstructorDoc;
50 import com.sun.javadoc.FieldDoc;
51 import com.sun.javadoc.MethodDoc;
52 import com.sun.javadoc.PackageDoc;
53
54 import java.lang.reflect.Modifier JavaDoc;
55 import java.util.ArrayList JavaDoc;
56 import java.util.Collection JavaDoc;
57 import java.util.Collections JavaDoc;
58 import java.util.HashMap JavaDoc;
59 import java.util.Iterator JavaDoc;
60 import java.util.List JavaDoc;
61 import java.util.Map JavaDoc;
62 import java.util.Set JavaDoc;
63
64 /**
65  * This implements ClassDoc and acts as a factory for ClassDocImpl
66  * and associated DocImpl.
67  * The factory will excluded new superclasses and introduction classes
68  * so the caller should take care to include those classes explicitly
69  * by adding them directly before they are sought indirectly or
70  * by post-processing them to enable inclusion as appropriate.
71  */

72 public class ClassDocImpl
73     extends ProgramElementDocImpl
74     implements org.aspectj.ajdoc.ClassDoc {
75
76     /**
77      * Returns an instance of ClassDoc represented by
78      * the passed in TypeDec.
79      *
80      * @param typeDec instance of TypeDec representing
81      * the ClassDoc that will be returned.
82      * @return an instance of ClassDoc mirroring
83      * the passed in TypeDec.
84      */

85     public final static ClassDocImpl getInstance(TypeDec typeDec) {
86         return factory.getInstance(typeDec);
87     }
88
89     /**
90      * Returns an instance of ClassDoc represented by
91      * the passed in TypeDec and containing ClassDoc (may be null).
92      *
93      * @param outerDoc the containing ClassDoc -- may be null.
94      * @param typeDec instance of TypeDec representing
95      * the ClassDoc that will be returned.
96      * @return an instance of ClassDoc mirroring
97      * the passed in TypeDec.
98      */

99     public final static ClassDocImpl getInstance(ClassDoc outerDoc, TypeDec typeDec) {
100         return factory.getInstance(outerDoc, typeDec);
101     }
102
103     /**
104      * Returns the known ClassDocImpl for a given String --
105      * the returned value may be null.
106      *
107      * @return the known ClassDocImpl for a given String --
108      * the returned value may be null.
109      */

110     public final static ClassDocImpl find(String JavaDoc qualifiedName) {
111         return factory.find(qualifiedName);
112     }
113
114     /**The factory used to create instances of this class. */
115     private final static Factory factory = new Factory();
116
117     /** The ClassDec to which is delegated. */
118     private final TypeDec typeDec;
119
120     // todo: we know these Collections are FilteredDecList, so declare that?
121
/** The introductions that affect a ClassDoc. */
122     private Collection JavaDoc introducers;
123
124     /** The array of fields visible in this type. */
125     private Collection JavaDoc fieldDocs;
126
127     /** The array of methods visible in this type. */
128     private Collection JavaDoc methodDocs;
129
130     /** The array of constructors visible in this type.
131       * The implementation must support iterator().remove().
132       */

133     private Collection JavaDoc constructorDocs;
134
135     /** The array of inner classes visible in thie type. */
136     private Collection JavaDoc innerclassDocs;
137
138     /** The array of interfaces this type implements. */
139     private Collection JavaDoc interfaceDocs;
140
141     /** The array of classes this type imports on demand. */
142     private Collection JavaDoc importedClasses;
143
144     /** The array of package this type imports on demand. */
145     private Collection JavaDoc importedPackages;
146
147     /** The array of pointcuts visible in this type. */
148     private Collection JavaDoc pointcutDocs;
149
150     /** cached variant of <code>((AjdocCompiler)ajc()).getFilter()</code> */
151     private AccessChecker filter;
152     
153     /**
154      * Constructs a representation of an AspectJ-compiled class
155      * using the underlying TypeDec and containning ClassDoc.
156      * NOTE: This is protected (and maybe should be private)
157      * because the static method {@link #getInstance(TypeDec)}
158      * should always be used to get instances of this type. It
159      * ensures that enclosing types are created before their
160      * enclosed types.
161      *
162      * @param containingClass ClassDoc that encloses this.
163      * @param typeDec The underlying TypeDec.
164      */

165     protected ClassDocImpl(com.sun.javadoc.ClassDoc containingClass,
166                            TypeDec typeDec) {
167         super(containingClass);
168         this.typeDec = typeDec;
169         //AccessChecker check = getFilter();
170
// RootDocImpl sets inclusion of world classes
171
setIncluded(false);
172         // have to install before creating imports to avoid cycles
173
factory.put(this, typeDec);
174         createImports(importedClasses = new ArrayList JavaDoc(),
175                       importedPackages = new ArrayList JavaDoc());
176     }
177
178     /**
179      * Maps Decs to their counterpart by testing with
180      * <code>instanceof</code>
181      *
182      * @return a MemberDocImpl that has an underlying Dec dec.
183      */

184     public MemberDocImpl docForDec(Dec dec) {
185         if (dec instanceof FieldDec) {
186             return docForDec((FieldDec)dec);
187         }
188         if (dec instanceof CodeDec) {
189             return docForDec((CodeDec)dec);
190         }
191         // todo: map for inner classes, Type, etc?
192
return null; //TODO error ???
193
}
194
195     /**
196      * Returns a FieldDocImpl that has an underlying FieldDec dec.
197      *
198      * @return a FieldDocImpl that has an underlying FieldDec dec.
199      */

200     public FieldDocImpl docForDec(FieldDec dec) {
201         FieldDoc[] fs = fields();
202         for (int i = 0; i < fs.length; i++) {
203             FieldDocImpl fd = (FieldDocImpl)fs[i];
204             if (fd.dec() == dec) return fd;
205         }
206         return null;
207     }
208
209     /**
210      * Returns a CodeDocImpl that has an underlying CodeDec dec.
211      *
212      * @return a CodeDocImpl that has an underlying CodeDec dec.
213      */

214     public CodeDocImpl docForDec(CodeDec dec) {
215         MethodDoc[] ms = methods();
216         for (int i = 0; i < ms.length; i++) {
217             CodeDocImpl cd = (CodeDocImpl)ms[i];
218             if (cd.dec() == dec) return cd;
219         }
220         ConstructorDoc[] cs = constructors();
221         for (int i = 0; i < cs.length; i++) {
222             CodeDocImpl cd = (CodeDocImpl)cs[i];
223             if (cd.dec() == dec) return cd;
224         }
225         return null;
226     }
227
228     /**
229      * @todo ??????
230      */

231     public TypeDec nonNullTypeDec() {
232         if (typeDec().getLexicalType() == null) return typeDec();
233         return super.nonNullTypeDec();
234     }
235
236     /**
237      * Returns a Collection of ClassDocImpls that have corresponding
238      * ClassDecs declared within classDec().
239      *
240      * @return a Collection of ClassDocImpls that have corresponding
241      * ClassDecs declared within classDec().
242      */

243     private Collection JavaDoc createInnerTypes() {
244         Collection JavaDoc items = ((NameType)typeDec.getType()).getInnerTypes();
245         FilteredDecList result =
246             new FilteredDecList(getFilter(), this);
247         if (items != null) {
248             for (Iterator JavaDoc i = items.iterator(); i.hasNext();) {
249                 result.add(((NameType)i.next()).getTypeDec());
250             }
251         }
252         Collections.sort(result);
253         return result;
254     }
255
256     /**
257      * Creates the two collection of imports -- class and packages --
258      * used by the file in which classDec() was declared.
259      *
260      * @param importClasses the classes to fill.
261      * @param importPkgs the packages to fill.
262      */

263     private void createImports(final Collection JavaDoc importClasses,
264                                final Collection JavaDoc importPkgs) {
265         CompilationUnit cu = typeDec.getCompilationUnit();
266         if (cu != null) {
267             Imports imports = cu.getImports();
268             if (imports != null) {
269                 for (int i = 0; i < imports.size(); i++) {
270                     Import imprt = imports.get(i);
271                     if (imprt != null) {
272                         if (imprt.getStar()) {
273                             PackageDoc importedPkg =
274                                 PackageDocImpl.getPackageDoc
275                                 (imprt.getName());
276                             if (importedPkg != null) {
277                                 importPkgs.add(importedPkg);
278                             }
279                         } else {
280                             com.sun.javadoc.ClassDoc importedClass =
281                                 findClass(imprt.getName());
282                             if (importedClass != null) {
283                                 importClasses.add(importedClass);
284                             }
285                         }
286                     }
287                 }
288             }
289         }
290     }
291
292     /**
293      * Returns a Collection of ClassDocImpl representing the
294      * interfaces the underlying TypeDec implements.
295      *
296      * @return a Collection of ClassDocImpl representing the
297      * interfaces the underlying TypeDec implements.
298      */

299     private Collection JavaDoc createInterfaces() {
300         //NameType type = (NameType)typeDec.getType();
301
Collection JavaDoc items = typeDec.getSuperInterfaceTypes();
302         FilteredDecList result =
303             new FilteredDecList(getFilter(), this);
304         if (items != null) {
305             for (Iterator JavaDoc i = items.iterator(); i.hasNext();) {
306                 result.add(((NameType)i.next()).getTypeDec());
307             }
308         }
309         Collections.sort(result);
310         return result;
311     }
312
313     /**
314      * Called by AjdocCompiler to do pruning once the whole world is created.
315      * This avoids using aspect before initialized when
316      * this classdoc constructed as a result of aspect
317      * initialization.
318      */

319     void postProcess() {
320         // prune compiler-generated default constructor if unadvised.
321
// can't do this on construction since advising aspect may exist but be uninitialized
322
final SourceLocation parentLoc = dec().getSourceLocation();
323         final int parentLine = (null == parentLoc ? -1 : parentLoc.getBeginLine());
324         final int parentColumn = (null == parentLoc ? -1 : parentLoc.getBeginColumn());
325         if (null == constructorDocs) {
326             if (null == constructors()) {
327                 // XXX harmless error System.err.println("Unable to post-process");
328
return;
329             }
330         }
331         try {
332             //ArrayList removed = new ArrayList();
333
for (Iterator JavaDoc i = constructorDocs.iterator(); i.hasNext(); ) {
334                 ConstructorDocImpl cdi = (ConstructorDocImpl) i.next();
335                 CodeDec cd = cdi.codeDec();
336                 SourceLocation sl = (null == cd ? null : cd.getSourceLocation());
337                 // if ajc changes so typedec start/end not equal to constructor, then can't recognize
338
if ((null != sl)
339                     && (parentColumn == sl.getBeginColumn())
340                     && (parentLine == sl.getBeginLine())) {
341                     Object JavaDoc[] advice = cdi.advice();
342                     if ((null != advice) && (1 > advice.length)) {
343                         i.remove();
344                         //removed.add(cdi);
345
//System.err.println("removing unadvised generated constructor: " + cdi);
346
} else {
347                         //System.err.println("keeping advised generated constructor: " + cdi);
348
}
349                 } else {
350                      //System.err.println("keeping ungenerated constructor: " + cdi);
351
}
352             }
353 // for (Iterator i = removed.iterator(); i.hasNext();) {
354
// Object dec = i.next();
355
// if (constructorDocs.contains(dec)) {
356
// throw new Error("remove failed for " + dec);
357
// }
358
// }
359
} catch (UnsupportedOperationException JavaDoc e) {
360             System.err.println("Warning: ClassDocImpl.constructorDocs not removable");
361         }
362     }
363     
364     /**
365      * Returns a Collection of ConstructorDocImpl representing the
366      * constructors the underlying TypeDec declares.
367      *
368      * @return a Collection of ConstructorDocImpl representing the
369      * constructors the underlying TypeDec declares.
370      */

371     private Collection JavaDoc createConstructors() {
372         NameType type = (NameType)typeDec.getType();
373         Collection JavaDoc items = type.getConstructors();
374         final SourceLocation parentLoc = dec().getSourceLocation();
375         final int parentLine = (null == parentLoc ? -1 : parentLoc.getBeginLine());
376         final int parentColumn = (null == parentLoc ? -1 : parentLoc.getBeginColumn());
377         FilteredDecList result =
378             new FilteredDecList(getFilter(), this);
379         if (items != null) {
380             for (Iterator JavaDoc i = items.iterator(); i.hasNext();) {
381                 Constructor c = (Constructor) i.next();
382                 ConstructorDec cd = c.getConstructorDec();
383                 ConstructorDocImpl impl = new ConstructorDocImpl(this, cd);
384                 // XXX workaround for ajc bug of default constructor source location
385
SourceLocation sl = (null == cd ? null : cd.getSourceLocation());
386                 // if line/column starts the same, then a generated constructor
387
if ((null != sl)
388                     && (parentColumn == sl.getBeginColumn())
389                     && (parentLine == sl.getBeginLine())) {
390                         // use source location clone without comment from class
391
TextSourceLocation tsl = new TextSourceLocation(sl.getCompilationUnit(),
392                             sl.getStartPosition(), sl.getEndPosition());
393                         tsl.clearComment();
394                         cd.setSourceLocation(tsl);
395                 }
396                 result.add(impl);
397             }
398         }
399         Collections.sort(result);
400         return result;
401     }
402     
403     /**
404      * Returns a Collection of PointcutDocImpl representing the
405      * pointcuts the underlying TypeDec declares.
406      *
407      * @return a Collection of PointcutDocImpl representing the
408      * pointcuts the underlying TypeDec declares.
409      */

410     private Collection JavaDoc createPointcuts() {
411         NameType type = (NameType)typeDec.getType();
412         Collection JavaDoc items = type.getPointcuts();
413         FilteredDecList result =
414             new FilteredDecList(getFilter(), this);
415         if (items != null) {
416             for (Iterator JavaDoc i = items.iterator(); i.hasNext();) {
417                 result.add(((PointcutSO)i.next()).getPointcutDec());
418             }
419         }
420         Collections.sort(result);
421         return result;
422     }
423
424     /**
425      * Returns a Collection of MethodDocImpl representing the
426      * methods the underlying TypeDec declares.
427      *
428      * @return a Collection of MethodDocImpl representing the
429      * methods the underlying TypeDec declares.
430      */

431     private Collection JavaDoc createMethods() {
432         NameType type = (NameType)typeDec.getType();
433         Collection JavaDoc methods = type.getMethods();
434         FilteredDecList result =
435             new FilteredDecList(getFilter(), this);
436         if (methods != null) {
437             for (Iterator JavaDoc i = methods.iterator(); i.hasNext();) {
438                 result.add(((Method)i.next()).getMethodDec());
439             }
440         }
441         Collections.sort(result);
442         return result;
443     }
444
445     /**
446      * Returns a Collection of FieldDocImpl representing the
447      * fields the underlying TypeDec declares.
448      *
449      * @return a Collection of FieldDocImpl representing the
450      * fields the underlying TypeDec declares.
451      */

452     private Collection JavaDoc createFields() {
453         NameType type = (NameType)typeDec.getType();
454         Collection JavaDoc fields = type.getFields();
455         FilteredDecList result =
456             new FilteredDecList(getFilter(), this);
457         if (fields != null) {
458             for (Iterator JavaDoc i = fields.iterator(); i.hasNext();) {
459                 result.add(((Field)i.next()).getFieldDec());
460             }
461         }
462         Collections.sort(result);
463         return result;
464     }
465
466     /** return (and cache) filter from ajc() */
467     protected AccessChecker getFilter() {
468         // nb: called during construction
469
if (null == filter) {
470             AspectJCompiler ajc = ajc();
471             if (ajc instanceof AjdocCompiler) {
472                 filter = ((AjdocCompiler) ajc).getFilter();
473             }
474         }
475         return filter; // still may be null
476
}
477
478     /**
479      * Returns the underlying Dec -- a TypeDec.
480      *
481      * @return the underlying Dec -- a TypeDec.
482      */

483     protected final Dec dec() {
484         return typeDec();
485     }
486     
487     /**
488      * Returns the underlying TypeDec.
489      *
490      * @return the underlying TypeDec.
491      */

492     public final TypeDec typeDec() {
493         return typeDec;
494     }
495
496     /**
497      * Returns the fully-qualified name of this TypeDec including
498      * the package and any enclosing classes.
499      *
500      * @return the fully-qualified name of this TypeDec including
501      * the package and any inclosing classes.
502      */

503     public String JavaDoc qualifiedName() {
504         return qualifiedTypeName().replace('$','.');
505     }
506
507     /**
508      * Returns the fully-qualfied name of this class.
509      *
510      * @return the fully-qualfied name of this class.
511      */

512     public String JavaDoc toString() {
513         return qualifiedName();
514     }
515
516     /**
517      * Returns the single name of this TypeDec excluding the package
518      * but including enclosing classes. NOTE: All dollar signs
519      * are replaced by periods.
520      *
521      * @return the single name of this TypeDec excluding the package
522      * but including enclosing classes.
523      */

524     public String JavaDoc name() {
525         return ((NameType)typeDec().getType()).
526             getExtendedId().replace('$','.');
527     }
528
529     /**
530      * Returns the class specified by <code>classname</code>
531      * from the context of <code>this</code>. This method may return
532      * <code>null</code> denoting the class wasn't found.
533      * Search proceeds in the following order:
534      *
535      * <ul><ll>
536      * <li>qualified name</li>
537      * <li>in this class (inner)</li>
538      * <li>in this package</li>
539      * <li>in the class imports</li>
540      * <li>in the package imports</li>
541      * </ll></ul>
542      *
543      * @return the type specified by <code>classname</code>
544      * from the context of <code>this</code>.
545      * @see Util#findClass(ClassDoc,String,JavaCompiler)
546      * @see <a HREF="http://java.sun.com/products/jdk/1.2/docs/tooldocs">
547      * Javadoc Tool Homepage</a>
548      */

549     public com.sun.javadoc.ClassDoc findClass(String JavaDoc classname) {
550         // Sanity check
551
if (classname == null || classname.length() < 1) {
552             return null;
553         }
554
555         // The result
556
com.sun.javadoc.ClassDoc desired;
557
558         // [0] The trivial case, the classname is this class
559
if (classname.equals(name()) ||
560             classname.equals(qualifiedName())) {
561             return this;
562         }
563
564         // [1] Look up the fully qualified name.
565
if ((desired = ClassDocImpl.find(classname)) != null) {
566             return desired;
567         }
568
569         // [2] Search the inner classes. We can assume that if
570
// classname refers to an inner class it is unqualified
571
// with respect to its package, because step [1] would have
572
// picked it up, then. First look to see if the name
573
// matches, then search the inner class itself. We check two
574
// values:
575
// [1] innername: the unqualified inner class name
576
// [2] classname: the qualified (with outer class) name
577
// Example:
578
// /**
579
// * @see Inner
580
// * // classname == Inner (f'cked)
581
// * // innername == Outer.Inner (ok)
582
// * @see Outer.Inner
583
// * // classname == Outer.Inner (ok)
584
// * // innername == Outer.Outer.Inner (f'cked)
585
// class Outer {
586
// static class Inner {}
587
// }
588
String JavaDoc innername = name() + '.' + classname;
589         com.sun.javadoc.ClassDoc[] inners = innerClasses();
590         if (inners != null) {
591             for (int i = 0; i < inners.length; i++) {
592                 if (classname.equals(inners[i].name()) ||
593                     innername.equals(inners[i].name())) {
594                     return inners[i];
595                 }
596             }
597         }
598
599         // [3] Search in this package
600
if ((desired = containingPackage().findClass(classname)) != null) {
601             return desired;
602         }
603
604         // [4] Search the class imports. The order for this is specified
605
// by the compiler -- if you don't believe me read for yourself:
606
// http://java.sun.com/products/jdk/1.2/docs/tooldocs/win32/ (cont't)
607
// javadoc.html#seesearchorder
608
// We don't look in other package, so we assume classname
609
// is full package-qualified.
610
com.sun.javadoc.ClassDoc[] imports = importedClasses();
611         if (imports != null) {
612             for (int i = 0; i < imports.length; i++) {
613                 if (classname.equals(imports[i].name())) {
614                     return imports[i];
615                 }
616             }
617         }
618
619         // [5] Search the package imports for the fully-qualified name.
620
PackageDoc[] pkgs = importedPackages();
621         if (pkgs != null) {
622             for (int i = 0; i < pkgs.length; i++) {
623                 if ((desired = pkgs[i].findClass(classname)) != null) {
624                     return desired;
625                 }
626             }
627         }
628
629         // [5 1/2] OK, I lied above, we do search a couple packages,
630
// it should be java.lang, but we're aspectj, so we'll look in
631
// org.aspectj.lang, too. We assume the names are package-unqualified
632
// in this step.
633
// TODO: check that this is made final, if not, make it static
634
String JavaDoc[] pkgnames = {"java.lang", "org.aspectj.lang"};
635         for (int i = 0; i < pkgnames.length; i++) {
636             PackageDoc pkg = PackageDocImpl.getPackageDoc(pkgnames[i]);
637             if (pkg != null) {
638                 if ((desired = pkg.findClass(classname)) != null) {
639                     return desired;
640                 }
641             }
642         }
643         // Found nothing.
644
return null;
645     }
646
647     /**
648      * Returns the fields visible in this type.
649      *
650      * @return an array of FieldDoc representing
651      * the fields visible in this type.
652      */

653     public FieldDoc[] fields() {
654         if (fieldDocs == null) {
655             fieldDocs = createFields();
656         }
657         return (FieldDoc[])fieldDocs.toArray
658             (new org.aspectj.ajdoc.FieldDoc[fieldDocs.size()]);
659     }
660
661     /**
662      * Returns <code>true</code> is this type is externalizable.
663      *
664      * @return <code>true</code> is this type is externalizable.
665      */

666     public boolean isExternalizable() {
667         return false; //TODO
668
}
669
670     /**
671      * Returns <code>true</code> if this type is serializable.
672      *
673      * @return <code>true</code> if this type is serializable.
674      */

675     public boolean isSerializable() {
676         for (Iterator JavaDoc i = typeDec().getSuperInterfaceTypes().iterator();
677              i.hasNext();) {
678             if (((Type)i.next()).getId().equals("java.io.Serializable")) {
679                 return true;
680             }
681         }
682         return false;
683     }
684
685     /**
686      * Returns the methods visible in this type.
687      *
688      * @return an array of MethodDoc representing the
689      * methods visible in this type.
690      */

691     public MethodDoc[] methods() {
692         if (methodDocs == null) {
693             methodDocs = createMethods();
694         }
695         return (MethodDoc[])methodDocs.toArray
696             (new org.aspectj.ajdoc.MethodDoc[methodDocs.size()]);
697     }
698
699     /**
700      * Returns the serializable methods visible in this type.
701      *
702      * @return an array of MethodDoc representing the
703      * serializable methods visible in this type.
704      */

705     public MethodDoc[] serializationMethods() {
706         List JavaDoc ser = new ArrayList JavaDoc();
707         MethodDoc[] mds = methods();
708         for (int i = 0, N = mds.length; i < N; i++) {
709             if (mds[i].tags("@serialized").length > 1) ser.add(mds[i]);
710         }
711         return (MethodDoc[])ser.toArray(new MethodDoc[ser.size()]);
712     }
713
714     /**
715      * Returns the serializable fields visible in this type.
716      *
717      * @return an array of MethodDoc representing the
718      * serializable fields visible in this type.
719      */

720     public FieldDoc[] serializableFields() {
721         List JavaDoc ser = new ArrayList JavaDoc();
722         FieldDoc[] fds = fields();
723         for (int i = 0, N = fds.length; i < N; i++) {
724             if (fds[i].serialFieldTags().length > 1) ser.add(fds[i]);
725         }
726         return (FieldDoc[])ser.toArray(new FieldDoc[ser.size()]);
727     }
728
729     /**
730      * Returns <code>true</code> is this type contains
731      * visible serializable fields.
732      *
733      * @return <code>true</code> is this type contains
734      * visible serializable fields.
735      */

736     public boolean definesSerializableFields() {
737         return serializableFields().length > 0;
738     }
739
740     /**
741      * Returns the super type of this type. The return value
742      * is guaranteed to be non-null unless this represents
743      * java.lang.Object.
744      *
745      * @return a ClassDoc representing the super type of this type.
746      * or null if this represents java.lang.Object.
747      */

748     public com.sun.javadoc.ClassDoc superclass() {
749         if ("java.lang.Object".equals(qualifiedTypeName())) {
750             return null;
751         } else {
752             TypeDec superType = typeDec().getSuperClassType().getTypeDec();
753             return ClassDocImpl.getInstance(superType);
754         }
755     }
756
757     /**
758      * Returns <code>true</code> is <code>c</code> is a
759      * subtype of <code>this</code>.
760      *
761      * @return <code>true</code> is <code>c</code> is a
762      * subtype of <code>this</code>.
763      */

764     public boolean subclassOf(com.sun.javadoc.ClassDoc c) {
765         return c != null && c.equals(superclass());
766     }
767
768     /**
769      * Returns the interfaces this type implements.
770      *
771      * @return an array of ClassDoc representing the
772      * interfaces this type implements.
773      */

774     public com.sun.javadoc.ClassDoc[] interfaces() {
775         if (interfaceDocs == null) {
776             interfaceDocs = createInterfaces();
777         }
778         return (ClassDoc[])interfaceDocs.toArray
779             (new org.aspectj.ajdoc.ClassDoc[interfaceDocs.size()]);
780     }
781
782     /**
783      * Returns the constructors visible in this type.
784      *
785      * @return an array of ConstructorDoc representing the
786      * visible constructors in this type.
787      */

788     public ConstructorDoc[] constructors() {
789         if (constructorDocs == null) {
790             constructorDocs = createConstructors();
791         }
792         return (ConstructorDoc[])constructorDocs.toArray
793             (new org.aspectj.ajdoc.ConstructorDoc[constructorDocs.size()]);
794     }
795
796     /**
797      * Returns the inner class visible in this type.
798      *
799      * @return an array of ClassDoc representing the inner
800      * classes visible in this type.
801      */

802     public com.sun.javadoc.ClassDoc[] innerClasses() {
803         if (innerclassDocs == null) {
804             innerclassDocs = createInnerTypes();
805         }
806         final int size = innerclassDocs.size();
807         return (ClassDoc[])innerclassDocs.toArray
808             (new org.aspectj.ajdoc.ClassDoc[size]);
809     }
810
811         /**
812      * Returns the types imported on demand by this type.
813      *
814      * @return an array of ClassDoc representing the
815      * types imported on demand by this type.
816      */

817     public com.sun.javadoc.ClassDoc[] importedClasses() {
818         return (ClassDoc[])importedClasses.toArray
819             (new org.aspectj.ajdoc.ClassDoc[importedClasses.size()]);
820     }
821
822     /**
823      * Returns the packages imported on demand by this type.
824      *
825      * @return an array of PackageDoc representing the
826      * packages imported on demand by this type.
827      */

828     public PackageDoc[] importedPackages() {
829         return (PackageDoc[])importedPackages.toArray
830             (new org.aspectj.ajdoc.PackageDoc[importedPackages.size()]);
831     }
832
833     /**
834      * Returns the pointcuts visible in this type.
835      *
836      * @return an array of PointcutDoc representing the
837      * pointcuts visible in this type.
838      */

839     public PointcutDoc[] pointcuts() {
840         if (pointcutDocs == null) {
841             pointcutDocs = createPointcuts();
842         }
843         return (PointcutDoc[])pointcutDocs.toArray
844             (new PointcutDoc[pointcutDocs.size()]);
845     }
846
847     /**
848      * Returns <code>true</code> is this type is <code>abstract</code>.
849      *
850      * @return <code>true</code> is this type is <code>abstract</code>.
851      */

852     public boolean isAbstract() {
853         return typeDec().isAbstract();
854     }
855
856     /**
857      * Returns <code>true</code> is this type is as exception.
858      *
859      * @return <code>true</code> is this type is an instance
860      * of java.lang.Exception.
861      */

862     public boolean isException() {
863         //TODO: make lazy
864
for (com.sun.javadoc.ClassDoc superclass = superclass();
865              superclass != null &&
866                  !superclass.qualifiedTypeName().equals("java.lang.Object");
867              superclass = superclass.superclass()) {
868             if (superclass.qualifiedTypeName().equals("java.lang.Exception")) {
869                 return true;
870             }
871         }
872         return false;
873     }
874
875     /**
876      * Returns <code>true</code> is this type is an error.
877      *
878      * @return <code>true</code> is this type is an instance
879      * of java.lang.Error.
880      */

881     public boolean isError() {
882         //TODO: make lazy
883
for (com.sun.javadoc.ClassDoc superclass = superclass();
884              superclass != null &&
885                  !superclass.qualifiedTypeName().equals("java.lang.Object");
886              superclass = superclass.superclass()) {
887             if (superclass.qualifiedTypeName().equals("java.lang.Error")) {
888                 return true;
889             }
890         }
891         return false;
892     }
893
894     /**
895      * Returns the introductions affecting a ClassDoc's
896      * type hierarchy.
897      *
898      * @return an array of IntroducedSuperDoc representing the
899      * introductions of this ClassDoc that affect its
900      * type hierarchy.
901      */

902     public IntroducedSuperDoc[] introducers() {
903         if (introducers == null) {
904             introducers = createIntroducers();
905         }
906         return (IntroducedSuperDoc[])introducers.toArray
907             (new IntroducedSuperDoc[introducers.size()]);
908     }
909     
910     /**
911      * Returns <code>true</code> is this is an <code>interface</code>.
912      *
913      * @return <code>true</code> is this is an <code>interface</code>.
914      */

915     public boolean isInterface() {
916         return typeDec() instanceof InterfaceDec;
917     }
918
919     /**
920      * Returns <code>true</code> is this is a <code>class</code>.
921      *
922      * @return <code>true</code> is this is a <code>class</code>.
923      */

924     public boolean isClass() {
925         return typeDec() instanceof ClassDec;
926     }
927
928     /**
929      * Returns <code>true</code> is this is an <code>aspect</code>.
930      *
931      * @return <code>true</code> is this is an <code>aspect</code>.
932      */

933     public boolean isAspect() {
934         return typeDec() instanceof AspectDec;
935     }
936
937     /**
938      * Returns <code>true</code> is this class is neither
939      * an error nor an exception, but this still could be
940      * an aspect.
941      *
942      * @return <code>true</code> is this class is neither
943      * an error nor an exception, but this still could be
944      * an aspect.
945      */

946     public boolean isOrdinaryClass() {
947         return isClass() && !(isError() || isException());
948     }
949
950     /**
951      * Returns int modifiers with the 'interface' bit set.
952      *
953      * @return int modifiers with the 'interface' bit set.
954      * @see java.lang.reflect.Modifier.
955      */

956     public int modifierSpecifier() {
957         return super.modifierSpecifier()
958             | (isInterface() ? Modifier.INTERFACE : 0);
959     }
960
961     
962     /* ------------------------------------------------------------
963      * Implementation of Type
964      * ------------------------------------------------------------
965      */

966
967     /**
968      * Returns the declaration of this type -- null if
969      * this isn't included.
970      *
971      * @return the ClassDoc represented by this Type or null
972      * if this isn't included.
973      */

974     public com.sun.javadoc.ClassDoc asClassDoc() {
975         return isIncluded() ? this : null;
976     }
977
978     /**
979      * Returns this type's dimension information as a String.
980      *
981      * @return this type's dimension information as a String.
982      */

983     public String JavaDoc dimension() {
984         return "";
985     }
986
987     /**
988      * Returns qualified name of type excluding
989      * any dimension information.
990      *
991      * @return qualified name of type excluding
992      * any dimension information.
993      */

994     public String JavaDoc qualifiedTypeName() {
995         return typeDec().getFullName().replace('$', '.');
996     }
997
998     /**
999      * Returns unqualified name of type excluding
1000     * any dimension information.
1001     *
1002     * @return unqualified name of type excluding
1003     * any dimension information.
1004     */

1005    public String JavaDoc typeName() {
1006        return typeDec().getId().replace('$', '.');
1007    }
1008
1009    /**
1010     * Returns the Collection of IntroducedSuperDec that
1011     * introduce a type intro this's type hierarchy. At the
1012     * same time, the method makes sure <code>this</code> is
1013     * added to every IntroducedSuperDec's list of targets.
1014     *
1015     * @return Collection of IntroducedSuperDec that
1016     * introduce a type intro this's type hierarchy.
1017     */

1018    private Collection JavaDoc createIntroducers() {
1019        Set JavaDoc affectedBy = ajc().getCorrespondences().getAffectedBy(typeDec);
1020        if (affectedBy.size() < 1) {
1021            return Collections.EMPTY_LIST;
1022        }
1023        Collection JavaDoc list = new ArrayList JavaDoc();
1024        for (Iterator JavaDoc i = affectedBy.iterator(); i.hasNext();) {
1025            Object JavaDoc o = i.next();
1026            if (o instanceof IntroducedSuperDec) {
1027                IntroducedSuperDec dec = (IntroducedSuperDec)o;
1028                TypeDec owner = ((NameType)dec.getDeclaringType()).getTypeDec();
1029                AspectDocImpl ad = (AspectDocImpl)ClassDocImpl.getInstance(owner);
1030                IntroducedSuperDocImpl id = (IntroducedSuperDocImpl)ad.introDocForDec(dec);
1031                list.add(id);
1032                id.addTarget(this);
1033                
1034            }
1035        }
1036        return list;
1037    }
1038
1039    
1040    /* ------------------------------------------------------------
1041     * Factory instantiation
1042     * ------------------------------------------------------------
1043     */

1044
1045    /**
1046     * Inner class in charge of creating instances of ClassDocImpl.
1047     */

1048    private final static class Factory {
1049
1050        private final Map JavaDoc typeDecsToClassDocs = new HashMap JavaDoc();
1051        private final Map JavaDoc qualifiedNamesToClassDocs = new HashMap JavaDoc();
1052
1053        public final ClassDocImpl find(String JavaDoc qualifiedName) {
1054            return (ClassDocImpl)qualifiedNamesToClassDocs.get(qualifiedName);
1055        }
1056
1057        public final ClassDocImpl getInstance(TypeDec typeDec) {
1058            if (typeDec == null) return null;
1059            ClassDocImpl outerDoc = getInstance(typeDec.getEnclosingTypeDec());
1060
1061            return getInstance(outerDoc, typeDec);
1062        }
1063        public final ClassDocImpl getInstance(ClassDoc outerDoc,
1064                                              TypeDec typeDec) {
1065            if (typeDec == null) return null;
1066            ClassDocImpl cd = (ClassDocImpl)typeDecsToClassDocs.get(typeDec);
1067            if (cd == null) {
1068                cd = makeInstance(outerDoc, typeDec);
1069                /*
1070                Object o = typeDecsToClassDocs.put(typeDec, cd);
1071                if (null != o) {
1072                    throw new Error("new " + cd + " displaced " + o + " for " + typeDec);
1073                }
1074                */

1075            }
1076            return cd;
1077        }
1078        private final ClassDocImpl makeInstance(ClassDoc outerDoc,
1079                                                TypeDec typeDec) {
1080            ClassDocImpl result = null;
1081            if (typeDec instanceof AspectDec) {
1082                result = new AspectDocImpl(outerDoc, (AspectDec)typeDec);
1083            } else {
1084                result = new ClassDocImpl(outerDoc, typeDec);
1085            }
1086            if (null == result.containingPackage()) {
1087                System.err.println("Warning: unable to add "
1088                                   + result + " to package");
1089            }
1090            return result;
1091        }
1092
1093        /**
1094         * constructor installs itself here before generating imports.
1095         * fyi: not Thread-safe since available from factory before
1096         * construction completes
1097         * @return object displaced, if any - error if not null
1098         */

1099        private final Object JavaDoc put(ClassDocImpl classdoc, TypeDec typeDec) {
1100            Object JavaDoc result = typeDecsToClassDocs.put(typeDec, classdoc);
1101            if (null == result) {
1102                result = qualifiedNamesToClassDocs.put(classdoc.qualifiedName(), classdoc);
1103            }
1104            return result;
1105        }
1106    } // factory
1107
}
1108
Popular Tags