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