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