/*
 * 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),
          Arrays.asList(Converter.convertAnnotationInstances(p.annotations())));
    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(), m.isDefault(), 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(), m.isDefault(), 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;
        // Workaround for a JavaDoc behavior change introduced in OpenJDK 8 that breaks
        // links in documentation and the content of API files like current.txt.
        // http://b/18051133.
        String name = m.name();
        ClassDoc containingClass = m.containingClass();
        if (containingClass.containingClass() != null) {
          // This should detect the new behavior and be bypassed otherwise.
          if (!name.contains(".")) {
            // Constructors of inner classes do not contain the name of the enclosing class
            // with OpenJDK 8. This simulates the old behavior:
            name = containingClass.name();
          }
        }
        // End of workaround.
        MethodInfo result =
            new MethodInfo(m.getRawCommentText(), new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes(m.typeParameters()))), 
                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/*isDefault*/, 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;
  }
}
