package com.gabrielittner.auto.value.util;

import com.google.common.collect.ImmutableSet;
import com.squareup.javapoet.TypeName;
import java.util.Set;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.ExecutableElement;

/**
 * A Property of the AutoValue annotated class.
 *
 * This convenience class wraps the {@link ExecutableElement} for properties provided by the
 * AutoValueExtension.Context to make accessing values easier.
 *
 * It is recommended that you get the {@link #humanName} directly from the properties returned
 * from the AutoValueExtension.Context#properties method.
 *
 * <pre>
 * ImmutableList.Builder<Property> values = ImmutableList.builder();
 * for (Map.Entry<String, ExecutableElement> entry : context.properties().entrySet()) {
 *   values.add(new Property(entry.getKey(), entry.getValue()));
 * }
 * return values.build();
 * </pre>
 */
public class Property {
  private final String methodName;
  private final String humanName;
  private final ExecutableElement element;
  private final TypeName type;
  private final ImmutableSet<String> annotations;

  public Property(String humanName, ExecutableElement element) {
    this.methodName = element.getSimpleName().toString();
    this.humanName = humanName;
    this.element = element;
    type = TypeName.get(element.getReturnType());
    annotations = ElementUtil.buildAnnotations(element);
  }

  /**
   * The method name of the property.
   */
  public String methodName() {
    return methodName;
  }

  /**
   * The human readable name of the property.  If all properties use {@code get} or {@code is}
   * prefixes, this name will be different from {@link #methodName()}.
   */
  public String humanName() {
    return humanName;
  }

  /**
   * The underlying ExecutableElement representing the get method of the property.
   */
  public ExecutableElement element() {
    return element;
  }

  /**
   * The return type of the property.
   */
  public TypeName type() {
    return type;
  }

  /**
   * The set of annotations present on the original property.
   */
  public Set<String> annotations() {
    return annotations;
  }

  /**
   * True if the property can be null.
   */
  public Boolean nullable() {
    return annotations.contains("Nullable");
  }
}

@@ -37,16 +37,123 @@
 .util;%0A%0A
+import com.google.auto.value.extension.AutoValueExtension;%0Aimport com.google.common.collect.ImmutableList;%0A
 import c
@@ -247,19 +247,19 @@
 va.util.
-Set
+Map
 ;%0Aimport
@@ -267,45 +267,17 @@
 java
-x.lang.model.element.AnnotationMirror
+.util.Set
 ;%0Aim
@@ -996,16 +996,475 @@
 perty %7B%0A
+%0A  /**%0A   * Builds a List of %7B@link Property%7D for the given %7B@link AutoValueExtension.Context%7D.%0A   */%0A  public static ImmutableList%3CProperty%3E buildProperties(AutoValueExtension.Context context) %7B%0A    ImmutableList.Builder%3CProperty%3E values = ImmutableList.builder();%0A    for (Map.Entry%3CString, ExecutableElement%3E entry : context.properties().entrySet()) %7B%0A      values.add(new Property(entry.getKey(), entry.getValue()));%0A    %7D%0A    return values.build();%0A  %7D%0A%0A
   privat

add static method to build Property List