summaryrefslogtreecommitdiffstats
path: root/tools/droiddoc/src/ClassInfo.java
diff options
context:
space:
mode:
Diffstat (limited to 'tools/droiddoc/src/ClassInfo.java')
-rw-r--r--tools/droiddoc/src/ClassInfo.java1463
1 files changed, 1463 insertions, 0 deletions
diff --git a/tools/droiddoc/src/ClassInfo.java b/tools/droiddoc/src/ClassInfo.java
new file mode 100644
index 0000000..36edbf8
--- /dev/null
+++ b/tools/droiddoc/src/ClassInfo.java
@@ -0,0 +1,1463 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import com.sun.javadoc.*;
+import com.sun.tools.doclets.*;
+import org.clearsilver.HDF;
+import org.clearsilver.CS;
+import java.util.*;
+import java.io.*;
+
+public class ClassInfo extends DocInfo implements ContainerInfo, Comparable, Scoped
+{
+ public static final Comparator<ClassInfo> comparator = new Comparator<ClassInfo>() {
+ public int compare(ClassInfo a, ClassInfo b) {
+ return a.name().compareTo(b.name());
+ }
+ };
+
+ public static final Comparator<ClassInfo> qualifiedComparator = new Comparator<ClassInfo>() {
+ public int compare(ClassInfo a, ClassInfo b) {
+ return a.qualifiedName().compareTo(b.qualifiedName());
+ }
+ };
+
+ public 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)
+ {
+ super(rawCommentText, position);
+
+ mClass = cl;
+ mIsPublic = isPublic;
+ mIsProtected = isProtected;
+ mIsPackagePrivate = isPackagePrivate;
+ mIsPrivate = isPrivate;
+ mIsStatic = isStatic;
+ mIsInterface = isInterface;
+ mIsAbstract = isAbstract;
+ mIsOrdinaryClass = isOrdinaryClass;
+ mIsException = isException;
+ mIsError = isError;
+ mIsEnum = isEnum;
+ mIsAnnotation = isAnnotation;
+ mIsFinal = isFinal;
+ mIsIncluded = isIncluded;
+ mName = name;
+ mQualifiedName = qualifiedName;
+ mQualifiedTypeName = qualifiedTypeName;
+ mIsPrimitive = isPrimitive;
+ mNameParts = name.split("\\.");
+ }
+
+ public void 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)
+ {
+ mTypeInfo = typeInfo;
+ mRealInterfaces = interfaces;
+ mRealInterfaceTypes = interfaceTypes;
+ mInnerClasses = innerClasses;
+ mAllConstructors = constructors;
+ mAllSelfMethods = methods;
+ mAnnotationElements = annotationElements;
+ mAllSelfFields = fields;
+ mEnumConstants = enumConstants;
+ mContainingPackage = containingPackage;
+ mContainingClass = containingClass;
+ mRealSuperclass = superclass;
+ mRealSuperclassType = superclassType;
+ mAnnotations = annotations;
+
+ // after providing new methods and new superclass info,clear any cached
+ // lists of self + superclass methods, ctors, etc.
+ mSuperclassInit = false;
+ mConstructors = null;
+ mMethods = null;
+ mSelfMethods = null;
+ mFields = null;
+ mSelfFields = null;
+ mSelfAttributes = null;
+ mDeprecatedKnown = false;
+
+ Arrays.sort(mEnumConstants, FieldInfo.comparator);
+ Arrays.sort(mInnerClasses, ClassInfo.comparator);
+ }
+
+ public void init2() {
+ // calling this here forces the AttrTagInfo objects to be linked to the AttribtueInfo
+ // objects
+ selfAttributes();
+ }
+
+ public void init3(TypeInfo[] types, ClassInfo[] realInnerClasses){
+ mTypeParameters = types;
+ mRealInnerClasses = realInnerClasses;
+ }
+
+ public ClassInfo[] getRealInnerClasses(){
+ return mRealInnerClasses;
+ }
+
+ public TypeInfo[] getTypeParameters(){
+ return mTypeParameters;
+ }
+
+ public boolean checkLevel()
+ {
+ int val = mCheckLevel;
+ if (val >= 0) {
+ return val != 0;
+ } else {
+ boolean v = DroidDoc.checkLevel(mIsPublic, mIsProtected,
+ mIsPackagePrivate, mIsPrivate, isHidden());
+ mCheckLevel = v ? 1 : 0;
+ return v;
+ }
+ }
+
+ public int compareTo(Object that) {
+ if (that instanceof ClassInfo) {
+ return mQualifiedName.compareTo(((ClassInfo)that).mQualifiedName);
+ } else {
+ return this.hashCode() - that.hashCode();
+ }
+ }
+
+ public ContainerInfo parent()
+ {
+ return this;
+ }
+
+ public boolean isPublic()
+ {
+ return mIsPublic;
+ }
+
+ public boolean isProtected()
+ {
+ return mIsProtected;
+ }
+
+ public boolean isPackagePrivate()
+ {
+ return mIsPackagePrivate;
+ }
+
+ public boolean isPrivate()
+ {
+ return mIsPrivate;
+ }
+
+ public boolean isStatic()
+ {
+ return mIsStatic;
+ }
+
+ public boolean isInterface()
+ {
+ return mIsInterface;
+ }
+
+ public boolean isAbstract()
+ {
+ return mIsAbstract;
+ }
+
+ public PackageInfo containingPackage()
+ {
+ return mContainingPackage;
+ }
+
+ public ClassInfo containingClass()
+ {
+ return mContainingClass;
+ }
+
+ public boolean isOrdinaryClass()
+ {
+ return mIsOrdinaryClass;
+ }
+
+ public boolean isException()
+ {
+ return mIsException;
+ }
+
+ public boolean isError()
+ {
+ return mIsError;
+ }
+
+ public boolean isEnum()
+ {
+ return mIsEnum;
+ }
+
+ public boolean isAnnotation()
+ {
+ return mIsAnnotation;
+ }
+
+ public boolean isFinal()
+ {
+ return mIsFinal;
+ }
+
+ public boolean isIncluded()
+ {
+ return mIsIncluded;
+ }
+
+ public HashSet<String> typeVariables()
+ {
+ HashSet<String> result = TypeInfo.typeVariables(mTypeInfo.typeArguments());
+ ClassInfo cl = containingClass();
+ while (cl != null) {
+ TypeInfo[] types = cl.asTypeInfo().typeArguments();
+ if (types != null) {
+ TypeInfo.typeVariables(types, result);
+ }
+ cl = cl.containingClass();
+ }
+ return result;
+ }
+
+ private static void gatherHiddenInterfaces(ClassInfo cl, HashSet<ClassInfo> interfaces) {
+ for (ClassInfo iface: cl.mRealInterfaces) {
+ if (iface.checkLevel()) {
+ interfaces.add(iface);
+ } else {
+ gatherHiddenInterfaces(iface, interfaces);
+ }
+ }
+ }
+
+ public ClassInfo[] interfaces()
+ {
+ if (mInterfaces == null) {
+ if (checkLevel()) {
+ HashSet<ClassInfo> interfaces = new HashSet<ClassInfo>();
+ ClassInfo superclass = mRealSuperclass;
+ while (superclass != null && !superclass.checkLevel()) {
+ gatherHiddenInterfaces(superclass, interfaces);
+ superclass = superclass.mRealSuperclass;
+ }
+ gatherHiddenInterfaces(this, interfaces);
+ mInterfaces = interfaces.toArray(new ClassInfo[interfaces.size()]);
+ } else {
+ // put something here in case someone uses it
+ mInterfaces = mRealInterfaces;
+ }
+ Arrays.sort(mInterfaces, ClassInfo.qualifiedComparator);
+ }
+ return mInterfaces;
+ }
+
+ public ClassInfo[] realInterfaces()
+ {
+ return mRealInterfaces;
+ }
+
+ TypeInfo[] realInterfaceTypes()
+ {
+ return mRealInterfaceTypes;
+ }
+
+ public String name()
+ {
+ return mName;
+ }
+
+ public String[] nameParts()
+ {
+ return mNameParts;
+ }
+
+ public String leafName()
+ {
+ return mNameParts[mNameParts.length-1];
+ }
+
+ public String qualifiedName()
+ {
+ return mQualifiedName;
+ }
+
+ public String qualifiedTypeName()
+ {
+ return mQualifiedTypeName;
+ }
+
+ public boolean isPrimitive()
+ {
+ return mIsPrimitive;
+ }
+
+ public MethodInfo[] allConstructors() {
+ return mAllConstructors;
+ }
+
+ public MethodInfo[] constructors()
+ {
+ if (mConstructors == null) {
+ MethodInfo[] methods = mAllConstructors;
+ ArrayList<MethodInfo> ctors = new ArrayList<MethodInfo>();
+ for (int i=0; i<methods.length; i++) {
+ MethodInfo m = methods[i];
+ if (!m.isHidden()) {
+ ctors.add(m);
+ }
+ }
+ mConstructors = ctors.toArray(new MethodInfo[ctors.size()]);
+ Arrays.sort(mConstructors, MethodInfo.comparator);
+ }
+ return mConstructors;
+ }
+
+ public ClassInfo[] innerClasses()
+ {
+ return mInnerClasses;
+ }
+
+ public TagInfo[] inlineTags()
+ {
+ return comment().tags();
+ }
+
+ public TagInfo[] firstSentenceTags()
+ {
+ return comment().briefTags();
+ }
+
+ public boolean isDeprecated() {
+ boolean deprecated = false;
+ if (!mDeprecatedKnown) {
+ boolean commentDeprecated = (comment().deprecatedTags().length > 0);
+ boolean annotationDeprecated = false;
+ for (AnnotationInstanceInfo annotation : annotations()) {
+ if (annotation.type().qualifiedName().equals("java.lang.Deprecated")) {
+ annotationDeprecated = true;
+ break;
+ }
+ }
+
+ if (commentDeprecated != annotationDeprecated) {
+ Errors.error(Errors.DEPRECATION_MISMATCH, position(),
+ "Class " + qualifiedName()
+ + ": @Deprecated annotation and @deprecated comment do not match");
+ }
+
+ mIsDeprecated = commentDeprecated | annotationDeprecated;
+ mDeprecatedKnown = true;
+ }
+ return mIsDeprecated;
+ }
+
+ public TagInfo[] deprecatedTags()
+ {
+ TagInfo[] result = comment().deprecatedTags();
+ if (result.length == 0) {
+ if (comment().undeprecateTags().length == 0) {
+ if (superclass() != null) {
+ result = superclass().deprecatedTags();
+ }
+ }
+ }
+ // should we also do the interfaces?
+ return result;
+ }
+
+ public MethodInfo[] methods()
+ {
+ if (mMethods == null) {
+ TreeMap<String,MethodInfo> all = new TreeMap<String,MethodInfo>();
+
+ ClassInfo[] ifaces = interfaces();
+ for (ClassInfo iface: ifaces) {
+ if (iface != null) {
+ MethodInfo[] inhereted = iface.methods();
+ for (MethodInfo method: inhereted) {
+ String key = method.name() + method.signature();
+ all.put(key, method);
+ }
+ }
+ }
+
+ ClassInfo superclass = superclass();
+ if (superclass != null) {
+ MethodInfo[] inhereted = superclass.methods();
+ for (MethodInfo method: inhereted) {
+ String key = method.name() + method.signature();
+ all.put(key, method);
+ }
+ }
+
+ MethodInfo[] methods = selfMethods();
+ for (MethodInfo method: methods) {
+ String key = method.name() + method.signature();
+ MethodInfo old = all.put(key, method);
+ }
+
+ mMethods = all.values().toArray(new MethodInfo[all.size()]);
+ }
+ return mMethods;
+ }
+
+ public MethodInfo[] annotationElements()
+ {
+ return mAnnotationElements;
+ }
+
+ public AnnotationInstanceInfo[] annotations()
+ {
+ return mAnnotations;
+ }
+
+ private static void addFields(ClassInfo cl, TreeMap<String,FieldInfo> all)
+ {
+ FieldInfo[] fields = cl.fields();
+ int N = fields.length;
+ for (int i=0; i<N; i++) {
+ FieldInfo f = fields[i];
+ all.put(f.name(), f);
+ }
+ }
+
+ public FieldInfo[] fields()
+ {
+ if (mFields == null) {
+ int N;
+ TreeMap<String,FieldInfo> all = new TreeMap<String,FieldInfo>();
+
+ ClassInfo[] interfaces = interfaces();
+ N = interfaces.length;
+ for (int i=0; i<N; i++) {
+ addFields(interfaces[i], all);
+ }
+
+ ClassInfo superclass = superclass();
+ if (superclass != null) {
+ addFields(superclass, all);
+ }
+
+ FieldInfo[] fields = selfFields();
+ N = fields.length;
+ for (int i=0; i<N; i++) {
+ FieldInfo f = fields[i];
+ if (!f.isHidden()) {
+ String key = f.name();
+ all.put(key, f);
+ }
+ }
+
+ mFields = all.values().toArray(new FieldInfo[0]);
+ }
+ return mFields;
+ }
+
+ public void gatherFields(ClassInfo owner, ClassInfo cl, HashMap<String,FieldInfo> fields) {
+ FieldInfo[] flds = cl.selfFields();
+ for (FieldInfo f: flds) {
+ if (f.checkLevel()) {
+ fields.put(f.name(), f.cloneForClass(owner));
+ }
+ }
+ }
+
+ public FieldInfo[] selfFields()
+ {
+ if (mSelfFields == null) {
+ HashMap<String,FieldInfo> fields = new HashMap<String,FieldInfo>();
+ // our hidden parents
+ if (mRealSuperclass != null && !mRealSuperclass.checkLevel()) {
+ gatherFields(this, mRealSuperclass, fields);
+ }
+ for (ClassInfo iface: mRealInterfaces) {
+ if (!iface.checkLevel()) {
+ gatherFields(this, iface, fields);
+ }
+ }
+ // mine
+ FieldInfo[] selfFields = mAllSelfFields;
+ for (int i=0; i<selfFields.length; i++) {
+ FieldInfo f = selfFields[i];
+ if (!f.isHidden()) {
+ fields.put(f.name(), f);
+ }
+ }
+ // combine and return in
+ mSelfFields = fields.values().toArray(new FieldInfo[fields.size()]);
+ Arrays.sort(mSelfFields, FieldInfo.comparator);
+ }
+ return mSelfFields;
+ }
+
+ public FieldInfo[] allSelfFields() {
+ return mAllSelfFields;
+ }
+
+ public void gatherMethods(ClassInfo owner, ClassInfo cl, HashMap<String,MethodInfo> methods) {
+ MethodInfo[] meth = cl.selfMethods();
+ for (MethodInfo m: meth) {
+ if (m.checkLevel()) {
+ methods.put(m.name()+m.signature(), m.cloneForClass(owner));
+ }
+ }
+ }
+
+ public MethodInfo[] selfMethods()
+ {
+ if (mSelfMethods == null) {
+ HashMap<String,MethodInfo> methods = new HashMap<String,MethodInfo>();
+ // our hidden parents
+ if (mRealSuperclass != null && !mRealSuperclass.checkLevel()) {
+ gatherMethods(this, mRealSuperclass, methods);
+ }
+ for (ClassInfo iface: mRealInterfaces) {
+ if (!iface.checkLevel()) {
+ gatherMethods(this, iface, methods);
+ }
+ }
+ // mine
+ MethodInfo[] selfMethods = mAllSelfMethods;
+ for (int i=0; i<selfMethods.length; i++) {
+ MethodInfo m = selfMethods[i];
+ if (m.checkLevel()) {
+ methods.put(m.name()+m.signature(), m);
+ }
+ }
+ // combine and return it
+ mSelfMethods = methods.values().toArray(new MethodInfo[methods.size()]);
+ Arrays.sort(mSelfMethods, MethodInfo.comparator);
+ }
+ return mSelfMethods;
+ }
+
+ public MethodInfo[] allSelfMethods() {
+ return mAllSelfMethods;
+ }
+
+ public void addMethod(MethodInfo method) {
+ MethodInfo[] methods = new MethodInfo[mAllSelfMethods.length + 1];
+ int i = 0;
+ for (MethodInfo m : mAllSelfMethods) {
+ methods[i] = m;
+ i++;
+ }
+ methods[i] = method;
+ mAllSelfMethods = methods;
+ }
+
+ public AttributeInfo[] selfAttributes()
+ {
+ if (mSelfAttributes == null) {
+ TreeMap<FieldInfo,AttributeInfo> attrs = new TreeMap<FieldInfo,AttributeInfo>();
+
+ // the ones in the class comment won't have any methods
+ for (AttrTagInfo tag: comment().attrTags()) {
+ FieldInfo field = tag.reference();
+ if (field != null) {
+ AttributeInfo attr = attrs.get(field);
+ if (attr == null) {
+ attr = new AttributeInfo(this, field);
+ attrs.put(field, attr);
+ }
+ tag.setAttribute(attr);
+ }
+ }
+
+ // in the methods
+ for (MethodInfo m: selfMethods()) {
+ for (AttrTagInfo tag: m.comment().attrTags()) {
+ FieldInfo field = tag.reference();
+ if (field != null) {
+ AttributeInfo attr = attrs.get(field);
+ if (attr == null) {
+ attr = new AttributeInfo(this, field);
+ attrs.put(field, attr);
+ }
+ tag.setAttribute(attr);
+ attr.methods.add(m);
+ }
+ }
+ }
+
+ //constructors too
+ for (MethodInfo m: constructors()) {
+ for (AttrTagInfo tag: m.comment().attrTags()) {
+ FieldInfo field = tag.reference();
+ if (field != null) {
+ AttributeInfo attr = attrs.get(field);
+ if (attr == null) {
+ attr = new AttributeInfo(this, field);
+ attrs.put(field, attr);
+ }
+ tag.setAttribute(attr);
+ attr.methods.add(m);
+ }
+ }
+ }
+
+ mSelfAttributes = attrs.values().toArray(new AttributeInfo[attrs.size()]);
+ Arrays.sort(mSelfAttributes, AttributeInfo.comparator);
+ }
+ return mSelfAttributes;
+ }
+
+ public FieldInfo[] enumConstants()
+ {
+ return mEnumConstants;
+ }
+
+ public ClassInfo superclass()
+ {
+ if (!mSuperclassInit) {
+ if (this.checkLevel()) {
+ // rearrange our little inheritance hierarchy, because we need to hide classes that
+ // don't pass checkLevel
+ ClassInfo superclass = mRealSuperclass;
+ while (superclass != null && !superclass.checkLevel()) {
+ superclass = superclass.mRealSuperclass;
+ }
+ mSuperclass = superclass;
+ } else {
+ mSuperclass = mRealSuperclass;
+ }
+ }
+ return mSuperclass;
+ }
+
+ public ClassInfo realSuperclass()
+ {
+ return mRealSuperclass;
+ }
+
+ /** always the real superclass, not the collapsed one we get through superclass(),
+ * also has the type parameter info if it's generic.
+ */
+ public TypeInfo superclassType()
+ {
+ return mRealSuperclassType;
+ }
+
+ public TypeInfo asTypeInfo()
+ {
+ return mTypeInfo;
+ }
+
+ TypeInfo[] interfaceTypes()
+ {
+ ClassInfo[] infos = interfaces();
+ int len = infos.length;
+ TypeInfo[] types = new TypeInfo[len];
+ for (int i=0; i<len; i++) {
+ types[i] = infos[i].asTypeInfo();
+ }
+ return types;
+ }
+
+ public String htmlPage()
+ {
+ String s = containingPackage().name();
+ s = s.replace('.', '/');
+ s += '/';
+ s += name();
+ s += ".html";
+ s = DroidDoc.javadocDir + s;
+ return s;
+ }
+
+ /** Even indirectly */
+ public boolean isDerivedFrom(ClassInfo cl)
+ {
+ ClassInfo dad = this.superclass();
+ if (dad != null) {
+ if (dad.equals(cl)) {
+ return true;
+ } else {
+ if (dad.isDerivedFrom(cl)) {
+ return true;
+ }
+ }
+ }
+ for (ClassInfo iface: interfaces()) {
+ if (iface.equals(cl)) {
+ return true;
+ } else {
+ if (iface.isDerivedFrom(cl)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public void makeKeywordEntries(List<KeywordEntry> keywords)
+ {
+ if (!checkLevel()) {
+ return;
+ }
+
+ String htmlPage = htmlPage();
+ String qualifiedName = qualifiedName();
+
+ keywords.add(new KeywordEntry(name(), htmlPage,
+ "class in " + containingPackage().name()));
+
+ FieldInfo[] fields = selfFields();
+ FieldInfo[] enumConstants = enumConstants();
+ MethodInfo[] ctors = constructors();
+ MethodInfo[] methods = selfMethods();
+
+ // enum constants
+ for (FieldInfo field: enumConstants()) {
+ if (field.checkLevel()) {
+ keywords.add(new KeywordEntry(field.name(),
+ htmlPage + "#" + field.anchor(),
+ "enum constant in " + qualifiedName));
+ }
+ }
+
+ // constants
+ for (FieldInfo field: fields) {
+ if (field.isConstant() && field.checkLevel()) {
+ keywords.add(new KeywordEntry(field.name(),
+ htmlPage + "#" + field.anchor(),
+ "constant in " + qualifiedName));
+ }
+ }
+
+ // fields
+ for (FieldInfo field: fields) {
+ if (!field.isConstant() && field.checkLevel()) {
+ keywords.add(new KeywordEntry(field.name(),
+ htmlPage + "#" + field.anchor(),
+ "field in " + qualifiedName));
+ }
+ }
+
+ // public constructors
+ for (MethodInfo m: ctors) {
+ if (m.isPublic() && m.checkLevel()) {
+ keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
+ htmlPage + "#" + m.anchor(),
+ "constructor in " + qualifiedName));
+ }
+ }
+
+ // protected constructors
+ if (DroidDoc.checkLevel(DroidDoc.SHOW_PROTECTED)) {
+ for (MethodInfo m: ctors) {
+ if (m.isProtected() && m.checkLevel()) {
+ keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
+ htmlPage + "#" + m.anchor(),
+ "constructor in " + qualifiedName));
+ }
+ }
+ }
+
+ // package private constructors
+ if (DroidDoc.checkLevel(DroidDoc.SHOW_PACKAGE)) {
+ for (MethodInfo m: ctors) {
+ if (m.isPackagePrivate() && m.checkLevel()) {
+ keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
+ htmlPage + "#" + m.anchor(),
+ "constructor in " + qualifiedName));
+ }
+ }
+ }
+
+ // private constructors
+ if (DroidDoc.checkLevel(DroidDoc.SHOW_PRIVATE)) {
+ for (MethodInfo m: ctors) {
+ if (m.isPrivate() && m.checkLevel()) {
+ keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
+ htmlPage + "#" + m.anchor(),
+ "constructor in " + qualifiedName));
+ }
+ }
+ }
+
+ // public methods
+ for (MethodInfo m: methods) {
+ if (m.isPublic() && m.checkLevel()) {
+ keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
+ htmlPage + "#" + m.anchor(),
+ "method in " + qualifiedName));
+ }
+ }
+
+ // protected methods
+ if (DroidDoc.checkLevel(DroidDoc.SHOW_PROTECTED)) {
+ for (MethodInfo m: methods) {
+ if (m.isProtected() && m.checkLevel()) {
+ keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
+ htmlPage + "#" + m.anchor(),
+ "method in " + qualifiedName));
+ }
+ }
+ }
+
+ // package private methods
+ if (DroidDoc.checkLevel(DroidDoc.SHOW_PACKAGE)) {
+ for (MethodInfo m: methods) {
+ if (m.isPackagePrivate() && m.checkLevel()) {
+ keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
+ htmlPage + "#" + m.anchor(),
+ "method in " + qualifiedName));
+ }
+ }
+ }
+
+ // private methods
+ if (DroidDoc.checkLevel(DroidDoc.SHOW_PRIVATE)) {
+ for (MethodInfo m: methods) {
+ if (m.isPrivate() && m.checkLevel()) {
+ keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
+ htmlPage + "#" + m.anchor(),
+ "method in " + qualifiedName));
+ }
+ }
+ }
+ }
+
+ public void makeLink(HDF data, String base)
+ {
+ data.setValue(base + ".label", this.name());
+ if (!this.isPrimitive() && this.isIncluded() && this.checkLevel()) {
+ data.setValue(base + ".link", this.htmlPage());
+ }
+ }
+
+ public static void makeLinkListHDF(HDF data, String base, ClassInfo[] classes) {
+ final int N = classes.length;
+ for (int i=0; i<N; i++) {
+ ClassInfo cl = classes[i];
+ if (cl.checkLevel()) {
+ cl.asTypeInfo().makeHDF(data, base + "." + i);
+ }
+ }
+ }
+
+ /**
+ * Used in lists of this class (packages, nested classes, known subclasses)
+ */
+ public void makeShortDescrHDF(HDF data, String base)
+ {
+ mTypeInfo.makeHDF(data, base + ".type");
+ data.setValue(base + ".kind", this.kind());
+ TagInfo.makeHDF(data, base + ".shortDescr", this.firstSentenceTags());
+ TagInfo.makeHDF(data, base + ".deprecated", deprecatedTags());
+ }
+
+ /**
+ * Turns into the main class page
+ */
+ public void makeHDF(HDF data)
+ {
+ int i, j, n;
+ String name = name();
+ String qualified = qualifiedName();
+ AttributeInfo[] selfAttributes = selfAttributes();
+ MethodInfo[] methods = selfMethods();
+ FieldInfo[] fields = selfFields();
+ FieldInfo[] enumConstants = enumConstants();
+ MethodInfo[] ctors = constructors();
+ ClassInfo[] inners = innerClasses();
+
+ // class name
+ mTypeInfo.makeHDF(data, "class.type");
+ mTypeInfo.makeQualifiedHDF(data, "class.qualifiedType");
+ data.setValue("class.name", name);
+ data.setValue("class.qualified", qualified);
+ String scope = "";
+ if (isProtected()) {
+ data.setValue("class.scope", "protected");
+ }
+ else if (isPublic()) {
+ data.setValue("class.scope", "public");
+ }
+ if (isStatic()) {
+ data.setValue("class.static", "static");
+ }
+ if (isFinal()) {
+ data.setValue("class.final", "final");
+ }
+ if (isAbstract() && !isInterface()) {
+ data.setValue("class.abstract", "abstract");
+ }
+
+ // class info
+ String kind = kind();
+ if (kind != null) {
+ data.setValue("class.kind", kind);
+ }
+
+ // the containing package -- note that this can be passed to type_link,
+ // but it also contains the list of all of the packages
+ containingPackage().makeClassLinkListHDF(data, "class.package");
+
+ // inheritance hierarchy
+ Vector<ClassInfo> superClasses = new Vector<ClassInfo>();
+ superClasses.add(this);
+ ClassInfo supr = superclass();
+ while (supr != null) {
+ superClasses.add(supr);
+ supr = supr.superclass();
+ }
+ n = superClasses.size();
+ for (i=0; i<n; i++) {
+ supr = superClasses.elementAt(n-i-1);
+
+ supr.asTypeInfo().makeQualifiedHDF(data, "class.inheritance." + i + ".class");
+ supr.asTypeInfo().makeHDF(data, "class.inheritance." + i + ".short_class");
+ j = 0;
+ for (TypeInfo t: supr.interfaceTypes()) {
+ t.makeHDF(data, "class.inheritance." + i + ".interfaces." + j);
+ j++;
+ }
+ }
+
+ // class description
+ TagInfo.makeHDF(data, "class.descr", inlineTags());
+ TagInfo.makeHDF(data, "class.seeAlso", comment().seeTags());
+ TagInfo.makeHDF(data, "class.deprecated", deprecatedTags());
+
+ // known subclasses
+ TreeMap<String, ClassInfo> direct = new TreeMap<String, ClassInfo>();
+ TreeMap<String, ClassInfo> indirect = new TreeMap<String, ClassInfo>();
+ ClassInfo[] all = Converter.rootClasses();
+ for (ClassInfo cl: all) {
+ if (cl.superclass() != null && cl.superclass().equals(this)) {
+ direct.put(cl.name(), cl);
+ }
+ else if (cl.isDerivedFrom(this)) {
+ indirect.put(cl.name(), cl);
+ }
+ }
+ // direct
+ i = 0;
+ for (ClassInfo cl: direct.values()) {
+ if (cl.checkLevel()) {
+ cl.makeShortDescrHDF(data, "class.subclasses.direct." + i);
+ }
+ i++;
+ }
+ // indirect
+ i = 0;
+ for (ClassInfo cl: indirect.values()) {
+ if (cl.checkLevel()) {
+ cl.makeShortDescrHDF(data, "class.subclasses.indirect." + i);
+ }
+ i++;
+ }
+
+ // nested classes
+ i=0;
+ for (ClassInfo inner: inners) {
+ if (inner.checkLevel()) {
+ inner.makeShortDescrHDF(data, "class.inners." + i);
+ }
+ i++;
+ }
+
+ // enum constants
+ i=0;
+ for (FieldInfo field: enumConstants) {
+ if (field.isConstant()) {
+ field.makeHDF(data, "class.enumConstants." + i);
+ i++;
+ }
+ }
+
+ // constants
+ i=0;
+ for (FieldInfo field: fields) {
+ if (field.isConstant()) {
+ field.makeHDF(data, "class.constants." + i);
+ i++;
+ }
+ }
+
+ // fields
+ i=0;
+ for (FieldInfo field: fields) {
+ if (!field.isConstant()) {
+ field.makeHDF(data, "class.fields." + i);
+ i++;
+ }
+ }
+
+ // public constructors
+ i=0;
+ for (MethodInfo ctor: ctors) {
+ if (ctor.isPublic()) {
+ ctor.makeHDF(data, "class.ctors.public." + i);
+ i++;
+ }
+ }
+
+ // protected constructors
+ if (DroidDoc.checkLevel(DroidDoc.SHOW_PROTECTED)) {
+ i=0;
+ for (MethodInfo ctor: ctors) {
+ if (ctor.isProtected()) {
+ ctor.makeHDF(data, "class.ctors.protected." + i);
+ i++;
+ }
+ }
+ }
+
+ // package private constructors
+ if (DroidDoc.checkLevel(DroidDoc.SHOW_PACKAGE)) {
+ i=0;
+ for (MethodInfo ctor: ctors) {
+ if (ctor.isPackagePrivate()) {
+ ctor.makeHDF(data, "class.ctors.package." + i);
+ i++;
+ }
+ }
+ }
+
+ // private constructors
+ if (DroidDoc.checkLevel(DroidDoc.SHOW_PRIVATE)) {
+ i=0;
+ for (MethodInfo ctor: ctors) {
+ if (ctor.isPrivate()) {
+ ctor.makeHDF(data, "class.ctors.private." + i);
+ i++;
+ }
+ }
+ }
+
+ // public methods
+ i=0;
+ for (MethodInfo method: methods) {
+ if (method.isPublic()) {
+ method.makeHDF(data, "class.methods.public." + i);
+ i++;
+ }
+ }
+
+ // protected methods
+ if (DroidDoc.checkLevel(DroidDoc.SHOW_PROTECTED)) {
+ i=0;
+ for (MethodInfo method: methods) {
+ if (method.isProtected()) {
+ method.makeHDF(data, "class.methods.protected." + i);
+ i++;
+ }
+ }
+ }
+
+ // package private methods
+ if (DroidDoc.checkLevel(DroidDoc.SHOW_PACKAGE)) {
+ i=0;
+ for (MethodInfo method: methods) {
+ if (method.isPackagePrivate()) {
+ method.makeHDF(data, "class.methods.package." + i);
+ i++;
+ }
+ }
+ }
+
+ // private methods
+ if (DroidDoc.checkLevel(DroidDoc.SHOW_PRIVATE)) {
+ i=0;
+ for (MethodInfo method: methods) {
+ if (method.isPrivate()) {
+ method.makeHDF(data, "class.methods.private." + i);
+ i++;
+ }
+ }
+ }
+
+ // xml attributes
+ i=0;
+ for (AttributeInfo attr: selfAttributes) {
+ if (attr.checkLevel()) {
+ attr.makeHDF(data, "class.attrs." + i);
+ i++;
+ }
+ }
+
+ // inherited methods
+ Set<ClassInfo> interfaces = new TreeSet<ClassInfo>();
+ addInterfaces(interfaces(), interfaces);
+ ClassInfo cl = superclass();
+ i=0;
+ while (cl != null) {
+ addInterfaces(cl.interfaces(), interfaces);
+ makeInheritedHDF(data, i, cl);
+ cl = cl.superclass();
+ i++;
+ }
+ for (ClassInfo iface: interfaces) {
+ makeInheritedHDF(data, i, iface);
+ i++;
+ }
+ }
+
+ private static void addInterfaces(ClassInfo[] ifaces, Set<ClassInfo> out)
+ {
+ for (ClassInfo cl: ifaces) {
+ out.add(cl);
+ addInterfaces(cl.interfaces(), out);
+ }
+ }
+
+ private static void makeInheritedHDF(HDF data, int index, ClassInfo cl)
+ {
+ int i;
+
+ String base = "class.inherited." + index;
+ data.setValue(base + ".qualified", cl.qualifiedName());
+ if (cl.checkLevel()) {
+ data.setValue(base + ".link", cl.htmlPage());
+ }
+ String kind = cl.kind();
+ if (kind != null) {
+ data.setValue(base + ".kind", kind);
+ }
+
+ // xml attributes
+ i=0;
+ for (AttributeInfo attr: cl.selfAttributes()) {
+ attr.makeHDF(data, base + ".attrs." + i);
+ i++;
+ }
+
+ // methods
+ i=0;
+ for (MethodInfo method: cl.selfMethods()) {
+ method.makeHDF(data, base + ".methods." + i);
+ i++;
+ }
+
+ // fields
+ i=0;
+ for (FieldInfo field: cl.selfFields()) {
+ if (!field.isConstant()) {
+ field.makeHDF(data, base + ".fields." + i);
+ i++;
+ }
+ }
+
+ // constants
+ i=0;
+ for (FieldInfo field: cl.selfFields()) {
+ if (field.isConstant()) {
+ field.makeHDF(data, base + ".constants." + i);
+ i++;
+ }
+ }
+ }
+
+ public boolean isHidden()
+ {
+ int val = mHidden;
+ if (val >= 0) {
+ return val != 0;
+ } else {
+ boolean v = isHiddenImpl();
+ mHidden = v ? 1 : 0;
+ return v;
+ }
+ }
+
+ public boolean isHiddenImpl()
+ {
+ ClassInfo cl = this;
+ while (cl != null) {
+ PackageInfo pkg = cl.containingPackage();
+ if (pkg.isHidden()) {
+ return true;
+ }
+ if (cl.comment().isHidden()) {
+ return true;
+ }
+ cl = cl.containingClass();
+ }
+ return false;
+ }
+
+ private MethodInfo matchMethod(MethodInfo[] methods, String name,
+ String[] params, String[] dimensions)
+ {
+ int len = methods.length;
+ for (int i=0; i<len; i++) {
+ MethodInfo method = methods[i];
+ if (method.name().equals(name)) {
+ if (params == null) {
+ return method;
+ } else {
+ if (method.matchesParams(params, dimensions)) {
+ return method;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ public MethodInfo findMethod(String name,
+ String[] params, String[] dimensions)
+ {
+ // first look on our class, and our superclasses
+
+ // for methods
+ MethodInfo rv;
+ rv = matchMethod(methods(), name, params, dimensions);
+
+ if (rv != null) {
+ return rv;
+ }
+
+ // for constructors
+ rv = matchMethod(constructors(), name, params, dimensions);
+ if (rv != null) {
+ return rv;
+ }
+
+ // then recursively look at our containing class
+ ClassInfo containing = containingClass();
+ if (containing != null) {
+ return containing.findMethod(name, params, dimensions);
+ }
+
+ return null;
+ }
+
+ private ClassInfo searchInnerClasses(String[] nameParts, int index)
+ {
+ String part = nameParts[index];
+
+ ClassInfo[] inners = mInnerClasses;
+ for (ClassInfo in: inners) {
+ String[] innerParts = in.nameParts();
+ if (part.equals(innerParts[innerParts.length-1])) {
+ if (index == nameParts.length-1) {
+ return in;
+ } else {
+ return in.searchInnerClasses(nameParts, index+1);
+ }
+ }
+ }
+ return null;
+ }
+
+ public ClassInfo extendedFindClass(String className)
+ {
+ // ClassDoc.findClass has this bug that we're working around here:
+ // If you have a class PackageManager with an inner class PackageInfo
+ // and you call it with "PackageInfo" it doesn't find it.
+ return searchInnerClasses(className.split("\\."), 0);
+ }
+
+ public ClassInfo findClass(String className)
+ {
+ return Converter.obtainClass(mClass.findClass(className));
+ }
+
+ public ClassInfo findInnerClass(String className)
+ {
+ // ClassDoc.findClass won't find inner classes. To deal with that,
+ // we try what they gave us first, but if that didn't work, then
+ // we see if there are any periods in className, and start searching
+ // from there.
+ String[] nodes = className.split("\\.");
+ ClassDoc cl = mClass;
+ for (String n: nodes) {
+ cl = cl.findClass(n);
+ if (cl == null) {
+ return null;
+ }
+ }
+ return Converter.obtainClass(cl);
+ }
+
+ public FieldInfo findField(String name)
+ {
+ // first look on our class, and our superclasses
+ for (FieldInfo f: fields()) {
+ if (f.name().equals(name)) {
+ return f;
+ }
+ }
+
+ // then look at our enum constants (these are really fields, maybe
+ // they should be mixed into fields(). not sure)
+ for (FieldInfo f: enumConstants()) {
+ if (f.name().equals(name)) {
+ return f;
+ }
+ }
+
+ // then recursively look at our containing class
+ ClassInfo containing = containingClass();
+ if (containing != null) {
+ return containing.findField(name);
+ }
+
+ return null;
+ }
+
+ public static ClassInfo[] sortByName(ClassInfo[] classes)
+ {
+ int i;
+ Sorter[] sorted = new Sorter[classes.length];
+ for (i=0; i<sorted.length; i++) {
+ ClassInfo cl = classes[i];
+ sorted[i] = new Sorter(cl.name(), cl);
+ }
+
+ Arrays.sort(sorted);
+
+ ClassInfo[] rv = new ClassInfo[classes.length];
+ for (i=0; i<rv.length; i++) {
+ rv[i] = (ClassInfo)sorted[i].data;
+ }
+
+ return rv;
+ }
+
+ public boolean equals(ClassInfo that)
+ {
+ if (that != null) {
+ return this.qualifiedName().equals(that.qualifiedName());
+ } else {
+ return false;
+ }
+ }
+
+ public void setNonWrittenConstructors(MethodInfo[] nonWritten) {
+ mNonWrittenConstructors = nonWritten;
+ }
+
+ public MethodInfo[] getNonWrittenConstructors() {
+ return mNonWrittenConstructors;
+ }
+
+ public String kind()
+ {
+ if (isOrdinaryClass()) {
+ return "class";
+ }
+ else if (isInterface()) {
+ return "interface";
+ }
+ else if (isEnum()) {
+ return "enum";
+ }
+ else if (isError()) {
+ return "class";
+ }
+ else if (isException()) {
+ return "class";
+ }
+ else if (isAnnotation()) {
+ return "@interface";
+ }
+ return null;
+ }
+
+ public void setHiddenMethods(MethodInfo[] mInfo){
+ mHiddenMethods = mInfo;
+ }
+ public MethodInfo[] getHiddenMethods(){
+ return mHiddenMethods;
+ }
+ public String toString(){
+ return this.qualifiedName();
+ }
+
+ public void setReasonIncluded(String reason) {
+ mReasonIncluded = reason;
+ }
+
+ public String getReasonIncluded() {
+ return mReasonIncluded;
+ }
+
+ private ClassDoc mClass;
+
+ // ctor
+ private boolean mIsPublic;
+ private boolean mIsProtected;
+ private boolean mIsPackagePrivate;
+ private boolean mIsPrivate;
+ private boolean mIsStatic;
+ private boolean mIsInterface;
+ private boolean mIsAbstract;
+ private boolean mIsOrdinaryClass;
+ private boolean mIsException;
+ private boolean mIsError;
+ private boolean mIsEnum;
+ private boolean mIsAnnotation;
+ private boolean mIsFinal;
+ private boolean mIsIncluded;
+ private String mName;
+ private String mQualifiedName;
+ private String mQualifiedTypeName;
+ private boolean mIsPrimitive;
+ private TypeInfo mTypeInfo;
+ private String[] mNameParts;
+
+ // init
+ private ClassInfo[] mRealInterfaces;
+ private ClassInfo[] mInterfaces;
+ private TypeInfo[] mRealInterfaceTypes;
+ private ClassInfo[] mInnerClasses;
+ private MethodInfo[] mAllConstructors;
+ private MethodInfo[] mAllSelfMethods;
+ private MethodInfo[] mAnnotationElements; // if this class is an annotation
+ private FieldInfo[] mAllSelfFields;
+ private FieldInfo[] mEnumConstants;
+ private PackageInfo mContainingPackage;
+ private ClassInfo mContainingClass;
+ private ClassInfo mRealSuperclass;
+ private TypeInfo mRealSuperclassType;
+ private ClassInfo mSuperclass;
+ private AnnotationInstanceInfo[] mAnnotations;
+ private boolean mSuperclassInit;
+ private boolean mDeprecatedKnown;
+
+ // lazy
+ private MethodInfo[] mConstructors;
+ private ClassInfo[] mRealInnerClasses;
+ private MethodInfo[] mSelfMethods;
+ private FieldInfo[] mSelfFields;
+ private AttributeInfo[] mSelfAttributes;
+ private MethodInfo[] mMethods;
+ private FieldInfo[] mFields;
+ private TypeInfo[] mTypeParameters;
+ private MethodInfo[] mHiddenMethods;
+ private int mHidden = -1;
+ private int mCheckLevel = -1;
+ private String mReasonIncluded;
+ private MethodInfo[] mNonWrittenConstructors;
+ private boolean mIsDeprecated;
+}