001: /*
002: * Copyright 1998-2004 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package com.sun.tools.doclets.internal.toolkit.util;
027:
028: import com.sun.tools.doclets.internal.toolkit.*;
029: import com.sun.javadoc.*;
030: import java.util.*;
031:
032: /**
033: * Build Class Hierarchy for all the Classes. This class builds the Class
034: * Tree and the Interface Tree separately.
035: *
036: * This code is not part of an API.
037: * It is implementation that is subject to change.
038: * Do not use it as an API
039: *
040: * @see java.util.HashMap
041: * @see java.util.List
042: * @see com.sun.javadoc.Type
043: * @see com.sun.javadoc.ClassDoc
044: * @author Atul M Dambalkar
045: */
046: public class ClassTree {
047:
048: /**
049: * List of baseclasses. Contains only java.lang.Object. Can be used to get
050: * the mapped listing of sub-classes.
051: */
052: private List baseclasses = new ArrayList();
053:
054: /**
055: * Mapping for each Class with their SubClasses
056: */
057: private Map subclasses = new HashMap();
058:
059: /**
060: * List of base-interfaces. Contains list of all the interfaces who do not
061: * have super-interfaces. Can be used to get the mapped listing of
062: * sub-interfaces.
063: */
064: private List baseinterfaces = new ArrayList();
065:
066: /**
067: * Mapping for each Interface with their SubInterfaces
068: */
069: private Map subinterfaces = new HashMap();
070:
071: private List baseEnums = new ArrayList();
072: private Map subEnums = new HashMap();
073:
074: private List baseAnnotationTypes = new ArrayList();
075: private Map subAnnotationTypes = new HashMap();
076:
077: /**
078: * Mapping for each Interface with classes who implement it.
079: */
080: private Map implementingclasses = new HashMap();
081:
082: /**
083: * Constructor. Build the Tree using the Root of this Javadoc run.
084: *
085: * @param configuration the configuration of the doclet.
086: * @param noDeprecated Don't add deprecated classes in the class tree, if
087: * true.
088: */
089: public ClassTree(Configuration configuration, boolean noDeprecated) {
090: configuration.message.notice("doclet.Building_Tree");
091: buildTree(configuration.root.classes(), configuration);
092: }
093:
094: /**
095: * Constructor. Build the Tree using the Root of this Javadoc run.
096: *
097: * @param root Root of the Document.
098: * @param configuration The curren configuration of the doclet.
099: */
100: public ClassTree(RootDoc root, Configuration configuration) {
101: buildTree(root.classes(), configuration);
102: }
103:
104: /**
105: * Constructor. Build the tree for the given array of classes.
106: *
107: * @param classes Array of classes.
108: * @param configuration The curren configuration of the doclet.
109: */
110: public ClassTree(ClassDoc[] classes, Configuration configuration) {
111: buildTree(classes, configuration);
112: }
113:
114: /**
115: * Generate mapping for the sub-classes for every class in this run.
116: * Return the sub-class list for java.lang.Object which will be having
117: * sub-class listing for itself and also for each sub-class itself will
118: * have their own sub-class lists.
119: *
120: * @param classes all the classes in this run.
121: * @param configuration the current configuration of the doclet.
122: */
123: private void buildTree(ClassDoc[] classes,
124: Configuration configuration) {
125: for (int i = 0; i < classes.length; i++) {
126: if (configuration.nodeprecated
127: && classes[i].tags("deprecated").length > 0) {
128: continue;
129: }
130: if (classes[i].isEnum()) {
131: processType(classes[i], configuration, baseEnums,
132: subEnums);
133: } else if (classes[i].isClass()) {
134: processType(classes[i], configuration, baseclasses,
135: subclasses);
136: } else if (classes[i].isInterface()) {
137: processInterface(classes[i]);
138: List list = (List) implementingclasses.get(classes[i]);
139: if (list != null) {
140: Collections.sort(list);
141: }
142: } else if (classes[i].isAnnotationType()) {
143: processType(classes[i], configuration,
144: baseAnnotationTypes, subAnnotationTypes);
145: }
146: }
147:
148: Collections.sort(baseinterfaces);
149: for (Iterator it = subinterfaces.values().iterator(); it
150: .hasNext();) {
151: Collections.sort((List) it.next());
152: }
153: for (Iterator it = subclasses.values().iterator(); it.hasNext();) {
154: Collections.sort((List) it.next());
155: }
156: }
157:
158: /**
159: * For the class passed map it to it's own sub-class listing.
160: * For the Class passed, get the super class,
161: * if superclass is non null, (it is not "java.lang.Object")
162: * get the "value" from the hashmap for this key Class
163: * if entry not found create one and get that.
164: * add this Class as a sub class in the list
165: * Recurse till hits java.lang.Object Null SuperClass.
166: *
167: * @param cd class for which sub-class mapping to be generated.
168: * @param configuration the current configurtation of the doclet.
169: */
170: private void processType(ClassDoc cd, Configuration configuration,
171: List bases, Map subs) {
172: ClassDoc super class = Util.getFirstVisibleSuperClassCD(cd,
173: configuration);
174: if (super class != null) {
175: if (!add(subs, super class, cd)) {
176: return;
177: } else {
178: processType(super class, configuration, bases, subs);
179: }
180: } else { // cd is java.lang.Object, add it once to the list
181: if (!bases.contains(cd)) {
182: bases.add(cd);
183: }
184: }
185: List intfacs = Util.getAllInterfaces(cd, configuration);
186: for (Iterator iter = intfacs.iterator(); iter.hasNext();) {
187: add(implementingclasses, ((Type) iter.next()).asClassDoc(),
188: cd);
189: }
190: }
191:
192: /**
193: * For the interface passed get the interfaces which it extends, and then
194: * put this interface in the sub-interface list of those interfaces. Do it
195: * recursively. If a interface doesn't have super-interface just attach
196: * that interface in the list of all the baseinterfaces.
197: *
198: * @param cd Interface under consideration.
199: */
200: private void processInterface(ClassDoc cd) {
201: ClassDoc[] intfacs = cd.interfaces();
202: if (intfacs.length > 0) {
203: for (int i = 0; i < intfacs.length; i++) {
204: if (!add(subinterfaces, intfacs[i], cd)) {
205: return;
206: } else {
207: processInterface(intfacs[i]); // Recurse
208: }
209: }
210: } else {
211: // we need to add all the interfaces who do not have
212: // super-interfaces to baseinterfaces list to traverse them
213: if (!baseinterfaces.contains(cd)) {
214: baseinterfaces.add(cd);
215: }
216: }
217: }
218:
219: /**
220: * Adjust the Class Tree. Add the class interface in to it's super-class'
221: * or super-interface's sub-interface list.
222: *
223: * @param map the entire map.
224: * @param superclass java.lang.Object or the super-interface.
225: * @param cd sub-interface to be mapped.
226: * @returns boolean true if class added, false if class already processed.
227: */
228: private boolean add(Map map, ClassDoc super class, ClassDoc cd) {
229: List list = (List) map.get(super class);
230: if (list == null) {
231: list = new ArrayList();
232: map.put(super class, list);
233: }
234: if (list.contains(cd)) {
235: return false;
236: } else {
237: list.add(cd);
238: }
239: return true;
240: }
241:
242: /**
243: * From the map return the list of sub-classes or sub-interfaces. If list
244: * is null create a new one and return it.
245: *
246: * @param map The entire map.
247: * @param cd class for which the sub-class list is requested.
248: * @returns List Sub-Class list for the class passed.
249: */
250: private List get(Map map, ClassDoc cd) {
251: List list = (List) map.get(cd);
252: if (list == null) {
253: return new ArrayList();
254: }
255: return list;
256: }
257:
258: /**
259: * Return the sub-class list for the class passed.
260: *
261: * @param cd class whose sub-class list is required.
262: */
263: public List subclasses(ClassDoc cd) {
264: return get(subclasses, cd);
265: }
266:
267: /**
268: * Return the sub-interface list for the interface passed.
269: *
270: * @param cd interface whose sub-interface list is required.
271: */
272: public List subinterfaces(ClassDoc cd) {
273: return get(subinterfaces, cd);
274: }
275:
276: /**
277: * Return the list of classes which implement the interface passed.
278: *
279: * @param cd interface whose implementing-classes list is required.
280: */
281: public List implementingclasses(ClassDoc cd) {
282: List result = get(implementingclasses, cd);
283: List subinterfaces = allSubs(cd, false);
284:
285: //If class x implements a subinterface of cd, then it follows
286: //that class x implements cd.
287: Iterator implementingClassesIter, subInterfacesIter = subinterfaces
288: .listIterator();
289: ClassDoc c;
290: while (subInterfacesIter.hasNext()) {
291: implementingClassesIter = implementingclasses(
292: (ClassDoc) subInterfacesIter.next()).listIterator();
293: while (implementingClassesIter.hasNext()) {
294: c = (ClassDoc) implementingClassesIter.next();
295: if (!result.contains(c)) {
296: result.add(c);
297: }
298: }
299: }
300: Collections.sort(result);
301: return result;
302: }
303:
304: /**
305: * Return the sub-class/interface list for the class/interface passed.
306: *
307: * @param cd class/interface whose sub-class/interface list is required.
308: * @param isEnum true if the subclasses should be forced to come from the
309: * enum tree.
310: */
311: public List subs(ClassDoc cd, boolean isEnum) {
312: if (isEnum) {
313: return get(subEnums, cd);
314: } else if (cd.isAnnotationType()) {
315: return get(subAnnotationTypes, cd);
316: } else if (cd.isInterface()) {
317: return get(subinterfaces, cd);
318: } else if (cd.isClass()) {
319: return get(subclasses, cd);
320: } else {
321: return null;
322: }
323:
324: }
325:
326: /**
327: * Return a list of all direct or indirect, sub-classes and subinterfaces
328: * of the ClassDoc argument.
329: *
330: * @param cd ClassDoc whose sub-classes or sub-interfaces are requested.
331: * @param isEnum true if the subclasses should be forced to come from the
332: * enum tree.
333: */
334: public List allSubs(ClassDoc cd, boolean isEnum) {
335: List list = subs(cd, isEnum);
336: for (int i = 0; i < list.size(); i++) {
337: cd = (ClassDoc) list.get(i);
338: List tlist = subs(cd, isEnum);
339: for (int j = 0; j < tlist.size(); j++) {
340: ClassDoc tcd = (ClassDoc) tlist.get(j);
341: if (!list.contains(tcd)) {
342: list.add(tcd);
343: }
344: }
345: }
346: Collections.sort(list);
347: return list;
348: }
349:
350: /**
351: * Return the base-classes list. This will have only one element namely
352: * thw classdoc for java.lang.Object, since this is the base class for all
353: * classes.
354: */
355: public List baseclasses() {
356: return baseclasses;
357: }
358:
359: /**
360: * Return the list of base interfaces. This is the list of interfaces
361: * which do not have super-interface.
362: */
363: public List baseinterfaces() {
364: return baseinterfaces;
365: }
366:
367: /**
368: * Return the list of base enums. This is the list of enums
369: * which do not have super-enums.
370: */
371: public List baseEnums() {
372: return baseEnums;
373: }
374:
375: /**
376: * Return the list of base annotation types. This is the list of
377: * annotation types which do not have super-annotation types.
378: */
379: public List baseAnnotationTypes() {
380: return baseAnnotationTypes;
381: }
382: }
|