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