001: /*
002: * Copyright 1998-2006 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.javadoc.*;
029: import java.util.*;
030:
031: /**
032: * Map all class uses for a given class.
033: *
034: * This code is not part of an API.
035: * It is implementation that is subject to change.
036: * Do not use it as an API
037: *
038: * @since 1.2
039: * @author Robert G. Field
040: */
041: public class ClassUseMapper {
042:
043: private final ClassTree classtree;
044:
045: /**
046: * Mapping of ClassDocs to set of PackageDoc used by that class.
047: * Entries may be null.
048: */
049: public Map classToPackage = new HashMap();
050:
051: /**
052: * Mapping of Annotations to set of PackageDoc that use the annotation.
053: */
054: public Map classToPackageAnnotations = new HashMap();
055:
056: /**
057: * Mapping of ClassDocs to set of ClassDoc used by that class.
058: * Entries may be null.
059: */
060: public Map classToClass = new HashMap();
061:
062: /**
063: * Mapping of ClassDocs to list of ClassDoc which are direct or
064: * indirect subclasses of that class.
065: * Entries may be null.
066: */
067: public Map classToSubclass = new HashMap();
068:
069: /**
070: * Mapping of ClassDocs to list of ClassDoc which are direct or
071: * indirect subinterfaces of that interface.
072: * Entries may be null.
073: */
074: public Map classToSubinterface = new HashMap();
075:
076: /**
077: * Mapping of ClassDocs to list of ClassDoc which implement
078: * this interface.
079: * Entries may be null.
080: */
081: public Map classToImplementingClass = new HashMap();
082:
083: /**
084: * Mapping of ClassDocs to list of FieldDoc declared as that class.
085: * Entries may be null.
086: */
087: public Map classToField = new HashMap();
088:
089: /**
090: * Mapping of ClassDocs to list of MethodDoc returning that class.
091: * Entries may be null.
092: */
093: public Map classToMethodReturn = new HashMap();
094:
095: /**
096: * Mapping of ClassDocs to list of MethodDoc having that class
097: * as an arg.
098: * Entries may be null.
099: */
100: public Map classToMethodArgs = new HashMap();
101:
102: /**
103: * Mapping of ClassDocs to list of MethodDoc which throws that class.
104: * Entries may be null.
105: */
106: public Map classToMethodThrows = new HashMap();
107:
108: /**
109: * Mapping of ClassDocs to list of ConstructorDoc having that class
110: * as an arg.
111: * Entries may be null.
112: */
113: public Map classToConstructorArgs = new HashMap();
114:
115: /**
116: * Mapping of ClassDocs to list of ConstructorDoc which throws that class.
117: * Entries may be null.
118: */
119: public Map classToConstructorThrows = new HashMap();
120:
121: /**
122: * The mapping of AnnotationTypeDocs to constructors that use them.
123: */
124: public Map classToConstructorAnnotations = new HashMap();
125:
126: /**
127: * The mapping of AnnotationTypeDocs to Constructor parameters that use them.
128: */
129: public Map classToConstructorParamAnnotation = new HashMap();
130:
131: /**
132: * The mapping of ClassDocs to Constructor arguments that use them as type parameters.
133: */
134: public Map classToConstructorDocArgTypeParam = new HashMap();
135:
136: /**
137: * The mapping of ClassDocs to ClassDocs that use them as type parameters.
138: */
139: public Map classToClassTypeParam = new HashMap();
140:
141: /**
142: * The mapping of AnnotationTypeDocs to ClassDocs that use them.
143: */
144: public Map classToClassAnnotations = new HashMap();
145:
146: /**
147: * The mapping of ClassDocs to ExecutableMemberDocs that use them as type parameters.
148: */
149: public Map classToExecMemberDocTypeParam = new HashMap();
150:
151: /**
152: * The mapping of ClassDocs to ExecutableMemberDocs arguments that use them as type parameters.
153: */
154: public Map classToExecMemberDocArgTypeParam = new HashMap();
155:
156: /**
157: * The mapping of AnnotationTypeDocs to ExecutableMemberDocs that use them.
158: */
159: public Map classToExecMemberDocAnnotations = new HashMap();
160:
161: /**
162: * The mapping of ClassDocs to ExecutableMemberDocs that have return type
163: * with type parameters of that class.
164: */
165: public Map classToExecMemberDocReturnTypeParam = new HashMap();
166:
167: /**
168: * The mapping of AnnotationTypeDocs to MethodDoc parameters that use them.
169: */
170: public Map classToExecMemberDocParamAnnotation = new HashMap();
171:
172: /**
173: * The mapping of ClassDocs to FieldDocs that use them as type parameters.
174: */
175: public Map classToFieldDocTypeParam = new HashMap();
176:
177: /**
178: * The mapping of AnnotationTypeDocs to FieldDocs that use them.
179: */
180: public Map annotationToFieldDoc = new HashMap();
181:
182: public ClassUseMapper(RootDoc root, ClassTree classtree) {
183: this .classtree = classtree;
184:
185: // Map subclassing, subinterfacing implementing, ...
186: for (Iterator it = classtree.baseclasses().iterator(); it
187: .hasNext();) {
188: subclasses((ClassDoc) it.next());
189: }
190: for (Iterator it = classtree.baseinterfaces().iterator(); it
191: .hasNext();) {
192: // does subinterfacing as side-effect
193: implementingClasses((ClassDoc) it.next());
194: }
195: // Map methods, fields, constructors using a class.
196: ClassDoc[] classes = root.classes();
197: for (int i = 0; i < classes.length; i++) {
198: PackageDoc pkg = classes[i].containingPackage();
199: mapAnnotations(classToPackageAnnotations, pkg, pkg);
200: ClassDoc cd = classes[i];
201: mapTypeParameters(classToClassTypeParam, cd, cd);
202: mapAnnotations(classToClassAnnotations, cd, cd);
203: FieldDoc[] fields = cd.fields();
204: for (int j = 0; j < fields.length; j++) {
205: FieldDoc fd = fields[j];
206: mapTypeParameters(classToFieldDocTypeParam, fd, fd);
207: mapAnnotations(annotationToFieldDoc, fd, fd);
208: if (!fd.type().isPrimitive()) {
209: add(classToField, fd.type().asClassDoc(), fd);
210: }
211: }
212: ConstructorDoc[] cons = cd.constructors();
213: for (int j = 0; j < cons.length; j++) {
214: mapAnnotations(classToConstructorAnnotations, cons[j],
215: cons[j]);
216: mapExecutable(cons[j]);
217: }
218: MethodDoc[] meths = cd.methods();
219: for (int j = 0; j < meths.length; j++) {
220: MethodDoc md = meths[j];
221: mapExecutable(md);
222: mapTypeParameters(classToExecMemberDocTypeParam, md, md);
223: mapAnnotations(classToExecMemberDocAnnotations, md, md);
224: if (!(md.returnType().isPrimitive() || md.returnType() instanceof TypeVariable)) {
225: mapTypeParameters(
226: classToExecMemberDocReturnTypeParam, md
227: .returnType(), md);
228: add(classToMethodReturn, md.returnType()
229: .asClassDoc(), md);
230: }
231: }
232: }
233: }
234:
235: /**
236: * Return all subclasses of a class AND fill-in classToSubclass map.
237: */
238: private Collection subclasses(ClassDoc cd) {
239: Collection ret = (Collection) classToSubclass.get(cd
240: .qualifiedName());
241: if (ret == null) {
242: ret = new TreeSet();
243: List subs = classtree.subclasses(cd);
244: if (subs != null) {
245: ret.addAll(subs);
246: for (Iterator it = subs.iterator(); it.hasNext();) {
247: ret.addAll(subclasses((ClassDoc) it.next()));
248: }
249: }
250: addAll(classToSubclass, cd, ret);
251: }
252: return ret;
253: }
254:
255: /**
256: * Return all subinterfaces of an interface AND fill-in classToSubinterface map.
257: */
258: private Collection subinterfaces(ClassDoc cd) {
259: Collection ret = (Collection) classToSubinterface.get(cd
260: .qualifiedName());
261: if (ret == null) {
262: ret = new TreeSet();
263: List subs = classtree.subinterfaces(cd);
264: if (subs != null) {
265: ret.addAll(subs);
266: for (Iterator it = subs.iterator(); it.hasNext();) {
267: ret.addAll(subinterfaces((ClassDoc) it.next()));
268: }
269: }
270: addAll(classToSubinterface, cd, ret);
271: }
272: return ret;
273: }
274:
275: /**
276: * Return all implementing classes of an interface (including
277: * all subclasses of implementing classes and all classes
278: * implementing subinterfaces) AND fill-in both classToImplementingClass
279: * and classToSubinterface maps.
280: */
281: private Collection implementingClasses(ClassDoc cd) {
282: Collection ret = (List) classToImplementingClass.get(cd
283: .qualifiedName());
284: if (ret == null) {
285: ret = new TreeSet();
286: List impl = classtree.implementingclasses(cd);
287: if (impl != null) {
288: ret.addAll(impl);
289: for (Iterator it = impl.iterator(); it.hasNext();) {
290: ret.addAll(subclasses((ClassDoc) it.next()));
291: }
292: }
293: for (Iterator it = subinterfaces(cd).iterator(); it
294: .hasNext();) {
295: ret.addAll(implementingClasses((ClassDoc) it.next()));
296: }
297: addAll(classToImplementingClass, cd, ret);
298: }
299: return ret;
300: }
301:
302: /**
303: * Determine classes used by a method or constructor, so they can be
304: * inverse mapped.
305: */
306: private void mapExecutable(ExecutableMemberDoc em) {
307: Parameter[] params = em.parameters();
308: boolean isConstructor = em.isConstructor();
309: List classArgs = new ArrayList();
310: for (int k = 0; k < params.length; k++) {
311: Type pcd = params[k].type();
312: // primitives don't get mapped, also avoid dups
313: if ((!params[k].type().isPrimitive())
314: && !classArgs.contains(pcd)
315: && !(pcd instanceof TypeVariable)) {
316: add(isConstructor ? classToConstructorArgs
317: : classToMethodArgs, pcd.asClassDoc(), em);
318: classArgs.add(pcd);
319: mapTypeParameters(
320: isConstructor ? classToConstructorDocArgTypeParam
321: : classToExecMemberDocArgTypeParam,
322: pcd, em);
323: }
324: mapAnnotations(
325: isConstructor ? classToConstructorParamAnnotation
326: : classToExecMemberDocParamAnnotation,
327: params[k], em);
328: }
329: ClassDoc[] thr = em.thrownExceptions();
330: for (int k = 0; k < thr.length; k++) {
331: add(isConstructor ? classToConstructorThrows
332: : classToMethodThrows, thr[k], em);
333: }
334: }
335:
336: private List refList(Map map, ClassDoc cd) {
337: List list = (List) map.get(cd.qualifiedName());
338: if (list == null) {
339: list = new ArrayList();
340: map.put(cd.qualifiedName(), list);
341: }
342: return list;
343: }
344:
345: private Set packageSet(ClassDoc cd) {
346: Set pkgSet = (Set) classToPackage.get(cd.qualifiedName());
347: if (pkgSet == null) {
348: pkgSet = new TreeSet();
349: classToPackage.put(cd.qualifiedName(), pkgSet);
350: }
351: return pkgSet;
352: }
353:
354: private Set classSet(ClassDoc cd) {
355: Set clsSet = (Set) classToClass.get(cd.qualifiedName());
356: if (clsSet == null) {
357: clsSet = new TreeSet();
358: classToClass.put(cd.qualifiedName(), clsSet);
359: }
360: return clsSet;
361: }
362:
363: private void add(Map map, ClassDoc cd, ProgramElementDoc ref) {
364: // add to specified map
365: refList(map, cd).add(ref);
366:
367: // add ref's package to package map and class map
368: packageSet(cd).add(ref.containingPackage());
369:
370: classSet(cd).add(
371: ref instanceof MemberDoc ? ((MemberDoc) ref)
372: .containingClass() : ref);
373: }
374:
375: private void addAll(Map map, ClassDoc cd, Collection refs) {
376: if (refs == null) {
377: return;
378: }
379: // add to specified map
380: refList(map, cd).addAll(refs);
381:
382: Set pkgSet = packageSet(cd);
383: Set clsSet = classSet(cd);
384: // add ref's package to package map and class map
385: for (Iterator it = refs.iterator(); it.hasNext();) {
386: ProgramElementDoc pedoc = (ProgramElementDoc) it.next();
387: pkgSet.add(pedoc.containingPackage());
388: clsSet.add(pedoc instanceof MemberDoc ? ((MemberDoc) pedoc)
389: .containingClass() : pedoc);
390:
391: }
392: }
393:
394: /**
395: * Map the ClassDocs to the ProgramElementDocs that use them as
396: * type parameters.
397: *
398: * @param map the map the insert the information into.
399: * @param doc the doc whose type parameters are being checked.
400: * @param holder the holder that owns the type parameters.
401: */
402: private void mapTypeParameters(Map map, Object doc,
403: ProgramElementDoc holder) {
404: TypeVariable[] typeVariables;
405: if (doc instanceof ClassDoc) {
406: typeVariables = ((ClassDoc) doc).typeParameters();
407: } else if (doc instanceof WildcardType) {
408: Type[] extendsBounds = ((WildcardType) doc).extendsBounds();
409: for (int k = 0; k < extendsBounds.length; k++) {
410: addTypeParameterToMap(map, extendsBounds[k], holder);
411: }
412: Type[] super Bounds = ((WildcardType) doc).super Bounds();
413: for (int k = 0; k < super Bounds.length; k++) {
414: addTypeParameterToMap(map, super Bounds[k], holder);
415: }
416: return;
417: } else if (doc instanceof ParameterizedType) {
418: Type[] typeArguments = ((ParameterizedType) doc)
419: .typeArguments();
420: for (int k = 0; k < typeArguments.length; k++) {
421: addTypeParameterToMap(map, typeArguments[k], holder);
422: }
423: return;
424: } else if (doc instanceof ExecutableMemberDoc) {
425: typeVariables = ((ExecutableMemberDoc) doc)
426: .typeParameters();
427: } else if (doc instanceof FieldDoc) {
428: Type fieldType = ((FieldDoc) doc).type();
429: mapTypeParameters(map, fieldType, holder);
430: return;
431: } else {
432: return;
433: }
434: for (int i = 0; i < typeVariables.length; i++) {
435: Type[] bounds = typeVariables[i].bounds();
436: for (int j = 0; j < bounds.length; j++) {
437: addTypeParameterToMap(map, bounds[j], holder);
438: }
439: }
440: }
441:
442: /**
443: * Map the AnnotationType to the ProgramElementDocs that use them as
444: * type parameters.
445: *
446: * @param map the map the insert the information into.
447: * @param doc the doc whose type parameters are being checked.
448: * @param holder the holder that owns the type parameters.
449: */
450: private void mapAnnotations(Map map, Object doc, Object holder) {
451: TypeVariable[] typeVariables;
452: AnnotationDesc[] annotations;
453: boolean isPackage = false;
454: if (doc instanceof ProgramElementDoc) {
455: annotations = ((ProgramElementDoc) doc).annotations();
456: } else if (doc instanceof PackageDoc) {
457: annotations = ((PackageDoc) doc).annotations();
458: isPackage = true;
459: } else if (doc instanceof Parameter) {
460: annotations = ((Parameter) doc).annotations();
461: } else {
462: throw new DocletAbortException();
463: }
464: for (int i = 0; i < annotations.length; i++) {
465: AnnotationTypeDoc annotationDoc = annotations[i]
466: .annotationType();
467: if (isPackage)
468: refList(map, annotationDoc).add(holder);
469: else
470: add(map, annotationDoc, (ProgramElementDoc) holder);
471: }
472: }
473:
474: private void addTypeParameterToMap(Map map, Type type,
475: ProgramElementDoc holder) {
476: if (type instanceof ClassDoc) {
477: add(map, (ClassDoc) type, holder);
478: } else if (type instanceof ParameterizedType) {
479: add(map, ((ParameterizedType) type).asClassDoc(), holder);
480: }
481: mapTypeParameters(map, type, holder);
482: }
483: }
|