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 PackageInfo(PackageDoc pkg, String name, SourcePositionInfo position)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 PackageInfo(String name)45 public PackageInfo(String name) { 46 super("", null); 47 mName = name; 48 initializeMaps(); 49 } 50 PackageInfo(String name, SourcePositionInfo position)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 initializeMaps()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 htmlPage()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 parent()79 public ContainerInfo parent() { 80 return null; 81 } 82 83 @Override isHidden()84 public boolean isHidden() { 85 return comment().isHidden(); 86 } 87 checkLevel()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 name()94 public String name() { 95 return mName; 96 } 97 qualifiedName()98 public String qualifiedName() { 99 return mName; 100 } 101 inlineTags()102 public TagInfo[] inlineTags() { 103 return comment().tags(); 104 } 105 firstSentenceTags()106 public TagInfo[] firstSentenceTags() { 107 return comment().briefTags(); 108 } 109 filterHidden(ClassInfo[] classes)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 makeLink(Data data, String base)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 makeClassLinkListHDF(Data data, String base)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 interfaces()140 public ClassInfo[] interfaces() { 141 if (mInterfaces == null) { 142 mInterfaces = 143 ClassInfo.sortByName(filterHidden(Converter.convertClasses(mPackage.interfaces()))); 144 } 145 return mInterfaces; 146 } 147 ordinaryClasses()148 public ClassInfo[] ordinaryClasses() { 149 if (mOrdinaryClasses == null) { 150 mOrdinaryClasses = 151 ClassInfo.sortByName(filterHidden(Converter.convertClasses(mPackage.ordinaryClasses()))); 152 } 153 return mOrdinaryClasses; 154 } 155 enums()156 public ClassInfo[] enums() { 157 if (mEnums == null) { 158 mEnums = ClassInfo.sortByName(filterHidden(Converter.convertClasses(mPackage.enums()))); 159 } 160 return mEnums; 161 } 162 exceptions()163 public ClassInfo[] exceptions() { 164 if (mExceptions == null) { 165 mExceptions = 166 ClassInfo.sortByName(filterHidden(Converter.convertClasses(mPackage.exceptions()))); 167 } 168 return mExceptions; 169 } 170 errors()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 hashCode()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 getClass(String className)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 addInterface(ClassInfo cls)227 public void addInterface(ClassInfo cls) { 228 mInterfacesMap.put(cls.name(), cls); 229 } 230 getInterface(String interfaceName)231 public ClassInfo getInterface(String interfaceName) { 232 return mInterfacesMap.get(interfaceName); 233 } 234 getOrdinaryClass(String className)235 public ClassInfo getOrdinaryClass(String className) { 236 return mOrdinaryClassesMap.get(className); 237 } 238 addOrdinaryClass(ClassInfo cls)239 public void addOrdinaryClass(ClassInfo cls) { 240 mOrdinaryClassesMap.put(cls.name(), cls); 241 } 242 getEnum(String enumName)243 public ClassInfo getEnum(String enumName) { 244 return mEnumsMap.get(enumName); 245 } 246 addEnum(ClassInfo cls)247 public void addEnum(ClassInfo cls) { 248 this.mEnumsMap.put(cls.name(), cls); 249 } 250 getException(String exceptionName)251 public ClassInfo getException(String exceptionName) { 252 return mExceptionsMap.get(exceptionName); 253 } 254 getError(String errorName)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 addClass(ClassInfo cl)262 public void addClass(ClassInfo cl) { 263 mClasses.put(cl.name(), cl); 264 } 265 allClasses()266 public HashMap<String, ClassInfo> allClasses() { 267 return mClasses; 268 } 269 isConsistent(PackageInfo pInfo)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