• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 import com.sun.javadoc.*;
18 import com.sun.tools.doclets.*;
19 import org.clearsilver.HDF;
20 import org.clearsilver.CS;
21 import java.util.*;
22 import java.io.*;
23 
24 public class ClassInfo extends DocInfo implements ContainerInfo, Comparable, Scoped
25 {
26     public static final Comparator<ClassInfo> comparator = new Comparator<ClassInfo>() {
27         public int compare(ClassInfo a, ClassInfo b) {
28             return a.name().compareTo(b.name());
29         }
30     };
31 
32     public static final Comparator<ClassInfo> qualifiedComparator = new Comparator<ClassInfo>() {
33         public int compare(ClassInfo a, ClassInfo b) {
34             return a.qualifiedName().compareTo(b.qualifiedName());
35         }
36     };
37 
ClassInfo( ClassDoc cl, String rawCommentText, SourcePositionInfo position, boolean isPublic, boolean isProtected, boolean isPackagePrivate, boolean isPrivate, boolean isStatic, boolean isInterface, boolean isAbstract, boolean isOrdinaryClass, boolean isException, boolean isError, boolean isEnum, boolean isAnnotation, boolean isFinal, boolean isIncluded, String name, String qualifiedName, String qualifiedTypeName, boolean isPrimitive)38     public ClassInfo(
39             ClassDoc cl,
40             String rawCommentText, SourcePositionInfo position,
41             boolean isPublic, boolean isProtected, boolean isPackagePrivate,
42             boolean isPrivate, boolean isStatic,
43             boolean isInterface, boolean isAbstract, boolean isOrdinaryClass,
44             boolean isException, boolean isError, boolean isEnum, boolean isAnnotation,
45             boolean isFinal, boolean isIncluded, String name,
46             String qualifiedName, String qualifiedTypeName, boolean isPrimitive)
47     {
48         super(rawCommentText, position);
49 
50         mClass = cl;
51         mIsPublic = isPublic;
52         mIsProtected = isProtected;
53         mIsPackagePrivate = isPackagePrivate;
54         mIsPrivate = isPrivate;
55         mIsStatic = isStatic;
56         mIsInterface = isInterface;
57         mIsAbstract = isAbstract;
58         mIsOrdinaryClass = isOrdinaryClass;
59         mIsException = isException;
60         mIsError = isError;
61         mIsEnum = isEnum;
62         mIsAnnotation = isAnnotation;
63         mIsFinal = isFinal;
64         mIsIncluded = isIncluded;
65         mName = name;
66         mQualifiedName = qualifiedName;
67         mQualifiedTypeName = qualifiedTypeName;
68         mIsPrimitive = isPrimitive;
69         mNameParts = name.split("\\.");
70     }
71 
init(TypeInfo typeInfo, ClassInfo[] interfaces, TypeInfo[] interfaceTypes, ClassInfo[] innerClasses, MethodInfo[] constructors, MethodInfo[] methods, MethodInfo[] annotationElements, FieldInfo[] fields, FieldInfo[] enumConstants, PackageInfo containingPackage, ClassInfo containingClass, ClassInfo superclass, TypeInfo superclassType, AnnotationInstanceInfo[] annotations)72     public void init(TypeInfo typeInfo, ClassInfo[] interfaces, TypeInfo[] interfaceTypes,
73             ClassInfo[] innerClasses,
74             MethodInfo[] constructors, MethodInfo[] methods, MethodInfo[] annotationElements,
75             FieldInfo[] fields, FieldInfo[] enumConstants,
76             PackageInfo containingPackage, ClassInfo containingClass,
77             ClassInfo superclass, TypeInfo superclassType, AnnotationInstanceInfo[] annotations)
78     {
79         mTypeInfo = typeInfo;
80         mRealInterfaces = interfaces;
81         mRealInterfaceTypes = interfaceTypes;
82         mInnerClasses = innerClasses;
83         mAllConstructors = constructors;
84         mAllSelfMethods = methods;
85         mAnnotationElements = annotationElements;
86         mAllSelfFields = fields;
87         mEnumConstants = enumConstants;
88         mContainingPackage = containingPackage;
89         mContainingClass = containingClass;
90         mRealSuperclass = superclass;
91         mRealSuperclassType = superclassType;
92         mAnnotations = annotations;
93 
94         // after providing new methods and new superclass info,clear any cached
95         // lists of self + superclass methods, ctors, etc.
96         mSuperclassInit = false;
97         mConstructors = null;
98         mMethods = null;
99         mSelfMethods = null;
100         mFields = null;
101         mSelfFields = null;
102         mSelfAttributes = null;
103         mDeprecatedKnown = false;
104 
105         Arrays.sort(mEnumConstants, FieldInfo.comparator);
106         Arrays.sort(mInnerClasses, ClassInfo.comparator);
107     }
108 
init2()109     public void init2() {
110         // calling this here forces the AttrTagInfo objects to be linked to the AttribtueInfo
111         // objects
112         selfAttributes();
113     }
114 
init3(TypeInfo[] types, ClassInfo[] realInnerClasses)115     public void init3(TypeInfo[] types, ClassInfo[] realInnerClasses){
116       mTypeParameters = types;
117       mRealInnerClasses = realInnerClasses;
118     }
119 
getRealInnerClasses()120     public ClassInfo[] getRealInnerClasses(){
121       return mRealInnerClasses;
122     }
123 
getTypeParameters()124     public TypeInfo[] getTypeParameters(){
125       return mTypeParameters;
126     }
127 
checkLevel()128     public boolean checkLevel()
129     {
130         int val = mCheckLevel;
131         if (val >= 0) {
132             return val != 0;
133         } else {
134             boolean v = DroidDoc.checkLevel(mIsPublic, mIsProtected,
135                                                 mIsPackagePrivate, mIsPrivate, isHidden());
136             mCheckLevel = v ? 1 : 0;
137             return v;
138         }
139     }
140 
compareTo(Object that)141     public int compareTo(Object that) {
142         if (that instanceof ClassInfo) {
143             return mQualifiedName.compareTo(((ClassInfo)that).mQualifiedName);
144         } else {
145             return this.hashCode() - that.hashCode();
146         }
147     }
148 
149     @Override
parent()150     public ContainerInfo parent()
151     {
152         return this;
153     }
154 
isPublic()155     public boolean isPublic()
156     {
157         return mIsPublic;
158     }
159 
isProtected()160     public boolean isProtected()
161     {
162         return mIsProtected;
163     }
164 
isPackagePrivate()165     public boolean isPackagePrivate()
166     {
167         return mIsPackagePrivate;
168     }
169 
isPrivate()170     public boolean isPrivate()
171     {
172         return mIsPrivate;
173     }
174 
isStatic()175     public boolean isStatic()
176     {
177         return mIsStatic;
178     }
179 
isInterface()180     public boolean isInterface()
181     {
182         return mIsInterface;
183     }
184 
isAbstract()185     public boolean isAbstract()
186     {
187         return mIsAbstract;
188     }
189 
containingPackage()190     public PackageInfo containingPackage()
191     {
192         return mContainingPackage;
193     }
194 
containingClass()195     public ClassInfo containingClass()
196     {
197         return mContainingClass;
198     }
199 
isOrdinaryClass()200     public boolean isOrdinaryClass()
201     {
202         return mIsOrdinaryClass;
203     }
204 
isException()205     public boolean isException()
206     {
207         return mIsException;
208     }
209 
isError()210     public boolean isError()
211     {
212         return mIsError;
213     }
214 
isEnum()215     public boolean isEnum()
216     {
217         return mIsEnum;
218     }
219 
isAnnotation()220     public boolean isAnnotation()
221     {
222         return mIsAnnotation;
223     }
224 
isFinal()225     public boolean isFinal()
226     {
227         return mIsFinal;
228     }
229 
isIncluded()230     public boolean isIncluded()
231     {
232         return mIsIncluded;
233     }
234 
typeVariables()235     public HashSet<String> typeVariables()
236     {
237         HashSet<String> result = TypeInfo.typeVariables(mTypeInfo.typeArguments());
238         ClassInfo cl = containingClass();
239         while (cl != null) {
240             TypeInfo[] types = cl.asTypeInfo().typeArguments();
241             if (types != null) {
242                 TypeInfo.typeVariables(types, result);
243             }
244             cl = cl.containingClass();
245         }
246         return result;
247     }
248 
gatherHiddenInterfaces(ClassInfo cl, HashSet<ClassInfo> interfaces)249     private static void gatherHiddenInterfaces(ClassInfo cl, HashSet<ClassInfo> interfaces) {
250         for (ClassInfo iface: cl.mRealInterfaces) {
251             if (iface.checkLevel()) {
252                 interfaces.add(iface);
253             } else {
254                 gatherHiddenInterfaces(iface, interfaces);
255             }
256         }
257     }
258 
interfaces()259     public ClassInfo[] interfaces()
260     {
261         if (mInterfaces == null) {
262             if (checkLevel()) {
263                 HashSet<ClassInfo> interfaces = new HashSet<ClassInfo>();
264                 ClassInfo superclass = mRealSuperclass;
265                 while (superclass != null && !superclass.checkLevel()) {
266                     gatherHiddenInterfaces(superclass, interfaces);
267                     superclass = superclass.mRealSuperclass;
268                 }
269                 gatherHiddenInterfaces(this, interfaces);
270                 mInterfaces = interfaces.toArray(new ClassInfo[interfaces.size()]);
271             } else {
272                 // put something here in case someone uses it
273                 mInterfaces = mRealInterfaces;
274             }
275             Arrays.sort(mInterfaces, ClassInfo.qualifiedComparator);
276         }
277         return mInterfaces;
278     }
279 
realInterfaces()280     public ClassInfo[] realInterfaces()
281     {
282         return mRealInterfaces;
283     }
284 
realInterfaceTypes()285     TypeInfo[] realInterfaceTypes()
286     {
287         return mRealInterfaceTypes;
288     }
289 
name()290     public String name()
291     {
292         return mName;
293     }
294 
nameParts()295     public String[] nameParts()
296     {
297         return mNameParts;
298     }
299 
leafName()300     public String leafName()
301     {
302         return mNameParts[mNameParts.length-1];
303     }
304 
qualifiedName()305     public String qualifiedName()
306     {
307         return mQualifiedName;
308     }
309 
qualifiedTypeName()310     public String qualifiedTypeName()
311     {
312         return mQualifiedTypeName;
313     }
314 
isPrimitive()315     public boolean isPrimitive()
316     {
317         return mIsPrimitive;
318     }
319 
allConstructors()320     public MethodInfo[] allConstructors() {
321         return mAllConstructors;
322     }
323 
constructors()324     public MethodInfo[] constructors()
325     {
326         if (mConstructors == null) {
327             MethodInfo[] methods = mAllConstructors;
328             ArrayList<MethodInfo> ctors = new ArrayList<MethodInfo>();
329             for (int i=0; i<methods.length; i++) {
330                 MethodInfo m = methods[i];
331                 if (!m.isHidden()) {
332                     ctors.add(m);
333                 }
334             }
335             mConstructors = ctors.toArray(new MethodInfo[ctors.size()]);
336             Arrays.sort(mConstructors, MethodInfo.comparator);
337         }
338         return mConstructors;
339     }
340 
innerClasses()341     public ClassInfo[] innerClasses()
342     {
343         return mInnerClasses;
344     }
345 
inlineTags()346     public TagInfo[] inlineTags()
347     {
348         return comment().tags();
349     }
350 
firstSentenceTags()351     public TagInfo[] firstSentenceTags()
352     {
353         return comment().briefTags();
354     }
355 
isDeprecated()356     public boolean isDeprecated() {
357         boolean deprecated = false;
358         if (!mDeprecatedKnown) {
359             boolean commentDeprecated = (comment().deprecatedTags().length > 0);
360             boolean annotationDeprecated = false;
361             for (AnnotationInstanceInfo annotation : annotations()) {
362                 if (annotation.type().qualifiedName().equals("java.lang.Deprecated")) {
363                     annotationDeprecated = true;
364                     break;
365                 }
366             }
367 
368             if (commentDeprecated != annotationDeprecated) {
369                 Errors.error(Errors.DEPRECATION_MISMATCH, position(),
370                         "Class " + qualifiedName()
371                         + ": @Deprecated annotation and @deprecated comment do not match");
372             }
373 
374             mIsDeprecated = commentDeprecated | annotationDeprecated;
375             mDeprecatedKnown = true;
376         }
377         return mIsDeprecated;
378     }
379 
deprecatedTags()380     public TagInfo[] deprecatedTags()
381     {
382         // Should we also do the interfaces?
383         return comment().deprecatedTags();
384     }
385 
methods()386     public MethodInfo[] methods()
387     {
388         if (mMethods == null) {
389             TreeMap<String,MethodInfo> all = new TreeMap<String,MethodInfo>();
390 
391             ClassInfo[] ifaces = interfaces();
392             for (ClassInfo iface: ifaces) {
393                 if (iface != null) {
394                     MethodInfo[] inhereted = iface.methods();
395                     for (MethodInfo method: inhereted) {
396                         String key = method.name() + method.signature();
397                         all.put(key, method);
398                     }
399                 }
400             }
401 
402             ClassInfo superclass = superclass();
403             if (superclass != null) {
404                 MethodInfo[] inhereted = superclass.methods();
405                 for (MethodInfo method: inhereted) {
406                     String key = method.name() + method.signature();
407                     all.put(key, method);
408                 }
409             }
410 
411             MethodInfo[] methods = selfMethods();
412             for (MethodInfo method: methods) {
413                 String key = method.name() + method.signature();
414                 MethodInfo old = all.put(key, method);
415             }
416 
417             mMethods = all.values().toArray(new MethodInfo[all.size()]);
418         }
419         return mMethods;
420     }
421 
annotationElements()422     public MethodInfo[] annotationElements()
423     {
424         return mAnnotationElements;
425     }
426 
annotations()427     public AnnotationInstanceInfo[] annotations()
428     {
429         return mAnnotations;
430     }
431 
addFields(ClassInfo cl, TreeMap<String,FieldInfo> all)432     private static void addFields(ClassInfo cl, TreeMap<String,FieldInfo> all)
433     {
434         FieldInfo[] fields = cl.fields();
435         int N = fields.length;
436         for (int i=0; i<N; i++) {
437             FieldInfo f = fields[i];
438             all.put(f.name(), f);
439         }
440     }
441 
fields()442     public FieldInfo[] fields()
443     {
444         if (mFields == null) {
445             int N;
446             TreeMap<String,FieldInfo> all = new TreeMap<String,FieldInfo>();
447 
448             ClassInfo[] interfaces = interfaces();
449             N = interfaces.length;
450             for (int i=0; i<N; i++) {
451                 addFields(interfaces[i], all);
452             }
453 
454             ClassInfo superclass = superclass();
455             if (superclass != null) {
456                 addFields(superclass, all);
457             }
458 
459             FieldInfo[] fields = selfFields();
460             N = fields.length;
461             for (int i=0; i<N; i++) {
462                 FieldInfo f = fields[i];
463                 if (!f.isHidden()) {
464                     String key = f.name();
465                     all.put(key, f);
466                 }
467             }
468 
469             mFields = all.values().toArray(new FieldInfo[0]);
470         }
471         return mFields;
472     }
473 
gatherFields(ClassInfo owner, ClassInfo cl, HashMap<String,FieldInfo> fields)474     public void gatherFields(ClassInfo owner, ClassInfo cl, HashMap<String,FieldInfo> fields) {
475         FieldInfo[] flds = cl.selfFields();
476         for (FieldInfo f: flds) {
477             if (f.checkLevel()) {
478                 fields.put(f.name(), f.cloneForClass(owner));
479             }
480         }
481     }
482 
selfFields()483     public FieldInfo[] selfFields()
484     {
485         if (mSelfFields == null) {
486             HashMap<String,FieldInfo> fields = new HashMap<String,FieldInfo>();
487             // our hidden parents
488             if (mRealSuperclass != null && !mRealSuperclass.checkLevel()) {
489                 gatherFields(this, mRealSuperclass, fields);
490             }
491             for (ClassInfo iface: mRealInterfaces) {
492                 if (!iface.checkLevel()) {
493                     gatherFields(this, iface, fields);
494                 }
495             }
496             // mine
497             FieldInfo[] selfFields = mAllSelfFields;
498             for (int i=0; i<selfFields.length; i++) {
499                 FieldInfo f = selfFields[i];
500                 if (!f.isHidden()) {
501                     fields.put(f.name(), f);
502                 }
503             }
504             // combine and return in
505             mSelfFields = fields.values().toArray(new FieldInfo[fields.size()]);
506             Arrays.sort(mSelfFields, FieldInfo.comparator);
507         }
508         return mSelfFields;
509     }
510 
allSelfFields()511     public FieldInfo[] allSelfFields() {
512         return mAllSelfFields;
513     }
514 
gatherMethods(ClassInfo owner, ClassInfo cl, HashMap<String,MethodInfo> methods)515     public void gatherMethods(ClassInfo owner, ClassInfo cl, HashMap<String,MethodInfo> methods) {
516         MethodInfo[] meth = cl.selfMethods();
517         for (MethodInfo m: meth) {
518             if (m.checkLevel()) {
519                 methods.put(m.name()+m.signature(), m.cloneForClass(owner));
520             }
521         }
522     }
523 
selfMethods()524     public MethodInfo[] selfMethods()
525     {
526         if (mSelfMethods == null) {
527             HashMap<String,MethodInfo> methods = new HashMap<String,MethodInfo>();
528             // our hidden parents
529             if (mRealSuperclass != null && !mRealSuperclass.checkLevel()) {
530                 gatherMethods(this, mRealSuperclass, methods);
531             }
532             for (ClassInfo iface: mRealInterfaces) {
533                 if (!iface.checkLevel()) {
534                     gatherMethods(this, iface, methods);
535                 }
536             }
537             // mine
538             MethodInfo[] selfMethods = mAllSelfMethods;
539             for (int i=0; i<selfMethods.length; i++) {
540                 MethodInfo m = selfMethods[i];
541                 if (m.checkLevel()) {
542                     methods.put(m.name()+m.signature(), m);
543                 }
544             }
545             // combine and return it
546             mSelfMethods = methods.values().toArray(new MethodInfo[methods.size()]);
547             Arrays.sort(mSelfMethods, MethodInfo.comparator);
548         }
549         return mSelfMethods;
550     }
551 
allSelfMethods()552     public MethodInfo[] allSelfMethods() {
553         return mAllSelfMethods;
554     }
555 
addMethod(MethodInfo method)556     public void addMethod(MethodInfo method) {
557         MethodInfo[] methods = new MethodInfo[mAllSelfMethods.length + 1];
558         int i = 0;
559         for (MethodInfo m : mAllSelfMethods) {
560             methods[i] = m;
561             i++;
562         }
563         methods[i] = method;
564         mAllSelfMethods = methods;
565     }
566 
selfAttributes()567     public AttributeInfo[] selfAttributes()
568     {
569         if (mSelfAttributes == null) {
570             TreeMap<FieldInfo,AttributeInfo> attrs = new TreeMap<FieldInfo,AttributeInfo>();
571 
572             // the ones in the class comment won't have any methods
573             for (AttrTagInfo tag: comment().attrTags()) {
574                 FieldInfo field = tag.reference();
575                 if (field != null) {
576                     AttributeInfo attr = attrs.get(field);
577                     if (attr == null) {
578                         attr = new AttributeInfo(this, field);
579                         attrs.put(field, attr);
580                     }
581                     tag.setAttribute(attr);
582                 }
583             }
584 
585             // in the methods
586             for (MethodInfo m: selfMethods()) {
587                 for (AttrTagInfo tag: m.comment().attrTags()) {
588                     FieldInfo field = tag.reference();
589                     if (field != null) {
590                         AttributeInfo attr = attrs.get(field);
591                         if (attr == null) {
592                             attr = new AttributeInfo(this, field);
593                             attrs.put(field, attr);
594                         }
595                         tag.setAttribute(attr);
596                         attr.methods.add(m);
597                     }
598                 }
599             }
600 
601             //constructors too
602            for (MethodInfo m: constructors()) {
603               for (AttrTagInfo tag: m.comment().attrTags()) {
604                   FieldInfo field = tag.reference();
605                   if (field != null) {
606                       AttributeInfo attr = attrs.get(field);
607                       if (attr == null) {
608                           attr = new AttributeInfo(this, field);
609                           attrs.put(field, attr);
610                       }
611                       tag.setAttribute(attr);
612                       attr.methods.add(m);
613                   }
614               }
615           }
616 
617             mSelfAttributes = attrs.values().toArray(new AttributeInfo[attrs.size()]);
618             Arrays.sort(mSelfAttributes, AttributeInfo.comparator);
619         }
620         return mSelfAttributes;
621     }
622 
enumConstants()623     public FieldInfo[] enumConstants()
624     {
625         return mEnumConstants;
626     }
627 
superclass()628     public ClassInfo superclass()
629     {
630         if (!mSuperclassInit) {
631             if (this.checkLevel()) {
632                 // rearrange our little inheritance hierarchy, because we need to hide classes that
633                 // don't pass checkLevel
634                 ClassInfo superclass = mRealSuperclass;
635                 while (superclass != null && !superclass.checkLevel()) {
636                     superclass = superclass.mRealSuperclass;
637                 }
638                 mSuperclass = superclass;
639             } else {
640                 mSuperclass = mRealSuperclass;
641             }
642         }
643         return mSuperclass;
644     }
645 
realSuperclass()646     public ClassInfo realSuperclass()
647     {
648         return mRealSuperclass;
649     }
650 
651     /** always the real superclass, not the collapsed one we get through superclass(),
652      * also has the type parameter info if it's generic.
653      */
superclassType()654     public TypeInfo superclassType()
655     {
656         return mRealSuperclassType;
657     }
658 
asTypeInfo()659     public TypeInfo asTypeInfo()
660     {
661         return mTypeInfo;
662     }
663 
interfaceTypes()664     TypeInfo[] interfaceTypes()
665     {
666         ClassInfo[] infos = interfaces();
667         int len = infos.length;
668         TypeInfo[] types = new TypeInfo[len];
669         for (int i=0; i<len; i++) {
670             types[i] = infos[i].asTypeInfo();
671         }
672         return types;
673     }
674 
htmlPage()675     public String htmlPage()
676     {
677         String s = containingPackage().name();
678         s = s.replace('.', '/');
679         s += '/';
680         s += name();
681         s += ".html";
682         s = DroidDoc.javadocDir + s;
683         return s;
684     }
685 
686     /** Even indirectly */
isDerivedFrom(ClassInfo cl)687     public boolean isDerivedFrom(ClassInfo cl)
688     {
689         ClassInfo dad = this.superclass();
690         if (dad != null) {
691             if (dad.equals(cl)) {
692                 return true;
693             } else {
694                 if (dad.isDerivedFrom(cl)) {
695                     return true;
696                 }
697             }
698         }
699         for (ClassInfo iface: interfaces()) {
700             if (iface.equals(cl)) {
701                 return true;
702             } else {
703                 if (iface.isDerivedFrom(cl)) {
704                     return true;
705                 }
706             }
707         }
708         return false;
709     }
710 
makeKeywordEntries(List<KeywordEntry> keywords)711     public void makeKeywordEntries(List<KeywordEntry> keywords)
712     {
713         if (!checkLevel()) {
714             return;
715         }
716 
717         String htmlPage = htmlPage();
718         String qualifiedName = qualifiedName();
719 
720         keywords.add(new KeywordEntry(name(), htmlPage,
721                 "class in " + containingPackage().name()));
722 
723         FieldInfo[] fields = selfFields();
724         FieldInfo[] enumConstants = enumConstants();
725         MethodInfo[] ctors = constructors();
726         MethodInfo[] methods = selfMethods();
727 
728         // enum constants
729         for (FieldInfo field: enumConstants()) {
730             if (field.checkLevel()) {
731                 keywords.add(new KeywordEntry(field.name(),
732                             htmlPage + "#" + field.anchor(),
733                             "enum constant in " + qualifiedName));
734             }
735         }
736 
737         // constants
738         for (FieldInfo field: fields) {
739             if (field.isConstant() && field.checkLevel()) {
740                 keywords.add(new KeywordEntry(field.name(),
741                             htmlPage + "#" + field.anchor(),
742                             "constant in " + qualifiedName));
743             }
744         }
745 
746         // fields
747         for (FieldInfo field: fields) {
748             if (!field.isConstant() && field.checkLevel()) {
749                 keywords.add(new KeywordEntry(field.name(),
750                             htmlPage + "#" + field.anchor(),
751                             "field in " + qualifiedName));
752             }
753         }
754 
755         // public constructors
756         for (MethodInfo m: ctors) {
757             if (m.isPublic() && m.checkLevel()) {
758                 keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
759                             htmlPage + "#" + m.anchor(),
760                             "constructor in " + qualifiedName));
761             }
762         }
763 
764         // protected constructors
765         if (DroidDoc.checkLevel(DroidDoc.SHOW_PROTECTED)) {
766             for (MethodInfo m: ctors) {
767                 if (m.isProtected() && m.checkLevel()) {
768                     keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
769                                 htmlPage + "#" + m.anchor(),
770                                 "constructor in " + qualifiedName));
771                 }
772             }
773         }
774 
775         // package private constructors
776         if (DroidDoc.checkLevel(DroidDoc.SHOW_PACKAGE)) {
777             for (MethodInfo m: ctors) {
778                 if (m.isPackagePrivate() && m.checkLevel()) {
779                     keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
780                                 htmlPage + "#" + m.anchor(),
781                                 "constructor in " + qualifiedName));
782                 }
783             }
784         }
785 
786         // private constructors
787         if (DroidDoc.checkLevel(DroidDoc.SHOW_PRIVATE)) {
788             for (MethodInfo m: ctors) {
789                 if (m.isPrivate() && m.checkLevel()) {
790                     keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
791                                 htmlPage + "#" + m.anchor(),
792                                 "constructor in " + qualifiedName));
793                 }
794             }
795         }
796 
797         // public methods
798         for (MethodInfo m: methods) {
799             if (m.isPublic() && m.checkLevel()) {
800                 keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
801                             htmlPage + "#" + m.anchor(),
802                             "method in " + qualifiedName));
803             }
804         }
805 
806         // protected methods
807         if (DroidDoc.checkLevel(DroidDoc.SHOW_PROTECTED)) {
808             for (MethodInfo m: methods) {
809                 if (m.isProtected() && m.checkLevel()) {
810                     keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
811                                 htmlPage + "#" + m.anchor(),
812                                 "method in " + qualifiedName));
813                 }
814             }
815         }
816 
817         // package private methods
818         if (DroidDoc.checkLevel(DroidDoc.SHOW_PACKAGE)) {
819             for (MethodInfo m: methods) {
820                 if (m.isPackagePrivate() && m.checkLevel()) {
821                     keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
822                                 htmlPage + "#" + m.anchor(),
823                                 "method in " + qualifiedName));
824                 }
825             }
826         }
827 
828         // private methods
829         if (DroidDoc.checkLevel(DroidDoc.SHOW_PRIVATE)) {
830             for (MethodInfo m: methods) {
831                 if (m.isPrivate() && m.checkLevel()) {
832                     keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
833                                 htmlPage + "#" + m.anchor(),
834                                 "method in " + qualifiedName));
835                 }
836             }
837         }
838     }
839 
makeLink(HDF data, String base)840     public void makeLink(HDF data, String base)
841     {
842         data.setValue(base + ".label", this.name());
843         if (!this.isPrimitive() && this.isIncluded() && this.checkLevel()) {
844             data.setValue(base + ".link", this.htmlPage());
845         }
846     }
847 
makeLinkListHDF(HDF data, String base, ClassInfo[] classes)848     public static void makeLinkListHDF(HDF data, String base, ClassInfo[] classes) {
849         final int N = classes.length;
850         for (int i=0; i<N; i++) {
851             ClassInfo cl = classes[i];
852             if (cl.checkLevel()) {
853                 cl.asTypeInfo().makeHDF(data, base + "." + i);
854             }
855         }
856     }
857 
858     /**
859      * Used in lists of this class (packages, nested classes, known subclasses)
860      */
makeShortDescrHDF(HDF data, String base)861     public void makeShortDescrHDF(HDF data, String base)
862     {
863         mTypeInfo.makeHDF(data, base + ".type");
864         data.setValue(base + ".kind", this.kind());
865         TagInfo.makeHDF(data, base + ".shortDescr", this.firstSentenceTags());
866         TagInfo.makeHDF(data, base + ".deprecated", deprecatedTags());
867         data.setValue(base + ".since", getSince());
868     }
869 
870     /**
871      * Turns into the main class page
872      */
makeHDF(HDF data)873     public void makeHDF(HDF data)
874     {
875         int i, j, n;
876         String name = name();
877         String qualified = qualifiedName();
878         AttributeInfo[] selfAttributes = selfAttributes();
879         MethodInfo[] methods = selfMethods();
880         FieldInfo[] fields = selfFields();
881         FieldInfo[] enumConstants = enumConstants();
882         MethodInfo[] ctors = constructors();
883         ClassInfo[] inners = innerClasses();
884 
885         // class name
886         mTypeInfo.makeHDF(data, "class.type");
887         mTypeInfo.makeQualifiedHDF(data, "class.qualifiedType");
888         data.setValue("class.name", name);
889         data.setValue("class.qualified", qualified);
890         String scope = "";
891         if (isProtected()) {
892             data.setValue("class.scope", "protected");
893         }
894         else if (isPublic()) {
895             data.setValue("class.scope", "public");
896         }
897         if (isStatic()) {
898             data.setValue("class.static", "static");
899         }
900         if (isFinal()) {
901             data.setValue("class.final", "final");
902         }
903         if (isAbstract() && !isInterface()) {
904             data.setValue("class.abstract", "abstract");
905         }
906 
907         // class info
908         String kind = kind();
909         if (kind != null) {
910             data.setValue("class.kind", kind);
911         }
912         data.setValue("class.since", getSince());
913 
914         // the containing package -- note that this can be passed to type_link,
915         // but it also contains the list of all of the packages
916         containingPackage().makeClassLinkListHDF(data, "class.package");
917 
918         // inheritance hierarchy
919         Vector<ClassInfo> superClasses = new Vector<ClassInfo>();
920         superClasses.add(this);
921         ClassInfo supr = superclass();
922         while (supr != null) {
923             superClasses.add(supr);
924             supr = supr.superclass();
925         }
926         n = superClasses.size();
927         for (i=0; i<n; i++) {
928             supr = superClasses.elementAt(n-i-1);
929 
930             supr.asTypeInfo().makeQualifiedHDF(data, "class.inheritance." + i + ".class");
931             supr.asTypeInfo().makeHDF(data, "class.inheritance." + i + ".short_class");
932             j = 0;
933             for (TypeInfo t: supr.interfaceTypes()) {
934                 t.makeHDF(data, "class.inheritance." + i + ".interfaces." + j);
935                 j++;
936             }
937         }
938 
939         // class description
940         TagInfo.makeHDF(data, "class.descr", inlineTags());
941         TagInfo.makeHDF(data, "class.seeAlso", comment().seeTags());
942         TagInfo.makeHDF(data, "class.deprecated", deprecatedTags());
943 
944         // known subclasses
945         TreeMap<String, ClassInfo> direct = new TreeMap<String, ClassInfo>();
946         TreeMap<String, ClassInfo> indirect = new TreeMap<String, ClassInfo>();
947         ClassInfo[] all = Converter.rootClasses();
948         for (ClassInfo cl: all) {
949             if (cl.superclass() != null && cl.superclass().equals(this)) {
950                 direct.put(cl.name(), cl);
951             }
952             else if (cl.isDerivedFrom(this)) {
953                 indirect.put(cl.name(), cl);
954             }
955         }
956         // direct
957         i = 0;
958         for (ClassInfo cl: direct.values()) {
959             if (cl.checkLevel()) {
960                 cl.makeShortDescrHDF(data, "class.subclasses.direct." + i);
961             }
962             i++;
963         }
964         // indirect
965         i = 0;
966         for (ClassInfo cl: indirect.values()) {
967             if (cl.checkLevel()) {
968                 cl.makeShortDescrHDF(data, "class.subclasses.indirect." + i);
969             }
970             i++;
971         }
972 
973         // nested classes
974         i=0;
975         for (ClassInfo inner: inners) {
976             if (inner.checkLevel()) {
977                 inner.makeShortDescrHDF(data, "class.inners." + i);
978             }
979             i++;
980         }
981 
982         // enum constants
983         i=0;
984         for (FieldInfo field: enumConstants) {
985             if (field.isConstant()) {
986                 field.makeHDF(data, "class.enumConstants." + i);
987                 i++;
988             }
989         }
990 
991         // constants
992         i=0;
993         for (FieldInfo field: fields) {
994             if (field.isConstant()) {
995                 field.makeHDF(data, "class.constants." + i);
996                 i++;
997             }
998         }
999 
1000         // fields
1001         i=0;
1002         for (FieldInfo field: fields) {
1003             if (!field.isConstant()) {
1004                 field.makeHDF(data, "class.fields." + i);
1005                 i++;
1006             }
1007         }
1008 
1009         // public constructors
1010         i=0;
1011         for (MethodInfo ctor: ctors) {
1012             if (ctor.isPublic()) {
1013                 ctor.makeHDF(data, "class.ctors.public." + i);
1014                 i++;
1015             }
1016         }
1017 
1018         // protected constructors
1019         if (DroidDoc.checkLevel(DroidDoc.SHOW_PROTECTED)) {
1020             i=0;
1021             for (MethodInfo ctor: ctors) {
1022                 if (ctor.isProtected()) {
1023                     ctor.makeHDF(data, "class.ctors.protected." + i);
1024                     i++;
1025                 }
1026             }
1027         }
1028 
1029         // package private constructors
1030         if (DroidDoc.checkLevel(DroidDoc.SHOW_PACKAGE)) {
1031             i=0;
1032             for (MethodInfo ctor: ctors) {
1033                 if (ctor.isPackagePrivate()) {
1034                     ctor.makeHDF(data, "class.ctors.package." + i);
1035                     i++;
1036                 }
1037             }
1038         }
1039 
1040         // private constructors
1041         if (DroidDoc.checkLevel(DroidDoc.SHOW_PRIVATE)) {
1042             i=0;
1043             for (MethodInfo ctor: ctors) {
1044                 if (ctor.isPrivate()) {
1045                     ctor.makeHDF(data, "class.ctors.private." + i);
1046                     i++;
1047                 }
1048             }
1049         }
1050 
1051         // public methods
1052         i=0;
1053         for (MethodInfo method: methods) {
1054             if (method.isPublic()) {
1055                 method.makeHDF(data, "class.methods.public." + i);
1056                 i++;
1057             }
1058         }
1059 
1060         // protected methods
1061         if (DroidDoc.checkLevel(DroidDoc.SHOW_PROTECTED)) {
1062             i=0;
1063             for (MethodInfo method: methods) {
1064                 if (method.isProtected()) {
1065                     method.makeHDF(data, "class.methods.protected." + i);
1066                     i++;
1067                 }
1068             }
1069         }
1070 
1071         // package private methods
1072         if (DroidDoc.checkLevel(DroidDoc.SHOW_PACKAGE)) {
1073             i=0;
1074             for (MethodInfo method: methods) {
1075                 if (method.isPackagePrivate()) {
1076                     method.makeHDF(data, "class.methods.package." + i);
1077                     i++;
1078                 }
1079             }
1080         }
1081 
1082         // private methods
1083         if (DroidDoc.checkLevel(DroidDoc.SHOW_PRIVATE)) {
1084             i=0;
1085             for (MethodInfo method: methods) {
1086                 if (method.isPrivate()) {
1087                     method.makeHDF(data, "class.methods.private." + i);
1088                     i++;
1089                 }
1090             }
1091         }
1092 
1093         // xml attributes
1094         i=0;
1095         for (AttributeInfo attr: selfAttributes) {
1096             if (attr.checkLevel()) {
1097                 attr.makeHDF(data, "class.attrs." + i);
1098                 i++;
1099             }
1100         }
1101 
1102         // inherited methods
1103         Set<ClassInfo> interfaces = new TreeSet<ClassInfo>();
1104         addInterfaces(interfaces(), interfaces);
1105         ClassInfo cl = superclass();
1106         i=0;
1107         while (cl != null) {
1108             addInterfaces(cl.interfaces(), interfaces);
1109             makeInheritedHDF(data, i, cl);
1110             cl = cl.superclass();
1111             i++;
1112         }
1113         for (ClassInfo iface: interfaces) {
1114             makeInheritedHDF(data, i, iface);
1115             i++;
1116         }
1117     }
1118 
addInterfaces(ClassInfo[] ifaces, Set<ClassInfo> out)1119     private static void addInterfaces(ClassInfo[] ifaces, Set<ClassInfo> out)
1120     {
1121         for (ClassInfo cl: ifaces) {
1122             out.add(cl);
1123             addInterfaces(cl.interfaces(), out);
1124         }
1125     }
1126 
makeInheritedHDF(HDF data, int index, ClassInfo cl)1127     private static void makeInheritedHDF(HDF data, int index, ClassInfo cl)
1128     {
1129         int i;
1130 
1131         String base = "class.inherited." + index;
1132         data.setValue(base + ".qualified", cl.qualifiedName());
1133         if (cl.checkLevel()) {
1134             data.setValue(base + ".link", cl.htmlPage());
1135         }
1136         String kind = cl.kind();
1137         if (kind != null) {
1138             data.setValue(base + ".kind", kind);
1139         }
1140 
1141         if (cl.mIsIncluded) {
1142             data.setValue(base + ".included", "true");
1143         }
1144 
1145         // xml attributes
1146         i=0;
1147         for (AttributeInfo attr: cl.selfAttributes()) {
1148             attr.makeHDF(data, base + ".attrs." + i);
1149             i++;
1150         }
1151 
1152         // methods
1153         i=0;
1154         for (MethodInfo method: cl.selfMethods()) {
1155             method.makeHDF(data, base + ".methods." + i);
1156             i++;
1157         }
1158 
1159         // fields
1160         i=0;
1161         for (FieldInfo field: cl.selfFields()) {
1162             if (!field.isConstant()) {
1163                 field.makeHDF(data, base + ".fields." + i);
1164                 i++;
1165             }
1166         }
1167 
1168         // constants
1169         i=0;
1170         for (FieldInfo field: cl.selfFields()) {
1171             if (field.isConstant()) {
1172                 field.makeHDF(data, base + ".constants." + i);
1173                 i++;
1174             }
1175         }
1176     }
1177 
1178     @Override
isHidden()1179     public boolean isHidden()
1180     {
1181         int val = mHidden;
1182         if (val >= 0) {
1183             return val != 0;
1184         } else {
1185             boolean v = isHiddenImpl();
1186             mHidden = v ? 1 : 0;
1187             return v;
1188         }
1189     }
1190 
isHiddenImpl()1191     public boolean isHiddenImpl()
1192     {
1193         ClassInfo cl = this;
1194         while (cl != null) {
1195             PackageInfo pkg = cl.containingPackage();
1196             if (pkg != null && pkg.isHidden()) {
1197                 return true;
1198             }
1199             if (cl.comment().isHidden()) {
1200                 return true;
1201             }
1202             cl = cl.containingClass();
1203         }
1204         return false;
1205     }
1206 
matchMethod(MethodInfo[] methods, String name, String[] params, String[] dimensions)1207     private MethodInfo matchMethod(MethodInfo[] methods, String name,
1208                                     String[] params, String[] dimensions)
1209     {
1210         int len = methods.length;
1211         for (int i=0; i<len; i++) {
1212             MethodInfo method = methods[i];
1213             if (method.name().equals(name)) {
1214                 if (params == null) {
1215                     return method;
1216                 } else {
1217                     if (method.matchesParams(params, dimensions)) {
1218                         return method;
1219                     }
1220                 }
1221             }
1222         }
1223         return null;
1224     }
1225 
findMethod(String name, String[] params, String[] dimensions)1226     public MethodInfo findMethod(String name,
1227                                     String[] params, String[] dimensions)
1228     {
1229         // first look on our class, and our superclasses
1230 
1231         // for methods
1232         MethodInfo rv;
1233         rv = matchMethod(methods(), name, params, dimensions);
1234 
1235         if (rv != null) {
1236             return rv;
1237         }
1238 
1239         // for constructors
1240         rv = matchMethod(constructors(), name, params, dimensions);
1241         if (rv != null) {
1242             return rv;
1243         }
1244 
1245         // then recursively look at our containing class
1246         ClassInfo containing = containingClass();
1247         if (containing != null) {
1248             return containing.findMethod(name, params, dimensions);
1249         }
1250 
1251         return null;
1252     }
1253 
searchInnerClasses(String[] nameParts, int index)1254     private ClassInfo searchInnerClasses(String[] nameParts, int index)
1255     {
1256         String part = nameParts[index];
1257 
1258         ClassInfo[] inners = mInnerClasses;
1259         for (ClassInfo in: inners) {
1260             String[] innerParts = in.nameParts();
1261             if (part.equals(innerParts[innerParts.length-1])) {
1262                 if (index == nameParts.length-1) {
1263                     return in;
1264                 } else {
1265                     return in.searchInnerClasses(nameParts, index+1);
1266                 }
1267             }
1268         }
1269         return null;
1270     }
1271 
extendedFindClass(String className)1272     public ClassInfo extendedFindClass(String className)
1273     {
1274         // ClassDoc.findClass has this bug that we're working around here:
1275         // If you have a class PackageManager with an inner class PackageInfo
1276         // and you call it with "PackageInfo" it doesn't find it.
1277         return searchInnerClasses(className.split("\\."), 0);
1278     }
1279 
findClass(String className)1280     public ClassInfo findClass(String className)
1281     {
1282         return Converter.obtainClass(mClass.findClass(className));
1283     }
1284 
findInnerClass(String className)1285     public ClassInfo findInnerClass(String className)
1286     {
1287         // ClassDoc.findClass won't find inner classes.  To deal with that,
1288         // we try what they gave us first, but if that didn't work, then
1289         // we see if there are any periods in className, and start searching
1290         // from there.
1291         String[] nodes = className.split("\\.");
1292         ClassDoc cl = mClass;
1293         for (String n: nodes) {
1294             cl = cl.findClass(n);
1295             if (cl == null) {
1296                 return null;
1297             }
1298         }
1299         return Converter.obtainClass(cl);
1300     }
1301 
findField(String name)1302     public FieldInfo findField(String name)
1303     {
1304         // first look on our class, and our superclasses
1305         for (FieldInfo f: fields()) {
1306             if (f.name().equals(name)) {
1307                 return f;
1308             }
1309         }
1310 
1311         // then look at our enum constants (these are really fields, maybe
1312         // they should be mixed into fields().  not sure)
1313         for (FieldInfo f: enumConstants()) {
1314             if (f.name().equals(name)) {
1315                 return f;
1316             }
1317         }
1318 
1319         // then recursively look at our containing class
1320         ClassInfo containing = containingClass();
1321         if (containing != null) {
1322             return containing.findField(name);
1323         }
1324 
1325         return null;
1326     }
1327 
sortByName(ClassInfo[] classes)1328     public static ClassInfo[] sortByName(ClassInfo[] classes)
1329     {
1330         int i;
1331         Sorter[] sorted = new Sorter[classes.length];
1332         for (i=0; i<sorted.length; i++) {
1333             ClassInfo cl = classes[i];
1334             sorted[i] = new Sorter(cl.name(), cl);
1335         }
1336 
1337         Arrays.sort(sorted);
1338 
1339         ClassInfo[] rv = new ClassInfo[classes.length];
1340         for (i=0; i<rv.length; i++) {
1341             rv[i] = (ClassInfo)sorted[i].data;
1342         }
1343 
1344         return rv;
1345     }
1346 
equals(ClassInfo that)1347     public boolean equals(ClassInfo that)
1348     {
1349         if (that != null) {
1350             return this.qualifiedName().equals(that.qualifiedName());
1351         } else {
1352             return false;
1353         }
1354     }
1355 
setNonWrittenConstructors(MethodInfo[] nonWritten)1356     public void setNonWrittenConstructors(MethodInfo[] nonWritten) {
1357         mNonWrittenConstructors = nonWritten;
1358     }
1359 
getNonWrittenConstructors()1360     public MethodInfo[] getNonWrittenConstructors() {
1361         return mNonWrittenConstructors;
1362     }
1363 
kind()1364     public String kind()
1365     {
1366         if (isOrdinaryClass()) {
1367             return "class";
1368         }
1369         else if (isInterface()) {
1370             return "interface";
1371         }
1372         else if (isEnum()) {
1373             return "enum";
1374         }
1375         else if (isError()) {
1376             return "class";
1377         }
1378         else if (isException()) {
1379             return "class";
1380         }
1381         else if (isAnnotation()) {
1382             return "@interface";
1383         }
1384         return null;
1385     }
1386 
setHiddenMethods(MethodInfo[] mInfo)1387     public void setHiddenMethods(MethodInfo[] mInfo){
1388         mHiddenMethods = mInfo;
1389     }
getHiddenMethods()1390     public MethodInfo[] getHiddenMethods(){
1391         return mHiddenMethods;
1392     }
1393     @Override
toString()1394     public String toString(){
1395         return this.qualifiedName();
1396     }
1397 
setReasonIncluded(String reason)1398     public void setReasonIncluded(String reason) {
1399         mReasonIncluded = reason;
1400     }
1401 
getReasonIncluded()1402     public String getReasonIncluded() {
1403         return mReasonIncluded;
1404     }
1405 
1406     private ClassDoc mClass;
1407 
1408     // ctor
1409     private boolean mIsPublic;
1410     private boolean mIsProtected;
1411     private boolean mIsPackagePrivate;
1412     private boolean mIsPrivate;
1413     private boolean mIsStatic;
1414     private boolean mIsInterface;
1415     private boolean mIsAbstract;
1416     private boolean mIsOrdinaryClass;
1417     private boolean mIsException;
1418     private boolean mIsError;
1419     private boolean mIsEnum;
1420     private boolean mIsAnnotation;
1421     private boolean mIsFinal;
1422     private boolean mIsIncluded;
1423     private String mName;
1424     private String mQualifiedName;
1425     private String mQualifiedTypeName;
1426     private boolean mIsPrimitive;
1427     private TypeInfo mTypeInfo;
1428     private String[] mNameParts;
1429 
1430     // init
1431     private ClassInfo[] mRealInterfaces;
1432     private ClassInfo[] mInterfaces;
1433     private TypeInfo[] mRealInterfaceTypes;
1434     private ClassInfo[] mInnerClasses;
1435     private MethodInfo[] mAllConstructors;
1436     private MethodInfo[] mAllSelfMethods;
1437     private MethodInfo[] mAnnotationElements; // if this class is an annotation
1438     private FieldInfo[] mAllSelfFields;
1439     private FieldInfo[] mEnumConstants;
1440     private PackageInfo mContainingPackage;
1441     private ClassInfo mContainingClass;
1442     private ClassInfo mRealSuperclass;
1443     private TypeInfo mRealSuperclassType;
1444     private ClassInfo mSuperclass;
1445     private AnnotationInstanceInfo[] mAnnotations;
1446     private boolean mSuperclassInit;
1447     private boolean mDeprecatedKnown;
1448 
1449     // lazy
1450     private MethodInfo[] mConstructors;
1451     private ClassInfo[] mRealInnerClasses;
1452     private MethodInfo[] mSelfMethods;
1453     private FieldInfo[] mSelfFields;
1454     private AttributeInfo[] mSelfAttributes;
1455     private MethodInfo[] mMethods;
1456     private FieldInfo[] mFields;
1457     private TypeInfo[] mTypeParameters;
1458     private MethodInfo[] mHiddenMethods;
1459     private int mHidden = -1;
1460     private int mCheckLevel = -1;
1461     private String mReasonIncluded;
1462     private MethodInfo[] mNonWrittenConstructors;
1463     private boolean mIsDeprecated;
1464 }
1465