1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/ClassUseMapper.java Sat Dec 01 00:00:00 2007 +0000 1.3 @@ -0,0 +1,474 @@ 1.4 +/* 1.5 + * Copyright 1998-2006 Sun Microsystems, Inc. All Rights Reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. Sun designates this 1.11 + * particular file as subject to the "Classpath" exception as provided 1.12 + * by Sun in the LICENSE file that accompanied this code. 1.13 + * 1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.17 + * version 2 for more details (a copy is included in the LICENSE file that 1.18 + * accompanied this code). 1.19 + * 1.20 + * You should have received a copy of the GNU General Public License version 1.21 + * 2 along with this work; if not, write to the Free Software Foundation, 1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.23 + * 1.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 1.25 + * CA 95054 USA or visit www.sun.com if you need additional information or 1.26 + * have any questions. 1.27 + */ 1.28 + 1.29 +package com.sun.tools.doclets.internal.toolkit.util; 1.30 + 1.31 +import com.sun.javadoc.*; 1.32 +import java.util.*; 1.33 + 1.34 +/** 1.35 + * Map all class uses for a given class. 1.36 + * 1.37 + * This code is not part of an API. 1.38 + * It is implementation that is subject to change. 1.39 + * Do not use it as an API 1.40 + * 1.41 + * @since 1.2 1.42 + * @author Robert G. Field 1.43 + */ 1.44 +public class ClassUseMapper { 1.45 + 1.46 + private final ClassTree classtree; 1.47 + 1.48 + /** 1.49 + * Mapping of ClassDocs to set of PackageDoc used by that class. 1.50 + * Entries may be null. 1.51 + */ 1.52 + public Map classToPackage = new HashMap(); 1.53 + 1.54 + /** 1.55 + * Mapping of Annotations to set of PackageDoc that use the annotation. 1.56 + */ 1.57 + public Map classToPackageAnnotations = new HashMap(); 1.58 + 1.59 + /** 1.60 + * Mapping of ClassDocs to set of ClassDoc used by that class. 1.61 + * Entries may be null. 1.62 + */ 1.63 + public Map classToClass = new HashMap(); 1.64 + 1.65 + /** 1.66 + * Mapping of ClassDocs to list of ClassDoc which are direct or 1.67 + * indirect subclasses of that class. 1.68 + * Entries may be null. 1.69 + */ 1.70 + public Map classToSubclass = new HashMap(); 1.71 + 1.72 + /** 1.73 + * Mapping of ClassDocs to list of ClassDoc which are direct or 1.74 + * indirect subinterfaces of that interface. 1.75 + * Entries may be null. 1.76 + */ 1.77 + public Map classToSubinterface = new HashMap(); 1.78 + 1.79 + /** 1.80 + * Mapping of ClassDocs to list of ClassDoc which implement 1.81 + * this interface. 1.82 + * Entries may be null. 1.83 + */ 1.84 + public Map classToImplementingClass = new HashMap(); 1.85 + 1.86 + /** 1.87 + * Mapping of ClassDocs to list of FieldDoc declared as that class. 1.88 + * Entries may be null. 1.89 + */ 1.90 + public Map classToField = new HashMap(); 1.91 + 1.92 + /** 1.93 + * Mapping of ClassDocs to list of MethodDoc returning that class. 1.94 + * Entries may be null. 1.95 + */ 1.96 + public Map classToMethodReturn = new HashMap(); 1.97 + 1.98 + /** 1.99 + * Mapping of ClassDocs to list of MethodDoc having that class 1.100 + * as an arg. 1.101 + * Entries may be null. 1.102 + */ 1.103 + public Map classToMethodArgs = new HashMap(); 1.104 + 1.105 + /** 1.106 + * Mapping of ClassDocs to list of MethodDoc which throws that class. 1.107 + * Entries may be null. 1.108 + */ 1.109 + public Map classToMethodThrows = new HashMap(); 1.110 + 1.111 + /** 1.112 + * Mapping of ClassDocs to list of ConstructorDoc having that class 1.113 + * as an arg. 1.114 + * Entries may be null. 1.115 + */ 1.116 + public Map classToConstructorArgs = new HashMap(); 1.117 + 1.118 + /** 1.119 + * Mapping of ClassDocs to list of ConstructorDoc which throws that class. 1.120 + * Entries may be null. 1.121 + */ 1.122 + public Map classToConstructorThrows = new HashMap(); 1.123 + 1.124 + /** 1.125 + * The mapping of AnnotationTypeDocs to constructors that use them. 1.126 + */ 1.127 + public Map classToConstructorAnnotations = new HashMap(); 1.128 + 1.129 + /** 1.130 + * The mapping of AnnotationTypeDocs to Constructor parameters that use them. 1.131 + */ 1.132 + public Map classToConstructorParamAnnotation = new HashMap(); 1.133 + 1.134 + /** 1.135 + * The mapping of ClassDocs to Constructor arguments that use them as type parameters. 1.136 + */ 1.137 + public Map classToConstructorDocArgTypeParam = new HashMap(); 1.138 + 1.139 + /** 1.140 + * The mapping of ClassDocs to ClassDocs that use them as type parameters. 1.141 + */ 1.142 + public Map classToClassTypeParam = new HashMap(); 1.143 + 1.144 + /** 1.145 + * The mapping of AnnotationTypeDocs to ClassDocs that use them. 1.146 + */ 1.147 + public Map classToClassAnnotations = new HashMap(); 1.148 + 1.149 + /** 1.150 + * The mapping of ClassDocs to ExecutableMemberDocs that use them as type parameters. 1.151 + */ 1.152 + public Map classToExecMemberDocTypeParam = new HashMap(); 1.153 + 1.154 + /** 1.155 + * The mapping of ClassDocs to ExecutableMemberDocs arguments that use them as type parameters. 1.156 + */ 1.157 + public Map classToExecMemberDocArgTypeParam = new HashMap(); 1.158 + 1.159 + /** 1.160 + * The mapping of AnnotationTypeDocs to ExecutableMemberDocs that use them. 1.161 + */ 1.162 + public Map classToExecMemberDocAnnotations = new HashMap(); 1.163 + 1.164 + /** 1.165 + * The mapping of ClassDocs to ExecutableMemberDocs that have return type 1.166 + * with type parameters of that class. 1.167 + */ 1.168 + public Map classToExecMemberDocReturnTypeParam = new HashMap(); 1.169 + 1.170 + /** 1.171 + * The mapping of AnnotationTypeDocs to MethodDoc parameters that use them. 1.172 + */ 1.173 + public Map classToExecMemberDocParamAnnotation = new HashMap(); 1.174 + 1.175 + /** 1.176 + * The mapping of ClassDocs to FieldDocs that use them as type parameters. 1.177 + */ 1.178 + public Map classToFieldDocTypeParam = new HashMap(); 1.179 + 1.180 + /** 1.181 + * The mapping of AnnotationTypeDocs to FieldDocs that use them. 1.182 + */ 1.183 + public Map annotationToFieldDoc = new HashMap(); 1.184 + 1.185 + 1.186 + public ClassUseMapper(RootDoc root, ClassTree classtree) { 1.187 + this.classtree = classtree; 1.188 + 1.189 + // Map subclassing, subinterfacing implementing, ... 1.190 + for (Iterator it = classtree.baseclasses().iterator(); it.hasNext();) { 1.191 + subclasses((ClassDoc)it.next()); 1.192 + } 1.193 + for (Iterator it = classtree.baseinterfaces().iterator(); it.hasNext();) { 1.194 + // does subinterfacing as side-effect 1.195 + implementingClasses((ClassDoc)it.next()); 1.196 + } 1.197 + // Map methods, fields, constructors using a class. 1.198 + ClassDoc[] classes = root.classes(); 1.199 + for (int i = 0; i < classes.length; i++) { 1.200 + PackageDoc pkg = classes[i].containingPackage(); 1.201 + mapAnnotations(classToPackageAnnotations, pkg, pkg); 1.202 + ClassDoc cd = classes[i]; 1.203 + mapTypeParameters(classToClassTypeParam, cd, cd); 1.204 + mapAnnotations(classToClassAnnotations, cd, cd); 1.205 + FieldDoc[] fields = cd.fields(); 1.206 + for (int j = 0; j < fields.length; j++) { 1.207 + FieldDoc fd = fields[j]; 1.208 + mapTypeParameters(classToFieldDocTypeParam, fd, fd); 1.209 + mapAnnotations(annotationToFieldDoc, fd, fd); 1.210 + if (! fd.type().isPrimitive()) { 1.211 + add(classToField, fd.type().asClassDoc(), fd); 1.212 + } 1.213 + } 1.214 + ConstructorDoc[] cons = cd.constructors(); 1.215 + for (int j = 0; j < cons.length; j++) { 1.216 + mapAnnotations(classToConstructorAnnotations, cons[j], cons[j]); 1.217 + mapExecutable(cons[j]); 1.218 + } 1.219 + MethodDoc[] meths = cd.methods(); 1.220 + for (int j = 0; j < meths.length; j++) { 1.221 + MethodDoc md = meths[j]; 1.222 + mapExecutable(md); 1.223 + mapTypeParameters(classToExecMemberDocTypeParam, md, md); 1.224 + mapAnnotations(classToExecMemberDocAnnotations, md, md); 1.225 + if (! (md.returnType().isPrimitive() || md.returnType() instanceof TypeVariable)) { 1.226 + mapTypeParameters(classToExecMemberDocReturnTypeParam, 1.227 + md.returnType(), md); 1.228 + add(classToMethodReturn, md.returnType().asClassDoc(), md); 1.229 + } 1.230 + } 1.231 + } 1.232 + } 1.233 + 1.234 + /** 1.235 + * Return all subclasses of a class AND fill-in classToSubclass map. 1.236 + */ 1.237 + private Collection subclasses(ClassDoc cd) { 1.238 + Collection ret = (Collection)classToSubclass.get(cd.qualifiedName()); 1.239 + if (ret == null) { 1.240 + ret = new TreeSet(); 1.241 + List subs = classtree.subclasses(cd); 1.242 + if (subs != null) { 1.243 + ret.addAll(subs); 1.244 + for (Iterator it = subs.iterator(); it.hasNext();) { 1.245 + ret.addAll(subclasses((ClassDoc)it.next())); 1.246 + } 1.247 + } 1.248 + addAll(classToSubclass, cd, ret); 1.249 + } 1.250 + return ret; 1.251 + } 1.252 + 1.253 + /** 1.254 + * Return all subinterfaces of an interface AND fill-in classToSubinterface map. 1.255 + */ 1.256 + private Collection subinterfaces(ClassDoc cd) { 1.257 + Collection ret = (Collection)classToSubinterface.get(cd.qualifiedName()); 1.258 + if (ret == null) { 1.259 + ret = new TreeSet(); 1.260 + List subs = classtree.subinterfaces(cd); 1.261 + if (subs != null) { 1.262 + ret.addAll(subs); 1.263 + for (Iterator it = subs.iterator(); it.hasNext();) { 1.264 + ret.addAll(subinterfaces((ClassDoc)it.next())); 1.265 + } 1.266 + } 1.267 + addAll(classToSubinterface, cd, ret); 1.268 + } 1.269 + return ret; 1.270 + } 1.271 + 1.272 + /** 1.273 + * Return all implementing classes of an interface (including 1.274 + * all subclasses of implementing classes and all classes 1.275 + * implementing subinterfaces) AND fill-in both classToImplementingClass 1.276 + * and classToSubinterface maps. 1.277 + */ 1.278 + private Collection implementingClasses(ClassDoc cd) { 1.279 + Collection ret = (List)classToImplementingClass.get(cd.qualifiedName()); 1.280 + if (ret == null) { 1.281 + ret = new TreeSet(); 1.282 + List impl = classtree.implementingclasses(cd); 1.283 + if (impl != null) { 1.284 + ret.addAll(impl); 1.285 + for (Iterator it = impl.iterator(); it.hasNext();) { 1.286 + ret.addAll(subclasses((ClassDoc)it.next())); 1.287 + } 1.288 + } 1.289 + for (Iterator it = subinterfaces(cd).iterator(); it.hasNext();) { 1.290 + ret.addAll(implementingClasses((ClassDoc)it.next())); 1.291 + } 1.292 + addAll(classToImplementingClass, cd, ret); 1.293 + } 1.294 + return ret; 1.295 + } 1.296 + 1.297 + /** 1.298 + * Determine classes used by a method or constructor, so they can be 1.299 + * inverse mapped. 1.300 + */ 1.301 + private void mapExecutable(ExecutableMemberDoc em) { 1.302 + Parameter[] params = em.parameters(); 1.303 + boolean isConstructor = em.isConstructor(); 1.304 + List classArgs = new ArrayList(); 1.305 + for (int k = 0; k < params.length; k++) { 1.306 + Type pcd = params[k].type(); 1.307 + // primitives don't get mapped, also avoid dups 1.308 + if ((! params[k].type().isPrimitive()) && 1.309 + ! classArgs.contains(pcd) && 1.310 + ! (pcd instanceof TypeVariable)) { 1.311 + add(isConstructor? classToConstructorArgs :classToMethodArgs, 1.312 + pcd.asClassDoc(), em); 1.313 + classArgs.add(pcd); 1.314 + mapTypeParameters(isConstructor? 1.315 + classToConstructorDocArgTypeParam : classToExecMemberDocArgTypeParam, 1.316 + pcd, em); 1.317 + } 1.318 + mapAnnotations( 1.319 + isConstructor ? 1.320 + classToConstructorParamAnnotation : 1.321 + classToExecMemberDocParamAnnotation, 1.322 + params[k], em); 1.323 + } 1.324 + ClassDoc[] thr = em.thrownExceptions(); 1.325 + for (int k = 0; k < thr.length; k++) { 1.326 + add(isConstructor? classToConstructorThrows : classToMethodThrows, 1.327 + thr[k], em); 1.328 + } 1.329 + } 1.330 + 1.331 + private List refList(Map map, ClassDoc cd) { 1.332 + List list = (List)map.get(cd.qualifiedName()); 1.333 + if (list == null) { 1.334 + list = new ArrayList(); 1.335 + map.put(cd.qualifiedName(), list); 1.336 + } 1.337 + return list; 1.338 + } 1.339 + 1.340 + private Set packageSet(ClassDoc cd) { 1.341 + Set pkgSet = (Set)classToPackage.get(cd.qualifiedName()); 1.342 + if (pkgSet == null) { 1.343 + pkgSet = new TreeSet(); 1.344 + classToPackage.put(cd.qualifiedName(), pkgSet); 1.345 + } 1.346 + return pkgSet; 1.347 + } 1.348 + 1.349 + private Set classSet(ClassDoc cd) { 1.350 + Set clsSet = (Set)classToClass.get(cd.qualifiedName()); 1.351 + if (clsSet == null) { 1.352 + clsSet = new TreeSet(); 1.353 + classToClass.put(cd.qualifiedName(), clsSet); 1.354 + } 1.355 + return clsSet; 1.356 + } 1.357 + 1.358 + private void add(Map map, ClassDoc cd, ProgramElementDoc ref) { 1.359 + // add to specified map 1.360 + refList(map, cd).add(ref); 1.361 + 1.362 + // add ref's package to package map and class map 1.363 + packageSet(cd).add(ref.containingPackage()); 1.364 + 1.365 + classSet(cd).add(ref instanceof MemberDoc? 1.366 + ((MemberDoc)ref).containingClass() : 1.367 + ref); 1.368 + } 1.369 + 1.370 + private void addAll(Map map, ClassDoc cd, Collection refs) { 1.371 + if (refs == null) { 1.372 + return; 1.373 + } 1.374 + // add to specified map 1.375 + refList(map, cd).addAll(refs); 1.376 + 1.377 + Set pkgSet = packageSet(cd); 1.378 + Set clsSet = classSet(cd); 1.379 + // add ref's package to package map and class map 1.380 + for (Iterator it = refs.iterator(); it.hasNext();) { 1.381 + ProgramElementDoc pedoc = (ProgramElementDoc)it.next(); 1.382 + pkgSet.add(pedoc.containingPackage()); 1.383 + clsSet.add(pedoc instanceof MemberDoc? 1.384 + ((MemberDoc)pedoc).containingClass() : 1.385 + pedoc); 1.386 + 1.387 + } 1.388 + } 1.389 + 1.390 + /** 1.391 + * Map the ClassDocs to the ProgramElementDocs that use them as 1.392 + * type parameters. 1.393 + * 1.394 + * @param map the map the insert the information into. 1.395 + * @param doc the doc whose type parameters are being checked. 1.396 + * @param holder the holder that owns the type parameters. 1.397 + */ 1.398 + private void mapTypeParameters(Map map, Object doc, 1.399 + ProgramElementDoc holder) { 1.400 + TypeVariable[] typeVariables; 1.401 + if (doc instanceof ClassDoc) { 1.402 + typeVariables = ((ClassDoc) doc).typeParameters(); 1.403 + } else if (doc instanceof WildcardType) { 1.404 + Type[] extendsBounds = ((WildcardType) doc).extendsBounds(); 1.405 + for (int k = 0; k < extendsBounds.length; k++) { 1.406 + addTypeParameterToMap(map, extendsBounds[k], holder); 1.407 + } 1.408 + Type[] superBounds = ((WildcardType) doc).superBounds(); 1.409 + for (int k = 0; k < superBounds.length; k++) { 1.410 + addTypeParameterToMap(map, superBounds[k], holder); 1.411 + } 1.412 + return; 1.413 + } else if (doc instanceof ParameterizedType) { 1.414 + Type[] typeArguments = ((ParameterizedType) doc).typeArguments(); 1.415 + for (int k = 0; k < typeArguments.length; k++) { 1.416 + addTypeParameterToMap(map, typeArguments[k], holder); 1.417 + } 1.418 + return; 1.419 + } else if (doc instanceof ExecutableMemberDoc) { 1.420 + typeVariables = ((ExecutableMemberDoc) doc).typeParameters(); 1.421 + } else if (doc instanceof FieldDoc) { 1.422 + Type fieldType = ((FieldDoc) doc).type(); 1.423 + mapTypeParameters(map, fieldType, holder); 1.424 + return; 1.425 + } else { 1.426 + return; 1.427 + } 1.428 + for (int i = 0; i < typeVariables.length; i++) { 1.429 + Type[] bounds = typeVariables[i].bounds(); 1.430 + for (int j = 0; j < bounds.length; j++) { 1.431 + addTypeParameterToMap(map, bounds[j], holder); 1.432 + } 1.433 + } 1.434 + } 1.435 + 1.436 + /** 1.437 + * Map the AnnotationType to the ProgramElementDocs that use them as 1.438 + * type parameters. 1.439 + * 1.440 + * @param map the map the insert the information into. 1.441 + * @param doc the doc whose type parameters are being checked. 1.442 + * @param holder the holder that owns the type parameters. 1.443 + */ 1.444 + private void mapAnnotations(Map map, Object doc, 1.445 + Object holder) { 1.446 + TypeVariable[] typeVariables; 1.447 + AnnotationDesc[] annotations; 1.448 + boolean isPackage = false; 1.449 + if (doc instanceof ProgramElementDoc) { 1.450 + annotations = ((ProgramElementDoc) doc).annotations(); 1.451 + } else if (doc instanceof PackageDoc) { 1.452 + annotations = ((PackageDoc) doc).annotations(); 1.453 + isPackage = true; 1.454 + } else if (doc instanceof Parameter) { 1.455 + annotations = ((Parameter) doc).annotations(); 1.456 + } else { 1.457 + throw new DocletAbortException(); 1.458 + } 1.459 + for (int i = 0; i < annotations.length; i++) { 1.460 + AnnotationTypeDoc annotationDoc = annotations[i].annotationType(); 1.461 + if (isPackage) 1.462 + refList(map, annotationDoc).add(holder); 1.463 + else 1.464 + add(map, annotationDoc, (ProgramElementDoc) holder); 1.465 + } 1.466 + } 1.467 + 1.468 + private void addTypeParameterToMap(Map map, Type type, 1.469 + ProgramElementDoc holder) { 1.470 + if (type instanceof ClassDoc) { 1.471 + add(map, (ClassDoc) type, holder); 1.472 + } else if (type instanceof ParameterizedType) { 1.473 + add(map, ((ParameterizedType) type).asClassDoc(), holder); 1.474 + } 1.475 + mapTypeParameters(map, type, holder); 1.476 + } 1.477 +}