Home | History | Annotate | Download | only in doclava
      1 /*
      2  * Copyright (C) 2010 Google Inc.
      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 package com.google.doclava;
     18 
     19 import com.google.doclava.apicheck.ApiInfo;
     20 import com.google.clearsilver.jsilver.data.Data;
     21 
     22 import com.sun.javadoc.*;
     23 import java.util.*;
     24 
     25 public class PackageInfo extends DocInfo implements ContainerInfo {
     26   public static final String DEFAULT_PACKAGE = "default package";
     27 
     28   public static final Comparator<PackageInfo> comparator = new Comparator<PackageInfo>() {
     29     public int compare(PackageInfo a, PackageInfo b) {
     30       return a.name().compareTo(b.name());
     31     }
     32   };
     33 
     34   public PackageInfo(PackageDoc pkg, String name, SourcePositionInfo position) {
     35     super(pkg.getRawCommentText(), position);
     36     if (name.isEmpty()) {
     37       mName = DEFAULT_PACKAGE;
     38     } else {
     39       mName = name;
     40     }
     41 
     42     mPackage = pkg;
     43     initializeMaps();
     44   }
     45 
     46   public PackageInfo(String name) {
     47     super("", null);
     48     mName = name;
     49     initializeMaps();
     50   }
     51 
     52   public PackageInfo(String name, SourcePositionInfo position) {
     53     super("", position);
     54 
     55     if (name.isEmpty()) {
     56       mName = "default package";
     57     } else {
     58       mName = name;
     59     }
     60     initializeMaps();
     61   }
     62 
     63   private void initializeMaps() {
     64       mInterfacesMap = new HashMap<String, ClassInfo>();
     65       mOrdinaryClassesMap = new HashMap<String, ClassInfo>();
     66       mEnumsMap = new HashMap<String, ClassInfo>();
     67       mExceptionsMap = new HashMap<String, ClassInfo>();
     68       mErrorsMap = new HashMap<String, ClassInfo>();
     69   }
     70 
     71   public String htmlPage() {
     72     String s = mName;
     73     s = s.replace('.', '/');
     74     s += "/package-summary.html";
     75     s = Doclava.javadocDir + s;
     76     return s;
     77   }
     78 
     79   @Override
     80   public ContainerInfo parent() {
     81     return null;
     82   }
     83 
     84   @Override
     85   public boolean isHidden() {
     86     return comment().isHidden();
     87   }
     88 
     89   public boolean checkLevel() {
     90     // TODO should return false if all classes are hidden but the package isn't.
     91     // We don't have this so I'm not doing it now.
     92     return !isHidden();
     93   }
     94 
     95   public String name() {
     96     return mName;
     97   }
     98 
     99   public String qualifiedName() {
    100     return mName;
    101   }
    102 
    103   public TagInfo[] inlineTags() {
    104     return comment().tags();
    105   }
    106 
    107   public TagInfo[] firstSentenceTags() {
    108     return comment().briefTags();
    109   }
    110 
    111   public static ClassInfo[] filterHidden(ClassInfo[] classes) {
    112     ArrayList<ClassInfo> out = new ArrayList<ClassInfo>();
    113 
    114     for (ClassInfo cl : classes) {
    115       if (!cl.isHidden()) {
    116         out.add(cl);
    117       }
    118     }
    119 
    120     return out.toArray(new ClassInfo[0]);
    121   }
    122 
    123   public void makeLink(Data data, String base) {
    124     if (checkLevel()) {
    125       data.setValue(base + ".link", htmlPage());
    126     }
    127     data.setValue(base + ".name", name());
    128     data.setValue(base + ".since", getSince());
    129   }
    130 
    131   public void makeClassLinkListHDF(Data data, String base) {
    132     makeLink(data, base);
    133     ClassInfo.makeLinkListHDF(data, base + ".interfaces", interfaces());
    134     ClassInfo.makeLinkListHDF(data, base + ".classes", ordinaryClasses());
    135     ClassInfo.makeLinkListHDF(data, base + ".enums", enums());
    136     ClassInfo.makeLinkListHDF(data, base + ".exceptions", exceptions());
    137     ClassInfo.makeLinkListHDF(data, base + ".errors", errors());
    138     data.setValue(base + ".since", getSince());
    139   }
    140 
    141   public ClassInfo[] interfaces() {
    142     if (mInterfaces == null) {
    143       mInterfaces =
    144           ClassInfo.sortByName(filterHidden(Converter.convertClasses(mPackage.interfaces())));
    145     }
    146     return mInterfaces;
    147   }
    148 
    149   public ClassInfo[] ordinaryClasses() {
    150     if (mOrdinaryClasses == null) {
    151       mOrdinaryClasses =
    152           ClassInfo.sortByName(filterHidden(Converter.convertClasses(mPackage.ordinaryClasses())));
    153     }
    154     return mOrdinaryClasses;
    155   }
    156 
    157   public ClassInfo[] enums() {
    158     if (mEnums == null) {
    159       mEnums = ClassInfo.sortByName(filterHidden(Converter.convertClasses(mPackage.enums())));
    160     }
    161     return mEnums;
    162   }
    163 
    164   public ClassInfo[] exceptions() {
    165     if (mExceptions == null) {
    166       mExceptions =
    167           ClassInfo.sortByName(filterHidden(Converter.convertClasses(mPackage.exceptions())));
    168     }
    169     return mExceptions;
    170   }
    171 
    172   public ClassInfo[] errors() {
    173     if (mErrors == null) {
    174       mErrors = ClassInfo.sortByName(filterHidden(Converter.convertClasses(mPackage.errors())));
    175     }
    176     return mErrors;
    177   }
    178 
    179   public ApiInfo containingApi() {
    180     return mContainingApi;
    181   }
    182 
    183   public void setContainingApi(ApiInfo api) {
    184     mContainingApi = api;
    185   }
    186 
    187   // in hashed containers, treat the name as the key
    188   @Override
    189   public int hashCode() {
    190     return mName.hashCode();
    191   }
    192 
    193   private String mName;
    194   private PackageDoc mPackage;
    195   private ApiInfo mContainingApi;
    196   private ClassInfo[] mInterfaces;
    197   private ClassInfo[] mOrdinaryClasses;
    198   private ClassInfo[] mEnums;
    199   private ClassInfo[] mExceptions;
    200   private ClassInfo[] mErrors;
    201 
    202   private HashMap<String, ClassInfo> mInterfacesMap;
    203   private HashMap<String, ClassInfo> mOrdinaryClassesMap;
    204   private HashMap<String, ClassInfo> mEnumsMap;
    205   private HashMap<String, ClassInfo> mExceptionsMap;
    206   private HashMap<String, ClassInfo> mErrorsMap;
    207 
    208 
    209   public ClassInfo getClass(String className) {
    210       ClassInfo cls = mInterfacesMap.get(className);
    211 
    212       if (cls != null) {
    213           return cls;
    214       }
    215 
    216       cls = mOrdinaryClassesMap.get(className);
    217 
    218       if (cls != null) {
    219           return cls;
    220       }
    221 
    222       cls = mEnumsMap.get(className);
    223 
    224       if (cls != null) {
    225           return cls;
    226       }
    227 
    228       cls = mEnumsMap.get(className);
    229 
    230       if (cls != null) {
    231           return cls;
    232       }
    233 
    234       return mErrorsMap.get(className);
    235   }
    236 
    237   public void addInterface(ClassInfo cls) {
    238       cls.setPackage(this);
    239       mInterfacesMap.put(cls.name(), cls);
    240   }
    241 
    242   public ClassInfo getInterface(String interfaceName) {
    243       return mInterfacesMap.get(interfaceName);
    244   }
    245 
    246   public ClassInfo getOrdinaryClass(String className) {
    247       return mOrdinaryClassesMap.get(className);
    248   }
    249 
    250   public void addOrdinaryClass(ClassInfo cls) {
    251       cls.setPackage(this);
    252       mOrdinaryClassesMap.put(cls.name(), cls);
    253   }
    254 
    255   public ClassInfo getEnum(String enumName) {
    256       return mEnumsMap.get(enumName);
    257   }
    258 
    259   public void addEnum(ClassInfo cls) {
    260       cls.setPackage(this);
    261       this.mEnumsMap.put(cls.name(), cls);
    262   }
    263 
    264   public ClassInfo getException(String exceptionName) {
    265       return mExceptionsMap.get(exceptionName);
    266   }
    267 
    268   public ClassInfo getError(String errorName) {
    269       return mErrorsMap.get(errorName);
    270   }
    271 
    272   // TODO: Leftovers from ApiCheck that should be better merged.
    273   private HashMap<String, ClassInfo> mClasses = new HashMap<String, ClassInfo>();
    274 
    275   public void addClass(ClassInfo cls) {
    276     cls.setPackage(this);
    277     mClasses.put(cls.name(), cls);
    278   }
    279 
    280   public HashMap<String, ClassInfo> allClasses() {
    281     return mClasses;
    282   }
    283 
    284   public boolean isConsistent(PackageInfo pInfo) {
    285     boolean consistent = true;
    286     for (ClassInfo cInfo : mClasses.values()) {
    287       if (pInfo.mClasses.containsKey(cInfo.name())) {
    288         if (!cInfo.isConsistent(pInfo.mClasses.get(cInfo.name()))) {
    289           consistent = false;
    290         }
    291       } else {
    292         Errors.error(Errors.REMOVED_CLASS, cInfo.position(), "Removed public class "
    293             + cInfo.qualifiedName());
    294         consistent = false;
    295       }
    296     }
    297     for (ClassInfo cInfo : pInfo.mClasses.values()) {
    298       if (!mClasses.containsKey(cInfo.name())) {
    299         Errors.error(Errors.ADDED_CLASS, cInfo.position(), "Added class " + cInfo.name()
    300             + " to package " + pInfo.name());
    301         consistent = false;
    302       }
    303     }
    304     return consistent;
    305   }
    306 }
    307