1 /* 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 17 package com.google.doclava; 18 19 import com.sun.javadoc.*; 20 import java.util.ArrayList; 21 import java.util.Arrays; 22 import java.util.HashMap; 23 import java.util.HashSet; 24 import java.util.ArrayList; 25 26 public 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 } 78 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))))); 103 } 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) { 114 return new TextTagInfo(tag.name(), tag.kind(), tag.text(), 115 Converter.convertSourcePosition(tag.position())); 116 } 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 = 337 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())))); 352 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 = 358 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())))); 374 result.setVarargs(m.isVarArgs()); 375 result.init(null); 376 return result; 377 } else { 378 ConstructorDoc m = (ConstructorDoc) o; 379 MethodInfo result = 380 new MethodInfo(m.getRawCommentText(), new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes(m.typeParameters()))), m 381 .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(), 385 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())))); 388 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(), 425 f.constantValue(), Converter.convertSourcePosition(f.position()), 426 new ArrayList<AnnotationInstanceInfo>(Arrays.asList(Converter 427 .convertAnnotationInstances(f.annotations())))); 428 } 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) { 468 ti.setTypeArguments(new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes(t.asParameterizedType().typeArguments())))); 469 } else if (t instanceof ClassDoc) { 470 ti.setTypeArguments(new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes(((ClassDoc) t).typeParameters())))); 471 } else if (t.asTypeVariable() != null) { 472 ti.setBounds(null, new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes((t.asTypeVariable().bounds()))))); 473 ti.setIsTypeVariable(true); 474 } else if (t.asWildcardType() != null) { 475 ti.setIsWildcard(true); 476 ti.setBounds(new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes(t.asWildcardType().superBounds()))), 477 new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes(t.asWildcardType().extendsBounds())))); 478 } 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; 666 ArrayList<AnnotationValueInfo> values = new ArrayList<AnnotationValueInfo>(); 667 for (int i = 0; i < old.length; i++) { 668 values.add(Converter.obtainAnnotationValue(old[i], null)); 669 } 670 converted = values; 671 } 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 } 691