blob: bdf6af56b7f9795a751b76a4a3f94ae7096d64ee [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
Narayan Kamathb1b0ee72013-10-24 15:57:08 +010019
20import com.sun.javadoc.AnnotationDesc;
21import com.sun.javadoc.AnnotationTypeDoc;
22import com.sun.javadoc.AnnotationTypeElementDoc;
23import com.sun.javadoc.AnnotationValue;
24import com.sun.javadoc.ClassDoc;
25import com.sun.javadoc.ConstructorDoc;
26import com.sun.javadoc.ExecutableMemberDoc;
27import com.sun.javadoc.FieldDoc;
28import com.sun.javadoc.MemberDoc;
29import com.sun.javadoc.MethodDoc;
30import com.sun.javadoc.PackageDoc;
31import com.sun.javadoc.ParamTag;
32import com.sun.javadoc.Parameter;
33import com.sun.javadoc.RootDoc;
34import com.sun.javadoc.SeeTag;
35import com.sun.javadoc.SourcePosition;
36import com.sun.javadoc.Tag;
37import com.sun.javadoc.ThrowsTag;
38import com.sun.javadoc.Type;
39
Ben Dodson920dbbb2010-08-04 15:21:06 -070040import java.util.ArrayList;
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -070041import java.util.Arrays;
Ben Dodson920dbbb2010-08-04 15:21:06 -070042import java.util.HashMap;
43import java.util.HashSet;
44
45public class Converter {
46 private static RootDoc root;
47
48 public static void makeInfo(RootDoc r) {
49 root = r;
50
Ben Dodson920dbbb2010-08-04 15:21:06 -070051 // create the objects
Narayan Kamathb1b0ee72013-10-24 15:57:08 +010052 ClassDoc[] classes = getClasses(r);
53 for (ClassDoc c : classes) {
54 Converter.obtainClass(c);
Ben Dodson920dbbb2010-08-04 15:21:06 -070055 }
Narayan Kamathb1b0ee72013-10-24 15:57:08 +010056
Ben Dodson920dbbb2010-08-04 15:21:06 -070057 ArrayList<ClassInfo> classesNeedingInit2 = new ArrayList<ClassInfo>();
Narayan Kamathb1b0ee72013-10-24 15:57:08 +010058
59 int i;
Ben Dodson920dbbb2010-08-04 15:21:06 -070060 // fill in the fields that reference other classes
61 while (mClassesNeedingInit.size() > 0) {
62 i = mClassesNeedingInit.size() - 1;
63 ClassNeedingInit clni = mClassesNeedingInit.get(i);
64 mClassesNeedingInit.remove(i);
65
66 initClass(clni.c, clni.cl);
67 classesNeedingInit2.add(clni.cl);
68 }
69 mClassesNeedingInit = null;
70 for (ClassInfo cl : classesNeedingInit2) {
71 cl.init2();
72 }
73
74 finishAnnotationValueInit();
75
76 // fill in the "root" stuff
Narayan Kamathb1b0ee72013-10-24 15:57:08 +010077 mRootClasses = Converter.convertClasses(classes);
78 }
79
80 private static ClassDoc[] getClasses(RootDoc r) {
81 ClassDoc[] classDocs = r.classes();
82 ArrayList<ClassDoc> filtered = new ArrayList<ClassDoc>(classDocs.length);
83 for (ClassDoc c : classDocs) {
84 if (c.position() != null) {
85 // Work around a javadoc bug in Java 7: We sometimes spuriously
86 // receive duplicate top level ClassDocs with null positions and no type
87 // information. Ignore them, since every ClassDoc must have a non null
88 // position.
89
90 filtered.add(c);
91 }
92 }
93
94 ClassDoc[] filteredArray = new ClassDoc[filtered.size()];
95 filtered.toArray(filteredArray);
96 return filteredArray;
Ben Dodson920dbbb2010-08-04 15:21:06 -070097 }
98
99 private static ClassInfo[] mRootClasses;
100
101 public static ClassInfo[] rootClasses() {
102 return mRootClasses;
103 }
104
105 public static ClassInfo[] allClasses() {
106 return (ClassInfo[]) mClasses.all();
107 }
108
109 private static void initClass(ClassDoc c, ClassInfo cl) {
110 MethodDoc[] annotationElements;
111 if (c instanceof AnnotationTypeDoc) {
112 annotationElements = ((AnnotationTypeDoc) c).elements();
113 } else {
114 annotationElements = new MethodDoc[0];
115 }
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700116 cl.init(Converter.obtainType(c),
117 new ArrayList<ClassInfo>(Arrays.asList(Converter.convertClasses(c.interfaces()))),
118 new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes(c.interfaceTypes()))),
119 new ArrayList<ClassInfo>(Arrays.asList(Converter.convertClasses(c.innerClasses()))),
120 new ArrayList<MethodInfo>(Arrays.asList(
121 Converter.convertMethods(c.constructors(false)))),
122 new ArrayList<MethodInfo>(Arrays.asList(Converter.convertMethods(c.methods(false)))),
123 new ArrayList<MethodInfo>(Arrays.asList(Converter.convertMethods(annotationElements))),
124 new ArrayList<FieldInfo>(Arrays.asList(Converter.convertFields(c.fields(false)))),
125 new ArrayList<FieldInfo>(Arrays.asList(Converter.convertFields(c.enumConstants()))),
126 Converter.obtainPackage(c.containingPackage()),
127 Converter.obtainClass(c.containingClass()),
128 Converter.obtainClass(c.superclass()), Converter.obtainType(c.superclassType()),
129 new ArrayList<AnnotationInstanceInfo>(Arrays.asList(
130 Converter.convertAnnotationInstances(c.annotations()))));
131
132 cl.setHiddenMethods(
133 new ArrayList<MethodInfo>(Arrays.asList(Converter.getHiddenMethods(c.methods(false)))));
134 cl.setNonWrittenConstructors(
135 new ArrayList<MethodInfo>(Arrays.asList(Converter.convertNonWrittenConstructors(
136 c.constructors(false)))));
137 cl.init3(
138 new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes(c.typeParameters()))),
139 new ArrayList<ClassInfo>(Arrays.asList(
140 Converter.convertClasses(c.innerClasses(false)))));
Ben Dodson920dbbb2010-08-04 15:21:06 -0700141 }
142
143 public static ClassInfo obtainClass(String className) {
144 return Converter.obtainClass(root.classNamed(className));
145 }
146
147 public static PackageInfo obtainPackage(String packageName) {
148 return Converter.obtainPackage(root.packageNamed(packageName));
149 }
150
151 private static TagInfo convertTag(Tag tag) {
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700152 return new TextTagInfo(tag.name(), tag.kind(), tag.text(),
153 Converter.convertSourcePosition(tag.position()));
Ben Dodson920dbbb2010-08-04 15:21:06 -0700154 }
155
156 private static ThrowsTagInfo convertThrowsTag(ThrowsTag tag, ContainerInfo base) {
157 return new ThrowsTagInfo(tag.name(), tag.text(), tag.kind(), Converter.obtainClass(tag
158 .exception()), tag.exceptionComment(), base, Converter
159 .convertSourcePosition(tag.position()));
160 }
161
162 private static ParamTagInfo convertParamTag(ParamTag tag, ContainerInfo base) {
163 return new ParamTagInfo(tag.name(), tag.kind(), tag.text(), tag.isTypeParameter(), tag
164 .parameterComment(), tag.parameterName(), base, Converter.convertSourcePosition(tag
165 .position()));
166 }
167
168 private static SeeTagInfo convertSeeTag(SeeTag tag, ContainerInfo base) {
169 return new SeeTagInfo(tag.name(), tag.kind(), tag.text(), base, Converter
170 .convertSourcePosition(tag.position()));
171 }
172
173 private static SourcePositionInfo convertSourcePosition(SourcePosition sp) {
174 if (sp == null) {
175 return null;
176 }
177 return new SourcePositionInfo(sp.file().toString(), sp.line(), sp.column());
178 }
179
180 public static TagInfo[] convertTags(Tag[] tags, ContainerInfo base) {
181 int len = tags.length;
182 TagInfo[] out = new TagInfo[len];
183 for (int i = 0; i < len; i++) {
184 Tag t = tags[i];
185 /*
186 * System.out.println("Tag name='" + t.name() + "' kind='" + t.kind() + "'");
187 */
188 if (t instanceof SeeTag) {
189 out[i] = Converter.convertSeeTag((SeeTag) t, base);
190 } else if (t instanceof ThrowsTag) {
191 out[i] = Converter.convertThrowsTag((ThrowsTag) t, base);
192 } else if (t instanceof ParamTag) {
193 out[i] = Converter.convertParamTag((ParamTag) t, base);
194 } else {
195 out[i] = Converter.convertTag(t);
196 }
197 }
198 return out;
199 }
200
201 public static ClassInfo[] convertClasses(ClassDoc[] classes) {
202 if (classes == null) return null;
203 int N = classes.length;
204 ClassInfo[] result = new ClassInfo[N];
205 for (int i = 0; i < N; i++) {
206 result[i] = Converter.obtainClass(classes[i]);
207 }
208 return result;
209 }
210
211 private static ParameterInfo convertParameter(Parameter p, SourcePosition pos, boolean isVarArg) {
212 if (p == null) return null;
213 ParameterInfo pi =
214 new ParameterInfo(p.name(), p.typeName(), Converter.obtainType(p.type()), isVarArg,
215 Converter.convertSourcePosition(pos));
216 return pi;
217 }
218
219 private static ParameterInfo[] convertParameters(Parameter[] p, ExecutableMemberDoc m) {
220 SourcePosition pos = m.position();
221 int len = p.length;
222 ParameterInfo[] q = new ParameterInfo[len];
223 for (int i = 0; i < len; i++) {
224 boolean isVarArg = (m.isVarArgs() && i == len - 1);
225 q[i] = Converter.convertParameter(p[i], pos, isVarArg);
226 }
227 return q;
228 }
229
230 private static TypeInfo[] convertTypes(Type[] p) {
231 if (p == null) return null;
232 int len = p.length;
233 TypeInfo[] q = new TypeInfo[len];
234 for (int i = 0; i < len; i++) {
235 q[i] = Converter.obtainType(p[i]);
236 }
237 return q;
238 }
239
240 private Converter() {}
241
242 private static class ClassNeedingInit {
243 ClassNeedingInit(ClassDoc c, ClassInfo cl) {
244 this.c = c;
245 this.cl = cl;
246 }
247
248 ClassDoc c;
249 ClassInfo cl;
250 }
251
252 private static ArrayList<ClassNeedingInit> mClassesNeedingInit =
253 new ArrayList<ClassNeedingInit>();
254
255 static ClassInfo obtainClass(ClassDoc o) {
256 return (ClassInfo) mClasses.obtain(o);
257 }
258
259 private static Cache mClasses = new Cache() {
260 @Override
261 protected Object make(Object o) {
262 ClassDoc c = (ClassDoc) o;
263 ClassInfo cl =
264 new ClassInfo(c, c.getRawCommentText(), Converter.convertSourcePosition(c.position()), c
265 .isPublic(), c.isProtected(), c.isPackagePrivate(), c.isPrivate(), c.isStatic(), c
266 .isInterface(), c.isAbstract(), c.isOrdinaryClass(), c.isException(), c.isError(), c
267 .isEnum(), (c instanceof AnnotationTypeDoc), c.isFinal(), c.isIncluded(), c.name(), c
268 .qualifiedName(), c.qualifiedTypeName(), c.isPrimitive());
269 if (mClassesNeedingInit != null) {
270 mClassesNeedingInit.add(new ClassNeedingInit(c, cl));
271 }
272 return cl;
273 }
274
275 @Override
276 protected void made(Object o, Object r) {
277 if (mClassesNeedingInit == null) {
278 initClass((ClassDoc) o, (ClassInfo) r);
279 ((ClassInfo) r).init2();
280 }
281 }
282
283 @Override
284 ClassInfo[] all() {
285 return mCache.values().toArray(new ClassInfo[mCache.size()]);
286 }
287 };
288
289 private static MethodInfo[] getHiddenMethods(MethodDoc[] methods) {
290 if (methods == null) return null;
291 ArrayList<MethodInfo> out = new ArrayList<MethodInfo>();
292 int N = methods.length;
293 for (int i = 0; i < N; i++) {
294 MethodInfo m = Converter.obtainMethod(methods[i]);
295 // System.out.println(m.toString() + ": ");
296 // for (TypeInfo ti : m.getTypeParameters()){
297 // if (ti.asClassInfo() != null){
298 // System.out.println(" " +ti.asClassInfo().toString());
299 // } else {
300 // System.out.println(" null");
301 // }
302 // }
303 if (m.isHidden()) {
304 out.add(m);
305 }
306 }
307 return out.toArray(new MethodInfo[out.size()]);
308 }
309
310 /**
311 * Convert MethodDoc[] into MethodInfo[]. Also filters according to the -private, -public option,
312 * because the filtering doesn't seem to be working in the ClassDoc.constructors(boolean) call.
313 */
314 private static MethodInfo[] convertMethods(MethodDoc[] methods) {
315 if (methods == null) return null;
316 ArrayList<MethodInfo> out = new ArrayList<MethodInfo>();
317 int N = methods.length;
318 for (int i = 0; i < N; i++) {
319 MethodInfo m = Converter.obtainMethod(methods[i]);
320 // System.out.println(m.toString() + ": ");
321 // for (TypeInfo ti : m.getTypeParameters()){
322 // if (ti.asClassInfo() != null){
323 // System.out.println(" " +ti.asClassInfo().toString());
324 // } else {
325 // System.out.println(" null");
326 // }
327 // }
328 if (m.checkLevel()) {
329 out.add(m);
330 }
331 }
332 return out.toArray(new MethodInfo[out.size()]);
333 }
334
335 private static MethodInfo[] convertMethods(ConstructorDoc[] methods) {
336 if (methods == null) return null;
337 ArrayList<MethodInfo> out = new ArrayList<MethodInfo>();
338 int N = methods.length;
339 for (int i = 0; i < N; i++) {
340 MethodInfo m = Converter.obtainMethod(methods[i]);
341 if (m.checkLevel()) {
342 out.add(m);
343 }
344 }
345 return out.toArray(new MethodInfo[out.size()]);
346 }
347
348 private static MethodInfo[] convertNonWrittenConstructors(ConstructorDoc[] methods) {
349 if (methods == null) return null;
350 ArrayList<MethodInfo> out = new ArrayList<MethodInfo>();
351 int N = methods.length;
352 for (int i = 0; i < N; i++) {
353 MethodInfo m = Converter.obtainMethod(methods[i]);
354 if (!m.checkLevel()) {
355 out.add(m);
356 }
357 }
358 return out.toArray(new MethodInfo[out.size()]);
359 }
360
361 private static MethodInfo obtainMethod(MethodDoc o) {
362 return (MethodInfo) mMethods.obtain(o);
363 }
364
365 private static MethodInfo obtainMethod(ConstructorDoc o) {
366 return (MethodInfo) mMethods.obtain(o);
367 }
368
369 private static Cache mMethods = new Cache() {
370 @Override
371 protected Object make(Object o) {
372 if (o instanceof AnnotationTypeElementDoc) {
373 AnnotationTypeElementDoc m = (AnnotationTypeElementDoc) o;
374 MethodInfo result =
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700375 new MethodInfo(m.getRawCommentText(),
376 new ArrayList<TypeInfo>(Arrays.asList(
377 Converter.convertTypes(m.typeParameters()))),
378 m.name(), m.signature(), Converter.obtainClass(m.containingClass()),
379 Converter.obtainClass(m.containingClass()), m.isPublic(), m.isProtected(), m
380 .isPackagePrivate(), m.isPrivate(), m.isFinal(), m.isStatic(), m.isSynthetic(),
381 m.isAbstract(), m.isSynchronized(), m.isNative(), true, "annotationElement",
382 m.flatSignature(), Converter.obtainMethod(m.overriddenMethod()),
383 Converter.obtainType(m.returnType()),
384 new ArrayList<ParameterInfo>(Arrays.asList(
385 Converter.convertParameters(m.parameters(), m))),
386 new ArrayList<ClassInfo>(Arrays.asList(Converter.convertClasses(
387 m.thrownExceptions()))), Converter.convertSourcePosition(m.position()),
388 new ArrayList<AnnotationInstanceInfo>(Arrays.asList(
389 Converter.convertAnnotationInstances(m.annotations()))));
Ben Dodson920dbbb2010-08-04 15:21:06 -0700390 result.setVarargs(m.isVarArgs());
391 result.init(Converter.obtainAnnotationValue(m.defaultValue(), result));
392 return result;
393 } else if (o instanceof MethodDoc) {
394 MethodDoc m = (MethodDoc) o;
395 MethodInfo result =
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700396 new MethodInfo(m.getRawCommentText(),
397 new ArrayList<TypeInfo>(Arrays.asList(
398 Converter.convertTypes(m.typeParameters()))), m.name(), m.signature(),
399 Converter.obtainClass(m.containingClass()),
400 Converter.obtainClass(m.containingClass()), m.isPublic(), m.isProtected(),
401 m.isPackagePrivate(), m.isPrivate(), m.isFinal(), m.isStatic(), m.isSynthetic(),
402 m.isAbstract(), m.isSynchronized(), m.isNative(), false, "method",
403 m.flatSignature(), Converter.obtainMethod(m.overriddenMethod()),
404 Converter.obtainType(m.returnType()),
405 new ArrayList<ParameterInfo>(Arrays.asList(
406 Converter.convertParameters(m.parameters(), m))),
407 new ArrayList<ClassInfo>(Arrays.asList(
408 Converter.convertClasses(m.thrownExceptions()))),
409 Converter.convertSourcePosition(m.position()),
410 new ArrayList<AnnotationInstanceInfo>(Arrays.asList(
411 Converter.convertAnnotationInstances(m.annotations()))));
Ben Dodson920dbbb2010-08-04 15:21:06 -0700412 result.setVarargs(m.isVarArgs());
413 result.init(null);
414 return result;
415 } else {
416 ConstructorDoc m = (ConstructorDoc) o;
417 MethodInfo result =
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700418 new MethodInfo(m.getRawCommentText(), new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes(m.typeParameters()))), m
Ben Dodson920dbbb2010-08-04 15:21:06 -0700419 .name(), m.signature(), Converter.obtainClass(m.containingClass()), Converter
420 .obtainClass(m.containingClass()), m.isPublic(), m.isProtected(), m
421 .isPackagePrivate(), m.isPrivate(), m.isFinal(), m.isStatic(), m.isSynthetic(),
422 false, m.isSynchronized(), m.isNative(), false, "constructor", m.flatSignature(),
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700423 null, null, new ArrayList<ParameterInfo>(Arrays.asList(Converter.convertParameters(m.parameters(), m))),
424 new ArrayList<ClassInfo>(Arrays.asList(Converter.convertClasses(m.thrownExceptions()))), Converter.convertSourcePosition(m
425 .position()), new ArrayList<AnnotationInstanceInfo>(Arrays.asList(Converter.convertAnnotationInstances(m.annotations()))));
Ben Dodson920dbbb2010-08-04 15:21:06 -0700426 result.setVarargs(m.isVarArgs());
427 result.init(null);
428 return result;
429 }
430 }
431 };
432
433
434 private static FieldInfo[] convertFields(FieldDoc[] fields) {
435 if (fields == null) return null;
436 ArrayList<FieldInfo> out = new ArrayList<FieldInfo>();
437 int N = fields.length;
438 for (int i = 0; i < N; i++) {
439 FieldInfo f = Converter.obtainField(fields[i]);
440 if (f.checkLevel()) {
441 out.add(f);
442 }
443 }
444 return out.toArray(new FieldInfo[out.size()]);
445 }
446
447 private static FieldInfo obtainField(FieldDoc o) {
448 return (FieldInfo) mFields.obtain(o);
449 }
450
451 private static FieldInfo obtainField(ConstructorDoc o) {
452 return (FieldInfo) mFields.obtain(o);
453 }
454
455 private static Cache mFields = new Cache() {
456 @Override
457 protected Object make(Object o) {
458 FieldDoc f = (FieldDoc) o;
459 return new FieldInfo(f.name(), Converter.obtainClass(f.containingClass()), Converter
460 .obtainClass(f.containingClass()), f.isPublic(), f.isProtected(), f.isPackagePrivate(), f
461 .isPrivate(), f.isFinal(), f.isStatic(), f.isTransient(), f.isVolatile(),
462 f.isSynthetic(), Converter.obtainType(f.type()), f.getRawCommentText(),
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700463 f.constantValue(), Converter.convertSourcePosition(f.position()),
464 new ArrayList<AnnotationInstanceInfo>(Arrays.asList(Converter
465 .convertAnnotationInstances(f.annotations()))));
Ben Dodson920dbbb2010-08-04 15:21:06 -0700466 }
467 };
468
469 private static PackageInfo obtainPackage(PackageDoc o) {
470 return (PackageInfo) mPackagees.obtain(o);
471 }
472
473 private static Cache mPackagees = new Cache() {
474 @Override
475 protected Object make(Object o) {
476 PackageDoc p = (PackageDoc) o;
477 return new PackageInfo(p, p.name(), Converter.convertSourcePosition(p.position()));
478 }
479 };
480
481 private static TypeInfo obtainType(Type o) {
482 return (TypeInfo) mTypes.obtain(o);
483 }
484
485 private static Cache mTypes = new Cache() {
486 @Override
487 protected Object make(Object o) {
488 Type t = (Type) o;
489 String simpleTypeName;
490 if (t instanceof ClassDoc) {
491 simpleTypeName = ((ClassDoc) t).name();
492 } else {
493 simpleTypeName = t.simpleTypeName();
494 }
495 TypeInfo ti =
496 new TypeInfo(t.isPrimitive(), t.dimension(), simpleTypeName, t.qualifiedTypeName(),
497 Converter.obtainClass(t.asClassDoc()));
498 return ti;
499 }
500
501 @Override
502 protected void made(Object o, Object r) {
503 Type t = (Type) o;
504 TypeInfo ti = (TypeInfo) r;
505 if (t.asParameterizedType() != null) {
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700506 ti.setTypeArguments(new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes(t.asParameterizedType().typeArguments()))));
Ben Dodson920dbbb2010-08-04 15:21:06 -0700507 } else if (t instanceof ClassDoc) {
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700508 ti.setTypeArguments(new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes(((ClassDoc) t).typeParameters()))));
Ben Dodson920dbbb2010-08-04 15:21:06 -0700509 } else if (t.asTypeVariable() != null) {
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700510 ti.setBounds(null, new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes((t.asTypeVariable().bounds())))));
Ben Dodson920dbbb2010-08-04 15:21:06 -0700511 ti.setIsTypeVariable(true);
512 } else if (t.asWildcardType() != null) {
513 ti.setIsWildcard(true);
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700514 ti.setBounds(new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes(t.asWildcardType().superBounds()))),
515 new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes(t.asWildcardType().extendsBounds()))));
Ben Dodson920dbbb2010-08-04 15:21:06 -0700516 }
517 }
518
519 @Override
520 protected Object keyFor(Object o) {
521 Type t = (Type) o;
522 String keyString = o.getClass().getName() + "/" + o.toString() + "/";
523 if (t.asParameterizedType() != null) {
524 keyString += t.asParameterizedType().toString() + "/";
525 if (t.asParameterizedType().typeArguments() != null) {
526 for (Type ty : t.asParameterizedType().typeArguments()) {
527 keyString += ty.toString() + "/";
528 }
529 }
530 } else {
531 keyString += "NoParameterizedType//";
532 }
533 if (t.asTypeVariable() != null) {
534 keyString += t.asTypeVariable().toString() + "/";
535 if (t.asTypeVariable().bounds() != null) {
536 for (Type ty : t.asTypeVariable().bounds()) {
537 keyString += ty.toString() + "/";
538 }
539 }
540 } else {
541 keyString += "NoTypeVariable//";
542 }
543 if (t.asWildcardType() != null) {
544 keyString += t.asWildcardType().toString() + "/";
545 if (t.asWildcardType().superBounds() != null) {
546 for (Type ty : t.asWildcardType().superBounds()) {
547 keyString += ty.toString() + "/";
548 }
549 }
550 if (t.asWildcardType().extendsBounds() != null) {
551 for (Type ty : t.asWildcardType().extendsBounds()) {
552 keyString += ty.toString() + "/";
553 }
554 }
555 } else {
556 keyString += "NoWildCardType//";
557 }
558
559 return keyString;
560 }
561 };
562
563 public static TypeInfo obtainTypeFromString(String type) {
564 return (TypeInfo) mTypesFromString.obtain(type);
565 }
566
567 private static final Cache mTypesFromString = new Cache() {
568 @Override
569 protected Object make(Object o) {
570 String name = (String) o;
571 return new TypeInfo(name);
572 }
573
574 @Override
575 protected void made(Object o, Object r) {
576
577 }
578
579 @Override
580 protected Object keyFor(Object o) {
581 return o;
582 }
583 };
584
585 private static MemberInfo obtainMember(MemberDoc o) {
586 return (MemberInfo) mMembers.obtain(o);
587 }
588
589 private static Cache mMembers = new Cache() {
590 @Override
591 protected Object make(Object o) {
592 if (o instanceof MethodDoc) {
593 return Converter.obtainMethod((MethodDoc) o);
594 } else if (o instanceof ConstructorDoc) {
595 return Converter.obtainMethod((ConstructorDoc) o);
596 } else if (o instanceof FieldDoc) {
597 return Converter.obtainField((FieldDoc) o);
598 } else {
599 return null;
600 }
601 }
602 };
603
604 private static AnnotationInstanceInfo[] convertAnnotationInstances(AnnotationDesc[] orig) {
605 int len = orig.length;
606 AnnotationInstanceInfo[] out = new AnnotationInstanceInfo[len];
607 for (int i = 0; i < len; i++) {
608 out[i] = Converter.obtainAnnotationInstance(orig[i]);
609 }
610 return out;
611 }
612
613
614 private static AnnotationInstanceInfo obtainAnnotationInstance(AnnotationDesc o) {
615 return (AnnotationInstanceInfo) mAnnotationInstances.obtain(o);
616 }
617
618 private static Cache mAnnotationInstances = new Cache() {
619 @Override
620 protected Object make(Object o) {
621 AnnotationDesc a = (AnnotationDesc) o;
622 ClassInfo annotationType = Converter.obtainClass(a.annotationType());
623 AnnotationDesc.ElementValuePair[] ev = a.elementValues();
624 AnnotationValueInfo[] elementValues = new AnnotationValueInfo[ev.length];
625 for (int i = 0; i < ev.length; i++) {
626 elementValues[i] =
627 obtainAnnotationValue(ev[i].value(), Converter.obtainMethod(ev[i].element()));
628 }
629 return new AnnotationInstanceInfo(annotationType, elementValues);
630 }
631 };
632
633
634 private abstract static class Cache {
635 void put(Object key, Object value) {
636 mCache.put(key, value);
637 }
638
639 Object obtain(Object o) {
640 if (o == null) {
641 return null;
642 }
643 Object k = keyFor(o);
644 Object r = mCache.get(k);
645 if (r == null) {
646 r = make(o);
647 mCache.put(k, r);
648 made(o, r);
649 }
650 return r;
651 }
652
653 protected HashMap<Object, Object> mCache = new HashMap<Object, Object>();
654
655 protected abstract Object make(Object o);
656
657 protected void made(Object o, Object r) {}
658
659 protected Object keyFor(Object o) {
660 return o;
661 }
662
663 Object[] all() {
664 return null;
665 }
666 }
667
668 // annotation values
669 private static HashMap<AnnotationValue, AnnotationValueInfo> mAnnotationValues =
670 new HashMap<AnnotationValue, AnnotationValueInfo>();
671 private static HashSet<AnnotationValue> mAnnotationValuesNeedingInit =
672 new HashSet<AnnotationValue>();
673
674 private static AnnotationValueInfo obtainAnnotationValue(AnnotationValue o, MethodInfo element) {
675 if (o == null) {
676 return null;
677 }
678 AnnotationValueInfo v = mAnnotationValues.get(o);
679 if (v != null) return v;
680 v = new AnnotationValueInfo(element);
681 mAnnotationValues.put(o, v);
682 if (mAnnotationValuesNeedingInit != null) {
683 mAnnotationValuesNeedingInit.add(o);
684 } else {
685 initAnnotationValue(o, v);
686 }
687 return v;
688 }
689
690 private static void initAnnotationValue(AnnotationValue o, AnnotationValueInfo v) {
691 Object orig = o.value();
692 Object converted;
693 if (orig instanceof Type) {
694 // class literal
695 converted = Converter.obtainType((Type) orig);
696 } else if (orig instanceof FieldDoc) {
697 // enum constant
698 converted = Converter.obtainField((FieldDoc) orig);
699 } else if (orig instanceof AnnotationDesc) {
700 // annotation instance
701 converted = Converter.obtainAnnotationInstance((AnnotationDesc) orig);
702 } else if (orig instanceof AnnotationValue[]) {
703 AnnotationValue[] old = (AnnotationValue[]) orig;
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700704 ArrayList<AnnotationValueInfo> values = new ArrayList<AnnotationValueInfo>();
705 for (int i = 0; i < old.length; i++) {
706 values.add(Converter.obtainAnnotationValue(old[i], null));
Ben Dodson920dbbb2010-08-04 15:21:06 -0700707 }
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700708 converted = values;
Ben Dodson920dbbb2010-08-04 15:21:06 -0700709 } else {
710 converted = orig;
711 }
712 v.init(converted);
713 }
714
715 private static void finishAnnotationValueInit() {
716 int depth = 0;
717 while (mAnnotationValuesNeedingInit.size() > 0) {
718 HashSet<AnnotationValue> set = mAnnotationValuesNeedingInit;
719 mAnnotationValuesNeedingInit = new HashSet<AnnotationValue>();
720 for (AnnotationValue o : set) {
721 AnnotationValueInfo v = mAnnotationValues.get(o);
722 initAnnotationValue(o, v);
723 }
724 depth++;
725 }
726 mAnnotationValuesNeedingInit = null;
727 }
728}