package com.google.auto.value.extension;

import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Set;

import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;

/**
 * An AutoValueExtension allows for extra functionality to be created during the generation
 * of an AutoValue class.
 *
 * <p>NOTE: The design of this interface is not final and subject to change.
 *
 * <p>Extensions are discovered at compile time using the {@link java.util.ServiceLoader} APIs,
 * allowing them to run without any additional annotations.
 *
 * <p>Extensions can extend the AutoValue implementation by generating subclasses of the AutoValue
 * generated class. It is not guaranteed that an Extension's generated class will be the final
 * class in the inheritance hierarchy, unless its {@link #mustBeFinal()} method returns true. Only
 * one Extension can return true for a given context. Only generated classes that will be the
 * final class in the inheritance hierarchy can be declared final. All others should be declared
 * abstract.
 *
 * <p>Each Extension must also be sure to generate a constructor with arguments corresponding to
 * all properties in {@link com.google.auto.value.AutoValueExtension.Context#properties()}, in
 * order. This constructor must have at least package visibility.
 */
public abstract class AutoValueExtension {

  /**
   * The context of the generation cycle.
   */
  public interface Context {

    /**
     * The processing environment of this generation cycle.
     *
     * @return The ProcessingEnvironment of this generation cycle.
     */
    ProcessingEnvironment processingEnvironment();

    /**
     * The package name of the classes to be generated.
     *
     * @return The package name of the classes to be generated.
     */
    String packageName();

    /**
     * The annotated class that this generation cycle is based on.
     *
     * <p>Given {@code @AutoValue public class Foo {...}}, this will be {@code Foo}.
     *
     * @return The annotated class.
     */
    TypeElement autoValueClass();

    /**
     * The ordered collection of properties to be generated by AutoValue.
     *
     * @return The ordered collection of properties.
     */
    Map<String, ExecutableElement> properties();
  }

  /**
   * Determines whether this extension applies to the given context.
   *
   * @param context The Context of the code generation for this class.
   * @return True if this extension should be applied in the given context.
   */
  public boolean applicable(Context context) {
    return false;
  }

  /**
   * Denotes that the class generated by this Extension must be the final class
   * in the inheritance hierarchy.  Only one extension may be the final class, so
   * this should be used sparingly.
   *
   * @param context The {@link com.google.auto.value.AutoValueExtension.Context} of the code
   *                generation for this class.
   * @return True if the resulting class must be the final class in the inheritance hierarchy.
   */
  public boolean mustBeFinal(Context context) {
    return false;
  }

  /**
   * Returns a non-null set of property names from {@link #properties()} that this extension intends
   * to implement.  This will prevent AutoValue from generating an implementation, and remove the
   * supplied properties from builders, constructors, {@code toString}, {@code equals},
   * and {@code hashCode}. The default set returned by this method is empty.
   *
   * <p>For example, Android's {@code Parcelable} interface includes a
   * <a href="http://developer.android.com/reference/android/os/Parcelable.html#describeContents()">method</a>
   * {@code int describeContents()}. Since this is an abstract method with no parameters, by
   * default AutoValue will consider that it defines an {@code int} property called
   * {@code describeContents}. If an {@code @AutoValue} class implements {@code Parcelable} and does
   * not provide an implementation of this method, by default its implementation will include
   * {@code describeContents} in builders, constructors, and so on. But an
   * {@code AutoValueExtension} that understands {@code Parcelable} can instead provide a useful
   * implementation and return a set containing {@code "describeContents"}. Then
   * {@code describeContents} will be omitted from builders and the rest.
   *
   * @param context The {@link com.google.auto.value.AutoValueExtension.Context} of the code
   *     generation for this class.
   * @return A collection of property names that this extension intends to implement.
   */
  public Set<String> consumeProperties(Context context) {
    return Collections.emptySet();
  }

  /**
   * Generates the source code of the class named {@code className} to extend
   * {@code classToExtend}, with the original annotated class of
   * {@code classToImplement}.  The generated class should be final if {@code isFinal}
   * is true; otherwise it should be abstract.
   *
   * @param context The {@link Context} of the code generation for this class.
   * @param className The name of the resulting class. The returned code will be written to a
   *     file named accordingly.
   * @param classToExtend The direct parent of the generated class. Could be the AutoValue
   *     generated class, or a class generated as the result of another
   *     extension.
   * @param isFinal True if this class is the last class in the chain, meaning it should be
   *     marked as final, otherwise it should be marked as abstract.
   * @return The source code of the generated class
   */
  public abstract String generateClass(
      Context context, String className, String classToExtend, boolean isFinal);
}

@@ -39,37 +39,8 @@
 n;%0A%0A
-import java.util.Collection;%0A
 impo
@@ -65,16 +65,16 @@
 ctions;%0A
+
 import j
@@ -893,16 +893,23 @@
 BeFinal(
+Context
 )%7D metho
@@ -927,16 +927,16 @@
 rue.
+%0A *
  Only
-%0A *
  one
@@ -1253,16 +1253,19 @@
 rties in
+%0A *
  %7B@link 
@@ -1278,32 +1278,42 @@
 ogle.auto.value.
+extension.
 AutoValueExtensi
@@ -1340,19 +1340,16 @@
 s()%7D, in
-%0A *
  order. 
@@ -1352,16 +1352,19 @@
 er. This
+%0A *
  constru
@@ -2908,64 +2908,15 @@
 The 
-%7B@link com.google.auto.value.AutoValueExtension.
 Context
-%7D
  of 
@@ -2927,28 +2927,8 @@
 code
-%0A   *               
  gen
@@ -3187,16 +3187,23 @@
  %7B@link 
+Context
 #propert
@@ -3228,24 +3228,29 @@
 xtension
+%0A   *
  intends
 %0A   * to
@@ -3241,21 +3241,16 @@
  intends
-%0A   *
  to impl
@@ -3255,17 +3255,16 @@
 plement.
- 
  This wi
@@ -3333,17 +3333,17 @@
 move
- the
 %0A   *
+ the
  sup
@@ -4418,64 +4418,15 @@
 The 
-%7B@link com.google.auto.value.AutoValueExtension.
 Context
-%7D
  of 
@@ -4433,25 +4433,16 @@
 the code
-%0A   *    
  generat

Fix the javadoc of AutoValueExtension, based on the changes in https://github.com/google/auto/pull/285 by rharter.