blob: e997b279957e4e092517cc30fb6f189926813ba8 [file] [log] [blame]
Ben Dodson920dbbb2010-08-04 15:21:06 -07001/*
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
17package com.google.doclava;
18
Mathieu11b17962013-06-07 17:24:18 -050019import com.google.doclava.apicheck.ApiInfo;
Ben Dodson920dbbb2010-08-04 15:21:06 -070020import com.google.clearsilver.jsilver.data.Data;
21
22import com.sun.javadoc.*;
23import java.util.*;
24
25public class PackageInfo extends DocInfo implements ContainerInfo {
26 public static final String DEFAULT_PACKAGE = "default package";
Scott Main3c1a6b22010-10-15 17:34:04 -070027
Ben Dodson920dbbb2010-08-04 15:21:06 -070028 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;
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -070043 initializeMaps();
Ben Dodson920dbbb2010-08-04 15:21:06 -070044 }
Scott Main3c1a6b22010-10-15 17:34:04 -070045
Ben Dodson920dbbb2010-08-04 15:21:06 -070046 public PackageInfo(String name) {
47 super("", null);
48 mName = name;
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -070049 initializeMaps();
Ben Dodson920dbbb2010-08-04 15:21:06 -070050 }
Scott Main3c1a6b22010-10-15 17:34:04 -070051
Ben Dodson920dbbb2010-08-04 15:21:06 -070052 public PackageInfo(String name, SourcePositionInfo position) {
53 super("", position);
Scott Main3c1a6b22010-10-15 17:34:04 -070054
Ben Dodson920dbbb2010-08-04 15:21:06 -070055 if (name.isEmpty()) {
56 mName = "default package";
57 } else {
58 mName = name;
59 }
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -070060 initializeMaps();
61 }
62
63 private void initializeMaps() {
Brett Chabot700b9f22013-10-04 16:57:39 -070064 mAnnotationsMap = new HashMap<String, ClassInfo>();
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -070065 mInterfacesMap = new HashMap<String, ClassInfo>();
66 mOrdinaryClassesMap = new HashMap<String, ClassInfo>();
67 mEnumsMap = new HashMap<String, ClassInfo>();
68 mExceptionsMap = new HashMap<String, ClassInfo>();
69 mErrorsMap = new HashMap<String, ClassInfo>();
Ben Dodson920dbbb2010-08-04 15:21:06 -070070 }
71
72 public String htmlPage() {
73 String s = mName;
74 s = s.replace('.', '/');
75 s += "/package-summary.html";
76 s = Doclava.javadocDir + s;
77 return s;
78 }
79
Ben Dodson920dbbb2010-08-04 15:21:06 -070080 @Override
81 public ContainerInfo parent() {
82 return null;
83 }
84
85 @Override
86 public boolean isHidden() {
Hui Shu5118ffe2014-02-18 14:06:42 -080087 if (mHidden == null) {
Adam Metcalff2d2e932013-08-19 17:12:24 -070088 if (hasHideComment()) {
89 // We change the hidden value of the package if a class wants to be not hidden.
Hui Shu5118ffe2014-02-18 14:06:42 -080090 ClassInfo[][] types = new ClassInfo[][] { annotations(), interfaces(), ordinaryClasses(),
91 enums(), exceptions() };
Adam Metcalff2d2e932013-08-19 17:12:24 -070092 for (ClassInfo[] type : types) {
93 if (type != null) {
94 for (ClassInfo c : type) {
95 if (c.hasShowAnnotation()) {
Hui Shu5118ffe2014-02-18 14:06:42 -080096 mHidden = false;
Adam Metcalff2d2e932013-08-19 17:12:24 -070097 return false;
98 }
99 }
100 }
101 }
Hui Shu5118ffe2014-02-18 14:06:42 -0800102 mHidden = true;
Adam Metcalff2d2e932013-08-19 17:12:24 -0700103 } else {
Hui Shu5118ffe2014-02-18 14:06:42 -0800104 mHidden = false;
Adam Metcalff2d2e932013-08-19 17:12:24 -0700105 }
106 }
Hui Shu5118ffe2014-02-18 14:06:42 -0800107 return mHidden;
108 }
109
110 @Override
111 public boolean isRemoved() {
112 if (mRemoved == null) {
113 if (hasRemovedComment()) {
114 // We change the removed value of the package if a class wants to be not hidden.
115 ClassInfo[][] types = new ClassInfo[][] { annotations(), interfaces(), ordinaryClasses(),
116 enums(), exceptions() };
117 for (ClassInfo[] type : types) {
118 if (type != null) {
119 for (ClassInfo c : type) {
120 if (c.hasShowAnnotation()) {
121 mRemoved = false;
122 return false;
123 }
124 }
125 }
126 }
127 mRemoved = true;
128 } else {
129 mRemoved = false;
130 }
131 }
132
133 return mRemoved;
134 }
135
136 @Override
137 public boolean isHiddenOrRemoved() {
138 return isHidden() || isRemoved();
Adam Metcalff2d2e932013-08-19 17:12:24 -0700139 }
140
141 /**
142 * Used by ClassInfo to determine packages default visability before annoations.
143 */
144 public boolean hasHideComment() {
Hui Shu5118ffe2014-02-18 14:06:42 -0800145 if (mHiddenByComment == null) {
146 mHiddenByComment = comment().isHidden();
Adam Metcalff2d2e932013-08-19 17:12:24 -0700147 }
Hui Shu5118ffe2014-02-18 14:06:42 -0800148 return mHiddenByComment;
149 }
150
151 public boolean hasRemovedComment() {
152 if (mRemovedByComment == null) {
153 mRemovedByComment = comment().isRemoved();
154 }
155
156 return mRemovedByComment;
Ben Dodson920dbbb2010-08-04 15:21:06 -0700157 }
158
159 public boolean checkLevel() {
160 // TODO should return false if all classes are hidden but the package isn't.
161 // We don't have this so I'm not doing it now.
Hui Shu5118ffe2014-02-18 14:06:42 -0800162 return !isHiddenOrRemoved();
Ben Dodson920dbbb2010-08-04 15:21:06 -0700163 }
164
165 public String name() {
166 return mName;
167 }
168
169 public String qualifiedName() {
170 return mName;
171 }
172
173 public TagInfo[] inlineTags() {
174 return comment().tags();
175 }
176
177 public TagInfo[] firstSentenceTags() {
178 return comment().briefTags();
179 }
180
Hui Shu5118ffe2014-02-18 14:06:42 -0800181 /**
182 * @param classes the Array of ClassInfo to be filtered
183 * @return an Array of ClassInfo without any hidden or removed classes
184 */
185 public static ClassInfo[] filterHiddenAndRemoved(ClassInfo[] classes) {
Ben Dodson920dbbb2010-08-04 15:21:06 -0700186 ArrayList<ClassInfo> out = new ArrayList<ClassInfo>();
187
188 for (ClassInfo cl : classes) {
Hui Shu5118ffe2014-02-18 14:06:42 -0800189 if (!cl.isHiddenOrRemoved()) {
Ben Dodson920dbbb2010-08-04 15:21:06 -0700190 out.add(cl);
191 }
192 }
193
194 return out.toArray(new ClassInfo[0]);
195 }
196
197 public void makeLink(Data data, String base) {
198 if (checkLevel()) {
199 data.setValue(base + ".link", htmlPage());
200 }
201 data.setValue(base + ".name", name());
202 data.setValue(base + ".since", getSince());
203 }
204
205 public void makeClassLinkListHDF(Data data, String base) {
206 makeLink(data, base);
Brett Chabot700b9f22013-10-04 16:57:39 -0700207 ClassInfo.makeLinkListHDF(data, base + ".annotations", annotations());
Ben Dodson920dbbb2010-08-04 15:21:06 -0700208 ClassInfo.makeLinkListHDF(data, base + ".interfaces", interfaces());
209 ClassInfo.makeLinkListHDF(data, base + ".classes", ordinaryClasses());
210 ClassInfo.makeLinkListHDF(data, base + ".enums", enums());
211 ClassInfo.makeLinkListHDF(data, base + ".exceptions", exceptions());
212 ClassInfo.makeLinkListHDF(data, base + ".errors", errors());
213 data.setValue(base + ".since", getSince());
214 }
215
Brett Chabot700b9f22013-10-04 16:57:39 -0700216 public ClassInfo[] annotations() {
217 if (mAnnotations == null) {
218 mAnnotations =
Hui Shu5118ffe2014-02-18 14:06:42 -0800219 ClassInfo.sortByName(filterHiddenAndRemoved(
220 Converter.convertClasses(mPackage.annotationTypes())));
Brett Chabot700b9f22013-10-04 16:57:39 -0700221 }
222 return mAnnotations;
223 }
224
Ben Dodson920dbbb2010-08-04 15:21:06 -0700225 public ClassInfo[] interfaces() {
226 if (mInterfaces == null) {
227 mInterfaces =
Hui Shu5118ffe2014-02-18 14:06:42 -0800228 ClassInfo.sortByName(filterHiddenAndRemoved(
229 Converter.convertClasses(mPackage.interfaces())));
Ben Dodson920dbbb2010-08-04 15:21:06 -0700230 }
231 return mInterfaces;
232 }
233
234 public ClassInfo[] ordinaryClasses() {
235 if (mOrdinaryClasses == null) {
236 mOrdinaryClasses =
Hui Shu5118ffe2014-02-18 14:06:42 -0800237 ClassInfo.sortByName(filterHiddenAndRemoved(
238 Converter.convertClasses(mPackage.ordinaryClasses())));
Ben Dodson920dbbb2010-08-04 15:21:06 -0700239 }
240 return mOrdinaryClasses;
241 }
242
243 public ClassInfo[] enums() {
244 if (mEnums == null) {
Hui Shu5118ffe2014-02-18 14:06:42 -0800245 mEnums = ClassInfo.sortByName(filterHiddenAndRemoved(
246 Converter.convertClasses(mPackage.enums())));
Ben Dodson920dbbb2010-08-04 15:21:06 -0700247 }
248 return mEnums;
249 }
250
251 public ClassInfo[] exceptions() {
252 if (mExceptions == null) {
253 mExceptions =
Hui Shu5118ffe2014-02-18 14:06:42 -0800254 ClassInfo.sortByName(filterHiddenAndRemoved(
255 Converter.convertClasses(mPackage.exceptions())));
Ben Dodson920dbbb2010-08-04 15:21:06 -0700256 }
257 return mExceptions;
258 }
259
260 public ClassInfo[] errors() {
261 if (mErrors == null) {
Hui Shu5118ffe2014-02-18 14:06:42 -0800262 mErrors = ClassInfo.sortByName(filterHiddenAndRemoved(
263 Converter.convertClasses(mPackage.errors())));
Ben Dodson920dbbb2010-08-04 15:21:06 -0700264 }
265 return mErrors;
266 }
267
Mathieu11b17962013-06-07 17:24:18 -0500268 public ApiInfo containingApi() {
269 return mContainingApi;
270 }
271
272 public void setContainingApi(ApiInfo api) {
273 mContainingApi = api;
274 }
275
Ben Dodson920dbbb2010-08-04 15:21:06 -0700276 // in hashed containers, treat the name as the key
277 @Override
278 public int hashCode() {
279 return mName.hashCode();
280 }
281
Hui Shu5118ffe2014-02-18 14:06:42 -0800282 private Boolean mHidden = null;
283 private Boolean mHiddenByComment = null;
284 private Boolean mRemoved = null;
285 private Boolean mRemovedByComment = null;
Ben Dodson920dbbb2010-08-04 15:21:06 -0700286 private String mName;
287 private PackageDoc mPackage;
Mathieu11b17962013-06-07 17:24:18 -0500288 private ApiInfo mContainingApi;
Brett Chabot700b9f22013-10-04 16:57:39 -0700289 private ClassInfo[] mAnnotations;
Ben Dodson920dbbb2010-08-04 15:21:06 -0700290 private ClassInfo[] mInterfaces;
291 private ClassInfo[] mOrdinaryClasses;
292 private ClassInfo[] mEnums;
293 private ClassInfo[] mExceptions;
294 private ClassInfo[] mErrors;
Scott Main3c1a6b22010-10-15 17:34:04 -0700295
Brett Chabot700b9f22013-10-04 16:57:39 -0700296 private HashMap<String, ClassInfo> mAnnotationsMap;
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700297 private HashMap<String, ClassInfo> mInterfacesMap;
298 private HashMap<String, ClassInfo> mOrdinaryClassesMap;
299 private HashMap<String, ClassInfo> mEnumsMap;
300 private HashMap<String, ClassInfo> mExceptionsMap;
301 private HashMap<String, ClassInfo> mErrorsMap;
302
303
304 public ClassInfo getClass(String className) {
305 ClassInfo cls = mInterfacesMap.get(className);
306
307 if (cls != null) {
308 return cls;
309 }
310
311 cls = mOrdinaryClassesMap.get(className);
312
313 if (cls != null) {
314 return cls;
315 }
316
317 cls = mEnumsMap.get(className);
318
319 if (cls != null) {
320 return cls;
321 }
322
323 cls = mEnumsMap.get(className);
324
325 if (cls != null) {
326 return cls;
327 }
Brett Chabot700b9f22013-10-04 16:57:39 -0700328 cls = mAnnotationsMap.get(className);
329
330 if (cls != null) {
331 return cls;
332 }
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700333
334 return mErrorsMap.get(className);
335 }
336
Brett Chabot700b9f22013-10-04 16:57:39 -0700337 public void addAnnotation(ClassInfo cls) {
338 cls.setPackage(this);
339 mAnnotationsMap.put(cls.name(), cls);
340 }
341
342 public ClassInfo getAnnotation(String annotationName) {
343 return mAnnotationsMap.get(annotationName);
344 }
345
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700346 public void addInterface(ClassInfo cls) {
Mathieu11b17962013-06-07 17:24:18 -0500347 cls.setPackage(this);
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700348 mInterfacesMap.put(cls.name(), cls);
349 }
350
351 public ClassInfo getInterface(String interfaceName) {
352 return mInterfacesMap.get(interfaceName);
353 }
354
355 public ClassInfo getOrdinaryClass(String className) {
356 return mOrdinaryClassesMap.get(className);
357 }
358
359 public void addOrdinaryClass(ClassInfo cls) {
Mathieu11b17962013-06-07 17:24:18 -0500360 cls.setPackage(this);
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700361 mOrdinaryClassesMap.put(cls.name(), cls);
362 }
363
364 public ClassInfo getEnum(String enumName) {
365 return mEnumsMap.get(enumName);
366 }
367
368 public void addEnum(ClassInfo cls) {
Mathieu11b17962013-06-07 17:24:18 -0500369 cls.setPackage(this);
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700370 this.mEnumsMap.put(cls.name(), cls);
371 }
372
373 public ClassInfo getException(String exceptionName) {
374 return mExceptionsMap.get(exceptionName);
375 }
376
377 public ClassInfo getError(String errorName) {
378 return mErrorsMap.get(errorName);
379 }
380
Ben Dodson920dbbb2010-08-04 15:21:06 -0700381 // TODO: Leftovers from ApiCheck that should be better merged.
382 private HashMap<String, ClassInfo> mClasses = new HashMap<String, ClassInfo>();
Scott Main3c1a6b22010-10-15 17:34:04 -0700383
Mathieu11b17962013-06-07 17:24:18 -0500384 public void addClass(ClassInfo cls) {
385 cls.setPackage(this);
386 mClasses.put(cls.name(), cls);
Ben Dodson920dbbb2010-08-04 15:21:06 -0700387 }
388
389 public HashMap<String, ClassInfo> allClasses() {
390 return mClasses;
391 }
Scott Main3c1a6b22010-10-15 17:34:04 -0700392
Ben Dodson920dbbb2010-08-04 15:21:06 -0700393 public boolean isConsistent(PackageInfo pInfo) {
394 boolean consistent = true;
395 for (ClassInfo cInfo : mClasses.values()) {
396 if (pInfo.mClasses.containsKey(cInfo.name())) {
397 if (!cInfo.isConsistent(pInfo.mClasses.get(cInfo.name()))) {
398 consistent = false;
399 }
400 } else {
401 Errors.error(Errors.REMOVED_CLASS, cInfo.position(), "Removed public class "
402 + cInfo.qualifiedName());
403 consistent = false;
404 }
405 }
406 for (ClassInfo cInfo : pInfo.mClasses.values()) {
407 if (!mClasses.containsKey(cInfo.name())) {
408 Errors.error(Errors.ADDED_CLASS, cInfo.position(), "Added class " + cInfo.name()
409 + " to package " + pInfo.name());
410 consistent = false;
411 }
412 }
413 return consistent;
414 }
415}