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