package org.checkerframework.javacutil;

import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.AnnotationValueVisitor;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Name;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.PrimitiveType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.ElementFilter;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import org.checkerframework.checker.interning.qual.Interned;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.checker.signature.qual.CanonicalName;
import org.checkerframework.checker.signature.qual.FullyQualifiedName;
import org.checkerframework.dataflow.qual.SideEffectFree;
import org.plumelib.util.StringsPlume;

/**
 * Builds an annotation mirror that may have some values.
 *
 * <p>Constructing an {@link AnnotationMirror} requires:
 *
 * <ol>
 *   <li>Constructing the builder with the desired annotation class
 *   <li>Setting each value individually using {@code setValue} methods
 *   <li>Calling {@link #build()} to get the annotation
 * </ol>
 *
 * Once an annotation is built, no further modification or calls to build can be made. Otherwise, a
 * {@link IllegalStateException} is thrown.
 *
 * <p>All setter methods throw {@link IllegalArgumentException} if the specified element is not
 * found, or if the given value is not a subtype of the expected type.
 *
 * <p>TODO: Doesn't type-check arrays yet
 */
public class AnnotationBuilder {

  /** The element utilities to use. */
  private final Elements elements;
  /** The type utilities to use. */
  private final Types types;

  /** The type element of the annotation. */
  private final TypeElement annotationElt;
  /** The type of the annotation. */
  private final DeclaredType annotationType;
  /** A mapping from element to AnnotationValue. */
  private final Map<ExecutableElement, AnnotationValue> elementValues;

  /**
   * Create a new AnnotationBuilder for the given annotation and environment (with no
   * elements/fields, but they can be added later).
   *
   * @param env the processing environment
   * @param anno the class of the annotation to build
   */
  @SuppressWarnings("nullness") // getCanonicalName expected to be non-null
  public AnnotationBuilder(ProcessingEnvironment env, Class<? extends Annotation> anno) {
    this(env, anno.getCanonicalName());
  }

  /**
   * Create a new AnnotationBuilder for the given annotation name (with no elements/fields, but they
   * can be added later).
   *
   * @param env the processing environment
   * @param name the canonical name of the annotation to build
   */
  public AnnotationBuilder(ProcessingEnvironment env, @FullyQualifiedName CharSequence name) {
    this.elements = env.getElementUtils();
    this.types = env.getTypeUtils();
    this.annotationElt = elements.getTypeElement(name);
    if (annotationElt == null) {
      throw new UserError("Could not find annotation: " + name + ". Is it on the classpath?");
    }
    assert annotationElt.getKind() == ElementKind.ANNOTATION_TYPE;
    this.annotationType = (DeclaredType) annotationElt.asType();
    this.elementValues = new LinkedHashMap<>();
  }

  /**
   * Create a new AnnotationBuilder that copies the given annotation, including its elements/fields.
   *
   * @param env the processing environment
   * @param annotation the annotation to copy
   */
  public AnnotationBuilder(ProcessingEnvironment env, AnnotationMirror annotation) {
    this.elements = env.getElementUtils();
    this.types = env.getTypeUtils();

    this.annotationType = annotation.getAnnotationType();
    this.annotationElt = (TypeElement) annotationType.asElement();

    this.elementValues = new LinkedHashMap<>();
    // AnnotationValues are immutable so putAll should suffice
    this.elementValues.putAll(annotation.getElementValues());
  }

  /**
   * Returns the type element of the annotation that is being built.
   *
   * @return the type element of the annotation that is being built
   */
  public TypeElement getAnnotationElt() {
    return annotationElt;
  }

  /**
   * Creates a mapping between element/field names and values.
   *
   * @param elementName the name of an element/field to initialize
   * @param elementValue the initial value for the element/field
   * @return a mappnig from the element name to the element value
   */
  public static Map<String, AnnotationValue> elementNamesValues(
      String elementName, Object elementValue) {
    return Collections.singletonMap(elementName, createValue(elementValue));
  }

  /**
   * Creates an {@link AnnotationMirror} that uses default values for elements/fields.
   * getElementValues on the result returns default values. If any element does not have a default,
   * this method throws an exception.
   *
   * <p>Most clients should use {@link #fromName}, using a Name created by the compiler. This method
   * is provided as a convenience to create an AnnotationMirror from scratch in a checker's code.
   *
   * @param elements the element utilities to use
   * @param aClass the annotation class
   * @return an {@link AnnotationMirror} of the given type
   * @throws UserError if the annotation corresponding to the class could not be loaded
   */
  public static AnnotationMirror fromClass(Elements elements, Class<? extends Annotation> aClass) {
    return fromClass(elements, aClass, Collections.emptyMap());
  }

  /**
   * Creates an {@link AnnotationMirror} given by a particular annotation class and a name-to-value
   * mapping for the elements/fields.
   *
   * <p>For other elements, getElementValues on the result returns default values. If any such
   * element does not have a default, this method throws an exception.
   *
   * <p>Most clients should use {@link #fromName}, using a Name created by the compiler. This method
   * is provided as a convenience to create an AnnotationMirror from scratch in a checker's code.
   *
   * @param elements the element utilities to use
   * @param aClass the annotation class
   * @param elementNamesValues the values for the annotation's elements/fields
   * @return an {@link AnnotationMirror} of the given type
   */
  public static AnnotationMirror fromClass(
      Elements elements,
      Class<? extends Annotation> aClass,
      Map<String, AnnotationValue> elementNamesValues) {
    String name = aClass.getCanonicalName();
    assert name != null : "@AssumeAssertion(nullness): assumption";
    AnnotationMirror res = fromName(elements, name, elementNamesValues);
    if (res == null) {
      throw new UserError(
          "AnnotationBuilder: error: fromClass can't load Class %s%n"
              + "ensure the class is on the compilation classpath",
          name);
    }
    return res;
  }

  /**
   * Creates an {@link AnnotationMirror} given by a particular fully-qualified name.
   * getElementValues on the result returns default values. If any element does not have a default,
   * this method throws an exception.
   *
   * <p>This method returns null if the annotation corresponding to the name could not be loaded.
   *
   * @param elements the element utilities to use
   * @param name the name of the annotation to create
   * @return an {@link AnnotationMirror} of type {@code} name or null if the annotation couldn't be
   *     loaded
   */
  public static @Nullable AnnotationMirror fromName(
      Elements elements, @FullyQualifiedName CharSequence name) {
    return fromName(elements, name, Collections.emptyMap());
  }

  /**
   * Creates an {@link AnnotationMirror} given by a particular fully-qualified name and
   * element/field values. If any element is not specified by the {@code elementValues} argument,
   * the default value is used. If any such element does not have a default, this method throws an
   * exception.
   *
   * <p>This method returns null if the annotation corresponding to the name could not be loaded.
   *
   * @param elements the element utilities to use
   * @param name the name of the annotation to create
   * @param elementNamesValues the values for the annotation's elements/fields
   * @return an {@link AnnotationMirror} of type {@code} name or null if the annotation couldn't be
   *     loaded
   */
  public static @Nullable AnnotationMirror fromName(
      Elements elements,
      @FullyQualifiedName CharSequence name,
      Map<String, AnnotationValue> elementNamesValues) {
    final TypeElement annoElt = elements.getTypeElement(name);
    if (annoElt == null) {
      return null;
    }
    if (annoElt.getKind() != ElementKind.ANNOTATION_TYPE) {
      throw new BugInCF(annoElt + " is not an annotation");
    }

    final DeclaredType annoType = (DeclaredType) annoElt.asType();
    if (annoType == null) {
      return null;
    }

    List<ExecutableElement> methods = ElementFilter.methodsIn(annoElt.getEnclosedElements());
    Map<ExecutableElement, AnnotationValue> elementValues = new LinkedHashMap<>(methods.size());
    for (ExecutableElement annoElement : methods) {
      AnnotationValue elementValue = elementNamesValues.get(annoElement.getSimpleName().toString());
      if (elementValue == null) {
        AnnotationValue defaultValue = annoElement.getDefaultValue();
        if (defaultValue == null) {
          throw new BugInCF(
              "AnnotationBuilder.fromName: no value for element %s of %s", annoElement, name);
        } else {
          elementValue = defaultValue;
        }
      }
      elementValues.put(annoElement, elementValue);
    }

    AnnotationMirror result = new CheckerFrameworkAnnotationMirror(annoType, elementValues);
    return result;
  }

  /** Whether or not {@link #build()} has been called. */
  private boolean wasBuilt = false;

  private void assertNotBuilt() {
    if (wasBuilt) {
      throw new BugInCF("AnnotationBuilder: error: type was already built");
    }
  }

  public AnnotationMirror build() {
    assertNotBuilt();
    wasBuilt = true;
    return new CheckerFrameworkAnnotationMirror(annotationType, elementValues);
  }

  /**
   * Copies every element value from the given annotation. If an element in the given annotation
   * doesn't exist in the annotation to be built, an error is raised unless the element is specified
   * in {@code ignorableElements}.
   *
   * @param other the annotation that holds the values to be copied; need not be an annotation of
   *     the same type of the one being built
   * @param ignorableElements the names of elements of {@code other} that can be safely dropped
   */
  public void copyElementValuesFromAnnotation(AnnotationMirror other, String... ignorableElements) {
    List<String> ignorableElementsList = Arrays.asList(ignorableElements);
    for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> eltValToCopy :
        other.getElementValues().entrySet()) {
      Name eltNameToCopy = eltValToCopy.getKey().getSimpleName();
      if (ignorableElementsList.contains(eltNameToCopy.toString())) {
        continue;
      }
      elementValues.put(findElement(eltNameToCopy), eltValToCopy.getValue());
    }
  }

  /**
   * Copies every element value from the given annotation. If an element in the given annotation
   * doesn't exist in the annotation to be built, an error is raised unless the element is specified
   * in {@code ignorableElements}.
   *
   * @param valueHolder the annotation that holds the values to be copied; must be the same type as
   *     the annotation being built
   * @param ignorableElements the elements that can be safely dropped
   */
  public void copyElementValuesFromAnnotation(
      AnnotationMirror valueHolder, Collection<ExecutableElement> ignorableElements) {
    for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry :
        valueHolder.getElementValues().entrySet()) {
      if (ignorableElements.contains(entry.getKey())) {
        continue;
      }
      elementValues.put(entry.getKey(), entry.getValue());
    }
  }

  /**
   * Copies the specified element values from the given annotation, using the specified renaming
   * map. Each value in the map must be an element name in the annotation being built. If an element
   * from the given annotation is not a key in the map, it is ignored.
   *
   * @param valueHolder the annotation that holds the values to be copied
   * @param elementNameRenaming a map from element names in {@code valueHolder} to element names of
   *     the annotation being built
   */
  public void copyRenameElementValuesFromAnnotation(
      AnnotationMirror valueHolder, Map<String, String> elementNameRenaming) {

    for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> eltValToCopy :
        valueHolder.getElementValues().entrySet()) {

      String sourceName = eltValToCopy.getKey().getSimpleName().toString();
      String targetName = elementNameRenaming.get(sourceName);
      if (targetName == null) {
        continue;
      }
      elementValues.put(findElement(targetName), eltValToCopy.getValue());
    }
  }

  /** Set the element/field with the given name, to the given value. */
  public AnnotationBuilder setValue(CharSequence elementName, AnnotationMirror value) {
    setValue(elementName, (Object) value);
    return this;
  }

  /**
   * Set the element/field with the given name, to the given value.
   *
   * @param elementName the element/field name
   * @param values the new value for the element/field
   * @return this
   */
  public AnnotationBuilder setValue(CharSequence elementName, List<? extends Object> values) {
    assertNotBuilt();
    ExecutableElement var = findElement(elementName);
    return setValue(var, values);
  }

  /**
   * Set the element to the given value.
   *
   * @param element the element
   * @param values the new value for the element
   * @return this
   */
  public AnnotationBuilder setValue(
      ExecutableElement element, List<? extends @NonNull Object> values) {
    assertNotBuilt();
    TypeMirror expectedType = element.getReturnType();
    if (expectedType.getKind() != TypeKind.ARRAY) {
      throw new BugInCF("value is an array while expected type is not");
    }
    expectedType = ((ArrayType) expectedType).getComponentType();

    List<AnnotationValue> avalues = new ArrayList<>(values.size());
    for (Object v : values) {
      checkSubtype(expectedType, v);
      avalues.add(createValue(v));
    }
    AnnotationValue aval = createValue(avalues);
    elementValues.put(element, aval);
    return this;
  }

  /** Set the element/field with the given name, to the given value. */
  public AnnotationBuilder setValue(CharSequence elementName, Object[] values) {
    return setValue(elementName, Arrays.asList(values));
  }

  /** Set the element/field with the given name, to the given value. */
  public AnnotationBuilder setValue(CharSequence elementName, Boolean value) {
    return setValue(elementName, (Object) value);
  }

  /** Set the element/field with the given name, to the given value. */
  public AnnotationBuilder setValue(CharSequence elementName, Character value) {
    return setValue(elementName, (Object) value);
  }

  /** Set the element/field with the given name, to the given value. */
  public AnnotationBuilder setValue(CharSequence elementName, Double value) {
    return setValue(elementName, (Object) value);
  }

  /** Set the element/field with the given name, to the given value. */
  public AnnotationBuilder setValue(CharSequence elementName, Float value) {
    return setValue(elementName, (Object) value);
  }

  /** Set the element/field with the given name, to the given value. */
  public AnnotationBuilder setValue(CharSequence elementName, Integer value) {
    return setValue(elementName, (Object) value);
  }

  /** Set the element/field with the given name, to the given value. */
  public AnnotationBuilder setValue(CharSequence elementName, Long value) {
    return setValue(elementName, (Object) value);
  }

  /** Set the element/field with the given name, to the given value. */
  public AnnotationBuilder setValue(CharSequence elementName, Short value) {
    return setValue(elementName, (Object) value);
  }

  /** Set the element/field with the given name, to the given value. */
  public AnnotationBuilder setValue(CharSequence elementName, String value) {
    return setValue(elementName, (Object) value);
  }

  /**
   * Remove the element/field with the given name. Does not err if no such element/field is present.
   */
  public AnnotationBuilder removeElement(CharSequence elementName) {
    assertNotBuilt();
    ExecutableElement var = findElement(elementName);
    elementValues.remove(var);
    return this;
  }

  private TypeMirror getErasedOrBoxedType(TypeMirror type) {
    // See com.sun.tools.javac.code.Attribute.Class.makeClassType()
    return type.getKind().isPrimitive()
        ? types.boxedClass((PrimitiveType) type).asType()
        : types.erasure(type);
  }

  public AnnotationBuilder setValue(CharSequence elementName, TypeMirror value) {
    assertNotBuilt();
    value = getErasedOrBoxedType(value);
    AnnotationValue val = createValue(value);
    ExecutableElement var = findElement(elementName);
    // Check subtyping
    if (!TypesUtils.isClass(var.getReturnType())) {
      throw new BugInCF("expected " + var.getReturnType());
    }

    elementValues.put(var, val);
    return this;
  }

  /**
   * Given a class, return the corresponding TypeMirror.
   *
   * @param clazz a class
   * @return the TypeMirror corresponding to the given class
   */
  private TypeMirror typeFromClass(Class<?> clazz) {
    return TypesUtils.typeFromClass(clazz, types, elements);
  }

  public AnnotationBuilder setValue(CharSequence elementName, Class<?> value) {
    TypeMirror type = typeFromClass(value);
    return setValue(elementName, getErasedOrBoxedType(type));
  }

  public AnnotationBuilder setValue(CharSequence elementName, Enum<?> value) {
    assertNotBuilt();
    VariableElement enumElt = findEnumElement(value);
    return setValue(elementName, enumElt);
  }

  public AnnotationBuilder setValue(CharSequence elementName, VariableElement value) {
    ExecutableElement var = findElement(elementName);
    if (var.getReturnType().getKind() != TypeKind.DECLARED) {
      throw new BugInCF("expected a non enum: " + var.getReturnType());
    }
    if (!((DeclaredType) var.getReturnType()).asElement().equals(value.getEnclosingElement())) {
      throw new BugInCF("expected a different type of enum: " + value.getEnclosingElement());
    }
    elementValues.put(var, createValue(value));
    return this;
  }

  // Keep this version synchronized with the VariableElement[] version below
  public AnnotationBuilder setValue(CharSequence elementName, Enum<?>[] values) {
    assertNotBuilt();

    if (values.length == 0) {
      setValue(elementName, Collections.emptyList());
      return this;
    }

    VariableElement enumElt = findEnumElement(values[0]);
    ExecutableElement var = findElement(elementName);

    TypeMirror expectedType = var.getReturnType();
    if (expectedType.getKind() != TypeKind.ARRAY) {
      throw new BugInCF("expected a non array: " + var.getReturnType());
    }

    expectedType = ((ArrayType) expectedType).getComponentType();
    if (expectedType.getKind() != TypeKind.DECLARED) {
      throw new BugInCF("expected a non enum component type: " + var.getReturnType());
    }
    if (!((DeclaredType) expectedType).asElement().equals(enumElt.getEnclosingElement())) {
      throw new BugInCF("expected a different type of enum: " + enumElt.getEnclosingElement());
    }

    List<AnnotationValue> res = new ArrayList<>(values.length);
    for (Enum<?> ev : values) {
      checkSubtype(expectedType, ev);
      enumElt = findEnumElement(ev);
      res.add(createValue(enumElt));
    }
    AnnotationValue val = createValue(res);
    elementValues.put(var, val);
    return this;
  }

  // Keep this version synchronized with the Enum<?>[] version above.
  // Which one is more useful/general? Unifying adds overhead of creating
  // another array.
  public AnnotationBuilder setValue(CharSequence elementName, VariableElement[] values) {
    assertNotBuilt();
    ExecutableElement var = findElement(elementName);

    TypeMirror expectedType = var.getReturnType();
    if (expectedType.getKind() != TypeKind.ARRAY) {
      throw new BugInCF("expected an array, but found: " + expectedType);
    }

    expectedType = ((ArrayType) expectedType).getComponentType();
    if (expectedType.getKind() != TypeKind.DECLARED) {
      throw new BugInCF(
          "expected a declared component type, but found: "
              + expectedType
              + " kind: "
              + expectedType.getKind());
    }
    if (!types.isSameType((DeclaredType) expectedType, values[0].asType())) {
      throw new BugInCF(
          "expected a different declared component type: " + expectedType + " vs. " + values[0]);
    }

    List<AnnotationValue> res = new ArrayList<>(values.length);
    for (VariableElement ev : values) {
      checkSubtype(expectedType, ev);
      // Is there a better way to distinguish between enums and
      // references to constants?
      if (ev.getConstantValue() != null) {
        res.add(createValue(ev.getConstantValue()));
      } else {
        res.add(createValue(ev));
      }
    }
    AnnotationValue val = createValue(res);
    elementValues.put(var, val);
    return this;
  }

  /** Find the VariableElement for the given enum. */
  private VariableElement findEnumElement(Enum<?> value) {
    String enumClass = value.getDeclaringClass().getCanonicalName();
    assert enumClass != null : "@AssumeAssertion(nullness): assumption";
    TypeElement enumClassElt = elements.getTypeElement(enumClass);
    assert enumClassElt != null;
    for (Element enumElt : enumClassElt.getEnclosedElements()) {
      if (enumElt.getSimpleName().contentEquals(value.name())) {
        return (VariableElement) enumElt;
      }
    }
    throw new BugInCF("cannot be here");
  }

  private AnnotationBuilder setValue(CharSequence key, Object value) {
    assertNotBuilt();
    AnnotationValue val = createValue(value);
    ExecutableElement var = findElement(key);
    checkSubtype(var.getReturnType(), value);
    elementValues.put(var, val);
    return this;
  }

  public ExecutableElement findElement(CharSequence key) {
    for (ExecutableElement elt : ElementFilter.methodsIn(annotationElt.getEnclosedElements())) {
      if (elt.getSimpleName().contentEquals(key)) {
        return elt;
      }
    }
    throw new BugInCF("Couldn't find " + key + " element in " + annotationElt);
  }

  /** @throws BugInCF if the type of {@code givenValue} is not the same as {@code expected} */
  private void checkSubtype(TypeMirror expected, Object givenValue) {
    if (expected.getKind().isPrimitive()) {
      expected = types.boxedClass((PrimitiveType) expected).asType();
    }

    if (expected.getKind() == TypeKind.DECLARED
        && TypesUtils.isClass(expected)
        && givenValue instanceof TypeMirror) {
      return;
    }

    TypeMirror found;
    boolean isSubtype;

    if (expected.getKind() == TypeKind.DECLARED
        && ((DeclaredType) expected).asElement().getKind() == ElementKind.ANNOTATION_TYPE
        && givenValue instanceof AnnotationMirror) {
      found = ((AnnotationMirror) givenValue).getAnnotationType();
      isSubtype = ((DeclaredType) expected).asElement().equals(((DeclaredType) found).asElement());
    } else if (givenValue instanceof AnnotationMirror) {
      found = ((AnnotationMirror) givenValue).getAnnotationType();
      // TODO: why is this always failing???
      isSubtype = false;
    } else if (givenValue instanceof VariableElement) {
      found = ((VariableElement) givenValue).asType();
      if (expected.getKind() == TypeKind.DECLARED) {
        isSubtype = types.isSubtype(types.erasure(found), types.erasure(expected));
      } else {
        isSubtype = false;
      }
    } else {
      String name = givenValue.getClass().getCanonicalName();
      assert name != null : "@AssumeAssertion(nullness): assumption";
      found = elements.getTypeElement(name).asType();
      isSubtype = types.isSubtype(types.erasure(found), types.erasure(expected));
    }
    if (!isSubtype) {
      // Annotations in stub files sometimes are the same type, but Types#isSubtype fails anyways.
      isSubtype = found.toString().equals(expected.toString());
    }

    if (!isSubtype) {
      throw new BugInCF(
          "given value differs from expected; " + "found: " + found + "; expected: " + expected);
    }
  }

  /**
   * Create an AnnotationValue -- a value for an annotation element/field.
   *
   * @param obj the value to be stored in an annotation element/field
   * @return an AnnotationValue for the given Java value
   */
  private static AnnotationValue createValue(final Object obj) {
    return new CheckerFrameworkAnnotationValue(obj);
  }

  /** Implementation of AnnotationMirror used by the Checker Framework. */
  /* default visibility to allow access from within package. */
  static class CheckerFrameworkAnnotationMirror implements AnnotationMirror {
    /** The interned toString value. */
    private @Nullable @Interned String toStringVal;
    /** The annotation type. */
    private final DeclaredType annotationType;
    /** The element values. */
    private final Map<ExecutableElement, AnnotationValue> elementValues;
    /** The annotation name. */
    // default visibility to allow access from within package.
    final @Interned @CanonicalName String annotationName;

    /**
     * Create a CheckerFrameworkAnnotationMirror.
     *
     * @param annotationType the annotation type
     * @param elementValues the element values
     */
    @SuppressWarnings("signature:assignment") // needs JDK annotations
    CheckerFrameworkAnnotationMirror(
        DeclaredType annotationType, Map<ExecutableElement, AnnotationValue> elementValues) {
      this.annotationType = annotationType;
      final TypeElement elm = (TypeElement) annotationType.asElement();
      this.annotationName = elm.getQualifiedName().toString().intern();
      this.elementValues = elementValues;
    }

    @Override
    public DeclaredType getAnnotationType() {
      return annotationType;
    }

    @Override
    public Map<? extends ExecutableElement, ? extends AnnotationValue> getElementValues() {
      return Collections.unmodifiableMap(elementValues);
    }

    @SideEffectFree
    @Override
    public String toString() {
      if (toStringVal != null) {
        return toStringVal;
      }
      StringBuilder buf = new StringBuilder();
      buf.append("@");
      buf.append(annotationName);
      int len = elementValues.size();
      if (len > 0) {
        buf.append('(');
        boolean first = true;
        for (Map.Entry<ExecutableElement, AnnotationValue> pair : elementValues.entrySet()) {
          if (!first) {
            buf.append(", ");
          }
          first = false;

          String name = pair.getKey().getSimpleName().toString();
          if (len > 1 || !name.equals("value")) {
            buf.append(name);
            buf.append('=');
          }
          buf.append(pair.getValue());
        }
        buf.append(')');
      }
      toStringVal = buf.toString().intern();
      return toStringVal;

      // return "@" + annotationType + "(" + elementValues + ")";
    }
  }

  /** Implementation of AnnotationValue used by the Checker Framework. */
  private static class CheckerFrameworkAnnotationValue implements AnnotationValue {
    /** The value. */
    private final Object value;
    /** The interned value of toString. */
    private @Nullable @Interned String toStringVal;

    /** Create an annotation value. */
    CheckerFrameworkAnnotationValue(Object obj) {
      this.value = obj;
    }

    @Override
    public Object getValue() {
      return value;
    }

    @SideEffectFree
    @Override
    public String toString() {
      if (this.toStringVal != null) {
        return this.toStringVal;
      }
      String toStringVal;
      if (value instanceof String) {
        toStringVal = "\"" + value + "\"";
      } else if (value instanceof Character) {
        toStringVal = "\'" + value + "\'";
      } else if (value instanceof List<?>) {
        List<?> list = (List<?>) value;
        toStringVal = "{" + StringsPlume.join(", ", list) + "}";
      } else if (value instanceof VariableElement) {
        // for Enums
        VariableElement var = (VariableElement) value;
        String encl = var.getEnclosingElement().toString();
        if (!encl.isEmpty()) {
          encl = encl + '.';
        }
        toStringVal = encl + var;
      } else if (value instanceof TypeMirror && TypesUtils.isClassType((TypeMirror) value)) {
        toStringVal = value.toString() + ".class";
      } else {
        toStringVal = value.toString();
      }
      this.toStringVal = toStringVal.intern();
      return this.toStringVal;
    }

    @SuppressWarnings("unchecked")
    @Override
    public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) {
      if (value instanceof AnnotationMirror) {
        return v.visitAnnotation((AnnotationMirror) value, p);
      } else if (value instanceof List) {
        return v.visitArray((List<? extends AnnotationValue>) value, p);
      } else if (value instanceof Boolean) {
        return v.visitBoolean((Boolean) value, p);
      } else if (value instanceof Character) {
        return v.visitChar((Character) value, p);
      } else if (value instanceof Double) {
        return v.visitDouble((Double) value, p);
      } else if (value instanceof VariableElement) {
        return v.visitEnumConstant((VariableElement) value, p);
      } else if (value instanceof Float) {
        return v.visitFloat((Float) value, p);
      } else if (value instanceof Integer) {
        return v.visitInt((Integer) value, p);
      } else if (value instanceof Long) {
        return v.visitLong((Long) value, p);
      } else if (value instanceof Short) {
        return v.visitShort((Short) value, p);
      } else if (value instanceof String) {
        return v.visitString((String) value, p);
      } else if (value instanceof TypeMirror) {
        return v.visitType((TypeMirror) value, p);
      } else {
        assert false : " unknown type : " + v.getClass();
        return v.visitUnknown(this, p);
      }
    }

    @Override
    public boolean equals(@Nullable Object obj) {
      // System.out.printf("Calling CFAV.equals()%n");
      if (!(obj instanceof AnnotationValue)) {
        return false;
      }
      AnnotationValue other = (AnnotationValue) obj;
      return Objects.equals(this.getValue(), other.getValue());
    }

    @Override
    public int hashCode() {
      return Objects.hashCode(this.value);
    }
  }
}
