/*
 * Copyright (C) 2010 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.doclava;


import com.sun.javadoc.AnnotationDesc;
import com.sun.javadoc.AnnotationTypeDoc;
import com.sun.javadoc.AnnotationTypeElementDoc;
import com.sun.javadoc.AnnotationValue;
import com.sun.javadoc.ClassDoc;
import com.sun.javadoc.ConstructorDoc;
import com.sun.javadoc.ExecutableMemberDoc;
import com.sun.javadoc.FieldDoc;
import com.sun.javadoc.MemberDoc;
import com.sun.javadoc.MethodDoc;
import com.sun.javadoc.PackageDoc;
import com.sun.javadoc.ParamTag;
import com.sun.javadoc.Parameter;
import com.sun.javadoc.RootDoc;
import com.sun.javadoc.SeeTag;
import com.sun.javadoc.SourcePosition;
import com.sun.javadoc.Tag;
import com.sun.javadoc.ThrowsTag;
import com.sun.javadoc.Type;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;

public class Converter {
  private static RootDoc root;

  public static void makeInfo(RootDoc r) {
    root = r;

    // create the objects
    ClassDoc[] classes = getClasses(r);
    for (ClassDoc c : classes) {
      Converter.obtainClass(c);
    }

    ArrayList<ClassInfo> classesNeedingInit2 = new ArrayList<ClassInfo>();

    int i;
    // fill in the fields that reference other classes
    while (mClassesNeedingInit.size() > 0) {
      i = mClassesNeedingInit.size() - 1;
      ClassNeedingInit clni = mClassesNeedingInit.get(i);
      mClassesNeedingInit.remove(i);

      initClass(clni.c, clni.cl);
      classesNeedingInit2.add(clni.cl);
    }
    mClassesNeedingInit = null;
    for (ClassInfo cl : classesNeedingInit2) {
      cl.init2();
    }

    finishAnnotationValueInit();

    // fill in the "root" stuff
    mRootClasses = Converter.convertClasses(classes);
  }

  private static ClassDoc[] getClasses(RootDoc r) {
    ClassDoc[] classDocs = r.classes();
    ArrayList<ClassDoc> filtered = new ArrayList<ClassDoc>(classDocs.length);
    for (ClassDoc c : classDocs) {
      if (c.position() != null) {
        // Work around a javadoc bug in Java 7: We sometimes spuriously
        // receive duplicate top level ClassDocs with null positions and no type
        // information. Ignore them, since every ClassDoc must have a non null
        // position.

        filtered.add(c);
      }
    }

    ClassDoc[] filteredArray = new ClassDoc[filtered.size()];
    filtered.toArray(filteredArray);
    return filteredArray;
  }

  private static ClassInfo[] mRootClasses;

  public static ClassInfo[] rootClasses() {
    return mRootClasses;
  }

  public static ClassInfo[] allClasses() {
    return (ClassInfo[]) mClasses.all();
  }

  private static final MethodDoc[] EMPTY_METHOD_DOC = new MethodDoc[0];

  private static void initClass(ClassDoc c, ClassInfo cl) {
    MethodDoc[] annotationElements;
    if (c instanceof AnnotationTypeDoc) {
      annotationElements = ((AnnotationTypeDoc) c).elements();
    } else {
      annotationElements = EMPTY_METHOD_DOC;
    }
    cl.init(Converter.obtainType(c),
            new ArrayList<ClassInfo>(Arrays.asList(Converter.convertClasses(c.interfaces()))),
            new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes(c.interfaceTypes()))),
            new ArrayList<ClassInfo>(Arrays.asList(Converter.convertClasses(c.innerClasses()))),
            new ArrayList<MethodInfo>(Arrays.asList(
                    Converter.convertMethods(c.constructors(false)))),
            new ArrayList<MethodInfo>(Arrays.asList(Converter.convertMethods(c.methods(false)))),
            new ArrayList<MethodInfo>(Arrays.asList(Converter.convertMethods(annotationElements))),
            new ArrayList<FieldInfo>(Arrays.asList(Converter.convertFields(c.fields(false)))),
            new ArrayList<FieldInfo>(Arrays.asList(Converter.convertFields(c.enumConstants()))),
            Converter.obtainPackage(c.containingPackage()),
            Converter.obtainClass(c.containingClass()),
            Converter.obtainClass(c.superclass()), Converter.obtainType(c.superclassType()),
            new ArrayList<AnnotationInstanceInfo>(Arrays.asList(
                    Converter.convertAnnotationInstances(c.annotations()))));

    cl.setHiddenMethods(
            new ArrayList<MethodInfo>(Arrays.asList(Converter.getHiddenMethods(c.methods(false)))));
    cl.setRemovedMethods(
            new ArrayList<MethodInfo>(Arrays.asList(Converter.getRemovedMethods(c.methods(false)))));

    cl.setRemovedSelfMethods(
        new ArrayList<MethodInfo>(Converter.convertAllMethods(c.methods(false))));
    cl.setRemovedConstructors(
        new ArrayList<MethodInfo>(Converter.convertAllMethods(c.constructors(false))));
    cl.setRemovedSelfFields(
        new ArrayList<FieldInfo>(Converter.convertAllFields(c.fields(false))));
    cl.setRemovedEnumConstants(
        new ArrayList<FieldInfo>(Converter.convertAllFields(c.enumConstants())));

    cl.setNonWrittenConstructors(
            new ArrayList<MethodInfo>(Arrays.asList(Converter.convertNonWrittenConstructors(
                    c.constructors(false)))));
    cl.init3(
            new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes(c.typeParameters()))),
            new ArrayList<ClassInfo>(Arrays.asList(
                    Converter.convertClasses(c.innerClasses(false)))));
  }

  public static ClassInfo obtainClass(String className) {
    return Converter.obtainClass(root.classNamed(className));
  }

  public static PackageInfo obtainPackage(String packageName) {
    return Converter.obtainPackage(root.packageNamed(packageName));
  }

  private static TagInfo convertTag(Tag tag) {
    return new TextTagInfo(tag.name(), tag.kind(), tag.text(),
            Converter.convertSourcePosition(tag.position()));
  }

  private static ThrowsTagInfo convertThrowsTag(ThrowsTag tag, ContainerInfo base) {
    return new ThrowsTagInfo(tag.name(), tag.text(), tag.kind(), Converter.obtainClass(tag
        .exception()), tag.exceptionComment(), base, Converter
        .convertSourcePosition(tag.position()));
  }

  private static ParamTagInfo convertParamTag(ParamTag tag, ContainerInfo base) {
    return new ParamTagInfo(tag.name(), tag.kind(), tag.text(), tag.isTypeParameter(), tag
        .parameterComment(), tag.parameterName(), base, Converter.convertSourcePosition(tag
        .position()));
  }

  private static SeeTagInfo convertSeeTag(SeeTag tag, ContainerInfo base) {
    return new SeeTagInfo(tag.name(), tag.kind(), tag.text(), base, Converter
        .convertSourcePosition(tag.position()));
  }

  private static SourcePositionInfo convertSourcePosition(SourcePosition sp) {
    if (sp == null) {
      return null;
    }
    return new SourcePositionInfo(sp.file().toString(), sp.line(), sp.column());
  }

  public static TagInfo[] convertTags(Tag[] tags, ContainerInfo base) {
    int len = tags.length;
    TagInfo[] out = TagInfo.getArray(len);
    for (int i = 0; i < len; i++) {
      Tag t = tags[i];
      /*
       * System.out.println("Tag name='" + t.name() + "' kind='" + t.kind() + "'");
       */
      if (t instanceof SeeTag) {
        out[i] = Converter.convertSeeTag((SeeTag) t, base);
      } else if (t instanceof ThrowsTag) {
        out[i] = Converter.convertThrowsTag((ThrowsTag) t, base);
      } else if (t instanceof ParamTag) {
        out[i] = Converter.convertParamTag((ParamTag) t, base);
      } else {
        out[i] = Converter.convertTag(t);
      }
    }
    return out;
  }

  public static ClassInfo[] convertClasses(ClassDoc[] classes) {
    if (classes == null) return null;
    int N = classes.length;
    ClassInfo[] result = new ClassInfo[N];
    for (int i = 0; i < N; i++) {
      result[i] = Converter.obtainClass(classes[i]);
    }
    return result;
  }

  private static ParameterInfo convertParameter(Parameter p, SourcePosition pos, boolean isVarArg) {
    if (p == null) return null;
    ParameterInfo pi =
        new ParameterInfo(p.name(), p.typeName(), Converter.obtainType(p.type()), isVarArg,
          Converter.convertSourcePosition(pos));
    return pi;
  }

  private static ParameterInfo[] convertParameters(Parameter[] p, ExecutableMemberDoc m) {
    SourcePosition pos = m.position();
    int len = p.length;
    ParameterInfo[] q = new ParameterInfo[len];
    for (int i = 0; i < len; i++) {
      boolean isVarArg = (m.isVarArgs() && i == len - 1);
      q[i] = Converter.convertParameter(p[i], pos, isVarArg);
    }
    return q;
  }

  private static TypeInfo[] convertTypes(Type[] p) {
    if (p == null) return null;
    int len = p.length;
    TypeInfo[] q = new TypeInfo[len];
    for (int i = 0; i < len; i++) {
      q[i] = Converter.obtainType(p[i]);
    }
    return q;
  }

  private Converter() {}

  private static class ClassNeedingInit {
    ClassNeedingInit(ClassDoc c, ClassInfo cl) {
      this.c = c;
      this.cl = cl;
    }

    ClassDoc c;
    ClassInfo cl;
  }

  private static ArrayList<ClassNeedingInit> mClassesNeedingInit =
      new ArrayList<ClassNeedingInit>();

  static ClassInfo obtainClass(ClassDoc o) {
    return (ClassInfo) mClasses.obtain(o);
  }

  private static Cache mClasses = new Cache() {
    @Override
    protected Object make(Object o) {
      ClassDoc c = (ClassDoc) o;
      ClassInfo cl =
          new ClassInfo(c, c.getRawCommentText(), Converter.convertSourcePosition(c.position()), c
              .isPublic(), c.isProtected(), c.isPackagePrivate(), c.isPrivate(), c.isStatic(), c
              .isInterface(), c.isAbstract(), c.isOrdinaryClass(), c.isException(), c.isError(), c
              .isEnum(), (c instanceof AnnotationTypeDoc), c.isFinal(), c.isIncluded(), c.name(), c
              .qualifiedName(), c.qualifiedTypeName(), c.isPrimitive());
      if (mClassesNeedingInit != null) {
        mClassesNeedingInit.add(new ClassNeedingInit(c, cl));
      }
      return cl;
    }

    @Override
    protected void made(Object o, Object r) {
      if (mClassesNeedingInit == null) {
        initClass((ClassDoc) o, (ClassInfo) r);
        ((ClassInfo) r).init2();
      }
    }

    @Override
    ClassInfo[] all() {
      return mCache.values().toArray(new ClassInfo[mCache.size()]);
    }
  };

  private static MethodInfo[] getHiddenMethods(MethodDoc[] methods) {
    if (methods == null) return null;
    ArrayList<MethodInfo> hiddenMethods = new ArrayList<MethodInfo>();
    for (MethodDoc method : methods) {
      MethodInfo methodInfo = Converter.obtainMethod(method);
      if (methodInfo.isHidden()) {
        hiddenMethods.add(methodInfo);
      }
    }

    return hiddenMethods.toArray(new MethodInfo[hiddenMethods.size()]);
  }

  // Gets the removed methods regardless of access levels
  private static MethodInfo[] getRemovedMethods(MethodDoc[] methods) {
    if (methods == null) return null;
    ArrayList<MethodInfo> removedMethods = new ArrayList<MethodInfo>();
    for (MethodDoc method : methods) {
      MethodInfo methodInfo = Converter.obtainMethod(method);
      if (methodInfo.isRemoved()) {
        removedMethods.add(methodInfo);
      }
    }

    return removedMethods.toArray(new MethodInfo[removedMethods.size()]);
  }

  /**
   * Converts FieldDoc[] into List<FieldInfo>. No filtering is done.
   */
  private static List<FieldInfo> convertAllFields(FieldDoc[] fields) {
    if (fields == null) return null;
    List<FieldInfo> allFields = new ArrayList<FieldInfo>();

    for (FieldDoc field : fields) {
      FieldInfo fieldInfo = Converter.obtainField(field);
      allFields.add(fieldInfo);
    }

    return allFields;
  }

  /**
   * Converts ExecutableMemberDoc[] into List<MethodInfo>. No filtering is done.
   */
  private static List<MethodInfo> convertAllMethods(ExecutableMemberDoc[] methods) {
    if (methods == null) return null;
    List<MethodInfo> allMethods = new ArrayList<MethodInfo>();
    for (ExecutableMemberDoc method : methods) {
      MethodInfo methodInfo = Converter.obtainMethod(method);
      allMethods.add(methodInfo);
    }
    return allMethods;
  }

  /**
   * Convert MethodDoc[] or ConstructorDoc[] into MethodInfo[].
   * Also filters according to the -private, -public option,
   * because the filtering doesn't seem to be working in the ClassDoc.constructors(boolean) call.
   */
  private static MethodInfo[] convertMethods(ExecutableMemberDoc[] methods) {
    if (methods == null) return null;
    List<MethodInfo> filteredMethods = new ArrayList<MethodInfo>();
    for (ExecutableMemberDoc method : methods) {
      MethodInfo methodInfo = Converter.obtainMethod(method);
      if (methodInfo.checkLevel()) {
        filteredMethods.add(methodInfo);
      }
    }

    return filteredMethods.toArray(new MethodInfo[filteredMethods.size()]);
  }

  private static MethodInfo[] convertNonWrittenConstructors(ConstructorDoc[] methods) {
    if (methods == null) return null;
    ArrayList<MethodInfo> ctors = new ArrayList<MethodInfo>();
    for (ConstructorDoc method : methods) {
      MethodInfo methodInfo = Converter.obtainMethod(method);
      if (!methodInfo.checkLevel()) {
        ctors.add(methodInfo);
      }
    }

    return ctors.toArray(new MethodInfo[ctors.size()]);
  }

  private static <E extends ExecutableMemberDoc> MethodInfo obtainMethod(E o) {
    return (MethodInfo) mMethods.obtain(o);
  }

  private static Cache mMethods = new Cache() {
    @Override
    protected Object make(Object o) {
      if (o instanceof AnnotationTypeElementDoc) {
        AnnotationTypeElementDoc m = (AnnotationTypeElementDoc) o;
        MethodInfo result =
            new MethodInfo(m.getRawCommentText(),
                    new ArrayList<TypeInfo>(Arrays.asList(
                            Converter.convertTypes(m.typeParameters()))),
                    m.name(), m.signature(), Converter.obtainClass(m.containingClass()),
                    Converter.obtainClass(m.containingClass()), m.isPublic(), m.isProtected(), m
                    .isPackagePrivate(), m.isPrivate(), m.isFinal(), m.isStatic(), m.isSynthetic(),
                    m.isAbstract(), m.isSynchronized(), m.isNative(), true, "annotationElement",
                    m.flatSignature(), Converter.obtainMethod(m.overriddenMethod()),
                    Converter.obtainType(m.returnType()),
                    new ArrayList<ParameterInfo>(Arrays.asList(
                            Converter.convertParameters(m.parameters(), m))),
                    new ArrayList<ClassInfo>(Arrays.asList(Converter.convertClasses(
                            m.thrownExceptions()))), Converter.convertSourcePosition(m.position()),
                    new ArrayList<AnnotationInstanceInfo>(Arrays.asList(
                            Converter.convertAnnotationInstances(m.annotations()))));
        result.setVarargs(m.isVarArgs());
        result.init(Converter.obtainAnnotationValue(m.defaultValue(), result));
        return result;
      } else if (o instanceof MethodDoc) {
        MethodDoc m = (MethodDoc) o;
        MethodInfo result =
            new MethodInfo(m.getRawCommentText(),
                    new ArrayList<TypeInfo>(Arrays.asList(
                            Converter.convertTypes(m.typeParameters()))), m.name(), m.signature(),
                    Converter.obtainClass(m.containingClass()),
                    Converter.obtainClass(m.containingClass()), m.isPublic(), m.isProtected(),
                    m.isPackagePrivate(), m.isPrivate(), m.isFinal(), m.isStatic(), m.isSynthetic(),
                    m.isAbstract(), m.isSynchronized(), m.isNative(), false, "method",
                    m.flatSignature(), Converter.obtainMethod(m.overriddenMethod()),
                    Converter.obtainType(m.returnType()),
                    new ArrayList<ParameterInfo>(Arrays.asList(
                            Converter.convertParameters(m.parameters(), m))),
                    new ArrayList<ClassInfo>(Arrays.asList(
                            Converter.convertClasses(m.thrownExceptions()))),
                    Converter.convertSourcePosition(m.position()),
                    new ArrayList<AnnotationInstanceInfo>(Arrays.asList(
                            Converter.convertAnnotationInstances(m.annotations()))));
        result.setVarargs(m.isVarArgs());
        result.init(null);
        return result;
      } else {
        ConstructorDoc m = (ConstructorDoc) o;
        MethodInfo result =
            new MethodInfo(m.getRawCommentText(), new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes(m.typeParameters()))), m
                .name(), m.signature(), Converter.obtainClass(m.containingClass()), Converter
                .obtainClass(m.containingClass()), m.isPublic(), m.isProtected(), m
                .isPackagePrivate(), m.isPrivate(), m.isFinal(), m.isStatic(), m.isSynthetic(),
                false, m.isSynchronized(), m.isNative(), false, "constructor", m.flatSignature(),
                null, null, new ArrayList<ParameterInfo>(Arrays.asList(Converter.convertParameters(m.parameters(), m))),
                new ArrayList<ClassInfo>(Arrays.asList(Converter.convertClasses(m.thrownExceptions()))), Converter.convertSourcePosition(m
                    .position()), new ArrayList<AnnotationInstanceInfo>(Arrays.asList(Converter.convertAnnotationInstances(m.annotations()))));
        result.setVarargs(m.isVarArgs());
        result.init(null);
        return result;
      }
    }
  };


  private static FieldInfo[] convertFields(FieldDoc[] fields) {
    if (fields == null) return null;
    ArrayList<FieldInfo> out = new ArrayList<FieldInfo>();
    int N = fields.length;
    for (int i = 0; i < N; i++) {
      FieldInfo f = Converter.obtainField(fields[i]);
      if (f.checkLevel()) {
        out.add(f);
      }
    }
    return out.toArray(new FieldInfo[out.size()]);
  }

  private static FieldInfo obtainField(FieldDoc o) {
    return (FieldInfo) mFields.obtain(o);
  }

  private static FieldInfo obtainField(ConstructorDoc o) {
    return (FieldInfo) mFields.obtain(o);
  }

  private static Cache mFields = new Cache() {
    @Override
    protected Object make(Object o) {
      FieldDoc f = (FieldDoc) o;
      return new FieldInfo(f.name(), Converter.obtainClass(f.containingClass()), Converter
          .obtainClass(f.containingClass()), f.isPublic(), f.isProtected(), f.isPackagePrivate(), f
          .isPrivate(), f.isFinal(), f.isStatic(), f.isTransient(), f.isVolatile(),
          f.isSynthetic(), Converter.obtainType(f.type()), f.getRawCommentText(),
          f.constantValue(), Converter.convertSourcePosition(f.position()),
          new ArrayList<AnnotationInstanceInfo>(Arrays.asList(Converter
              .convertAnnotationInstances(f.annotations()))));
    }
  };

  private static PackageInfo obtainPackage(PackageDoc o) {
    return (PackageInfo) mPackagees.obtain(o);
  }

  private static Cache mPackagees = new Cache() {
    @Override
    protected Object make(Object o) {
      PackageDoc p = (PackageDoc) o;
      return new PackageInfo(p, p.name(), Converter.convertSourcePosition(p.position()));
    }
  };

  private static TypeInfo obtainType(Type o) {
    return (TypeInfo) mTypes.obtain(o);
  }

  private static Cache mTypes = new Cache() {
    @Override
    protected Object make(Object o) {
      Type t = (Type) o;
      String simpleTypeName;
      if (t instanceof ClassDoc) {
        simpleTypeName = ((ClassDoc) t).name();
      } else {
        simpleTypeName = t.simpleTypeName();
      }
      TypeInfo ti =
          new TypeInfo(t.isPrimitive(), t.dimension(), simpleTypeName, t.qualifiedTypeName(),
              Converter.obtainClass(t.asClassDoc()));
      return ti;
    }

    @Override
    protected void made(Object o, Object r) {
      Type t = (Type) o;
      TypeInfo ti = (TypeInfo) r;
      if (t.asParameterizedType() != null) {
        ti.setTypeArguments(new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes(t.asParameterizedType().typeArguments()))));
      } else if (t instanceof ClassDoc) {
        ti.setTypeArguments(new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes(((ClassDoc) t).typeParameters()))));
      } else if (t.asTypeVariable() != null) {
        ti.setBounds(null, new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes((t.asTypeVariable().bounds())))));
        ti.setIsTypeVariable(true);
      } else if (t.asWildcardType() != null) {
        ti.setIsWildcard(true);
        ti.setBounds(new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes(t.asWildcardType().superBounds()))),
                new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes(t.asWildcardType().extendsBounds()))));
      }
    }

    @Override
    protected Object keyFor(Object o) {
      Type t = (Type) o;
      String keyString = o.getClass().getName() + "/" + o.toString() + "/";
      if (t.asParameterizedType() != null) {
        keyString += t.asParameterizedType().toString() + "/";
        if (t.asParameterizedType().typeArguments() != null) {
          for (Type ty : t.asParameterizedType().typeArguments()) {
            keyString += ty.toString() + "/";
          }
        }
      } else {
        keyString += "NoParameterizedType//";
      }
      if (t.asTypeVariable() != null) {
        keyString += t.asTypeVariable().toString() + "/";
        if (t.asTypeVariable().bounds() != null) {
          for (Type ty : t.asTypeVariable().bounds()) {
            keyString += ty.toString() + "/";
          }
        }
      } else {
        keyString += "NoTypeVariable//";
      }
      if (t.asWildcardType() != null) {
        keyString += t.asWildcardType().toString() + "/";
        if (t.asWildcardType().superBounds() != null) {
          for (Type ty : t.asWildcardType().superBounds()) {
            keyString += ty.toString() + "/";
          }
        }
        if (t.asWildcardType().extendsBounds() != null) {
          for (Type ty : t.asWildcardType().extendsBounds()) {
            keyString += ty.toString() + "/";
          }
        }
      } else {
        keyString += "NoWildCardType//";
      }

      return keyString;
    }
  };

  public static TypeInfo obtainTypeFromString(String type) {
    return (TypeInfo) mTypesFromString.obtain(type);
  }

  private static final Cache mTypesFromString = new Cache() {
    @Override
    protected Object make(Object o) {
      String name = (String) o;
      return new TypeInfo(name);
    }

    @Override
    protected void made(Object o, Object r) {

    }

    @Override
    protected Object keyFor(Object o) {
      return o;
    }
  };

  private static MemberInfo obtainMember(MemberDoc o) {
    return (MemberInfo) mMembers.obtain(o);
  }

  private static Cache mMembers = new Cache() {
    @Override
    protected Object make(Object o) {
      if (o instanceof MethodDoc) {
        return Converter.obtainMethod((MethodDoc) o);
      } else if (o instanceof ConstructorDoc) {
        return Converter.obtainMethod((ConstructorDoc) o);
      } else if (o instanceof FieldDoc) {
        return Converter.obtainField((FieldDoc) o);
      } else {
        return null;
      }
    }
  };

  private static AnnotationInstanceInfo[] convertAnnotationInstances(AnnotationDesc[] orig) {
    int len = orig.length;
    AnnotationInstanceInfo[] out = new AnnotationInstanceInfo[len];
    for (int i = 0; i < len; i++) {
      out[i] = Converter.obtainAnnotationInstance(orig[i]);
    }
    return out;
  }


  private static AnnotationInstanceInfo obtainAnnotationInstance(AnnotationDesc o) {
    return (AnnotationInstanceInfo) mAnnotationInstances.obtain(o);
  }

  private static Cache mAnnotationInstances = new Cache() {
    @Override
    protected Object make(Object o) {
      AnnotationDesc a = (AnnotationDesc) o;
      ClassInfo annotationType = Converter.obtainClass(a.annotationType());
      AnnotationDesc.ElementValuePair[] ev = a.elementValues();
      AnnotationValueInfo[] elementValues = new AnnotationValueInfo[ev.length];
      for (int i = 0; i < ev.length; i++) {
        elementValues[i] =
            obtainAnnotationValue(ev[i].value(), Converter.obtainMethod(ev[i].element()));
      }
      return new AnnotationInstanceInfo(annotationType, elementValues);
    }
  };


  private abstract static class Cache {
    void put(Object key, Object value) {
      mCache.put(key, value);
    }

    Object obtain(Object o) {
      if (o == null) {
        return null;
      }
      Object k = keyFor(o);
      Object r = mCache.get(k);
      if (r == null) {
        r = make(o);
        mCache.put(k, r);
        made(o, r);
      }
      return r;
    }

    protected HashMap<Object, Object> mCache = new HashMap<Object, Object>();

    protected abstract Object make(Object o);

    protected void made(Object o, Object r) {}

    protected Object keyFor(Object o) {
      return o;
    }

    Object[] all() {
      return null;
    }
  }

  // annotation values
  private static HashMap<AnnotationValue, AnnotationValueInfo> mAnnotationValues =
      new HashMap<AnnotationValue, AnnotationValueInfo>();
  private static HashSet<AnnotationValue> mAnnotationValuesNeedingInit =
      new HashSet<AnnotationValue>();

  private static AnnotationValueInfo obtainAnnotationValue(AnnotationValue o, MethodInfo element) {
    if (o == null) {
      return null;
    }
    AnnotationValueInfo v = mAnnotationValues.get(o);
    if (v != null) return v;
    v = new AnnotationValueInfo(element);
    mAnnotationValues.put(o, v);
    if (mAnnotationValuesNeedingInit != null) {
      mAnnotationValuesNeedingInit.add(o);
    } else {
      initAnnotationValue(o, v);
    }
    return v;
  }

  private static void initAnnotationValue(AnnotationValue o, AnnotationValueInfo v) {
    Object orig = o.value();
    Object converted;
    if (orig instanceof Type) {
      // class literal
      converted = Converter.obtainType((Type) orig);
    } else if (orig instanceof FieldDoc) {
      // enum constant
      converted = Converter.obtainField((FieldDoc) orig);
    } else if (orig instanceof AnnotationDesc) {
      // annotation instance
      converted = Converter.obtainAnnotationInstance((AnnotationDesc) orig);
    } else if (orig instanceof AnnotationValue[]) {
      AnnotationValue[] old = (AnnotationValue[]) orig;
      ArrayList<AnnotationValueInfo> values = new ArrayList<AnnotationValueInfo>();
      for (int i = 0; i < old.length; i++) {
        values.add(Converter.obtainAnnotationValue(old[i], null));
      }
      converted = values;
    } else {
      converted = orig;
    }
    v.init(converted);
  }

  private static void finishAnnotationValueInit() {
    int depth = 0;
    while (mAnnotationValuesNeedingInit.size() > 0) {
      HashSet<AnnotationValue> set = mAnnotationValuesNeedingInit;
      mAnnotationValuesNeedingInit = new HashSet<AnnotationValue>();
      for (AnnotationValue o : set) {
        AnnotationValueInfo v = mAnnotationValues.get(o);
        initAnnotationValue(o, v);
      }
      depth++;
    }
    mAnnotationValuesNeedingInit = null;
  }
}
