PageRenderTime 122ms CodeModel.GetById 2ms app.highlight 107ms RepoModel.GetById 1ms app.codeStats 1ms

/tools/droiddoc/src/ClassInfo.java

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