// Path: objectmapper-processor/src/main/java/com/hannesdorfmann/sqlbrite/objectmapper/processor/ColumnAnnotatedMethod.java
// public class ColumnAnnotatedMethod implements ColumnAnnotateable {
// 
//   private ExecutableElement method;
//   private String columnName;
//   private CodeGenerator codeGenerator;
//   private boolean throwOnColumnIndexNotFound;
// 
//   public ColumnAnnotatedMethod(ExecutableElement method, Column annotation)
//       throws ProcessingException {
// 
//     if (!method.getModifiers().contains(Modifier.PUBLIC)) {
//       throw new ProcessingException(method,
//           "Setter method %s in %s annotated with @%s is not public. Only PUBLIC setter methods are supported",
//           method.getSimpleName().toString(), method.getEnclosingElement().toString(),
//           Column.class.getSimpleName());
//     }
// 
//     if (method.getParameters().size() != 1) {
//       throw new ProcessingException(method,
//           "Setter method %s in %s annotated with @%s MUST have exactly one parameter!",
//           method.toString(), method.getEnclosingElement().toString(), Column.class.getSimpleName());
//     }
// 
//     columnName = annotation.value();
//     if (columnName == null || columnName.length() == 0) {
//       throw new ProcessingException(method, "The column name is unspecified for method %s in %s",
//           method.getSimpleName().toString(), method.getEnclosingElement().toString());
//     }
// 
//     throwOnColumnIndexNotFound = annotation.throwOnColumnIndexNotFound();
//     this.method = method;
// 
//     codeGenerator = MethodCodeFactory.get(this);
//   }
// 
//   @Override public void generateAssignStatement(CodeBlock.Builder builder, String objectVarName,
//       String cursorVarName, String indexVarName) {
// 
//     codeGenerator.generateAssignStatement(builder, objectVarName, cursorVarName, indexVarName);
//   }
// 
//   @Override public String getColumnName() {
//     return columnName;
//   }
// 
//   @Override public String getElementName() {
//     return method.toString();
//   }
// 
//   @Override public String getQualifiedSurroundingClassName() {
//     TypeElement typeElement = (TypeElement) method.getEnclosingElement();
//     return typeElement.getQualifiedName().toString();
//   }
// 
//   public String getMethodName() {
//     return method.getSimpleName().toString();
//   }
// 
//   public ExecutableElement getMethod() {
//     return method;
//   }
// 
//   public VariableElement getParameter() {
//     return method.getParameters().get(0);
//   }
// 
//   @Override public void generateContentValuesBuilderMethod(TypeSpec.Builder builder, TypeName type,
//       String contentValuesVarName) {
//     codeGenerator.generateContentValuesBuilderMethod(builder, type, contentValuesVarName);
//   }
// 
//   @Override public boolean isThrowOnColumnIndexNotFound() {
//     return throwOnColumnIndexNotFound;
//   }
// }
// 
// Path: objectmapper-processor/src/main/java/com/hannesdorfmann/sqlbrite/objectmapper/processor/generator/CodeGenerator.java
// public interface CodeGenerator {
// 
//   /**
//    * Generate the code for reading cursor into the object
//    *
//    * @param builder the {@link CodeBlock.Builder}
//    * @param objectVarName The variable name of the object that gets instantiated and filled with
//    * data from cursor
//    * @param cursorVarName The variable name of the cursor from which you should read
//    * @param indexVarName The variable name of the index of the column
//    */
//   void generateAssignStatement(CodeBlock.Builder builder, String objectVarName,
//       String cursorVarName, String indexVarName);
// 
//   void generateContentValuesBuilderMethod(TypeSpec.Builder builder, TypeName type,
//       String contentValuesVarName);
// }


import com.hannesdorfmann.sqlbrite.objectmapper.processor.ColumnAnnotatedMethod;
import com.hannesdorfmann.sqlbrite.objectmapper.processor.generator.CodeGenerator;
import com.squareup.javapoet.CodeBlock;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
import javax.lang.model.element.Modifier;
package com.hannesdorfmann.sqlbrite.objectmapper.processor.generator.method;


/**
 * Generates the code to assign cursor data throught setter methods
 *
 * @author Hannes Dorfmann
 */
public class DateMethodCodeGenerator implements CodeGenerator {

  protected ColumnAnnotatedMethod method;

  public DateMethodCodeGenerator(ColumnAnnotatedMethod method) {
    this.method = method;
  }

  @Override public void generateAssignStatement(CodeBlock.Builder builder, String objectVarName,
      String cursorVarName, String indexVarName) {

    builder.addStatement("$L.$L( new java.util.Date($L.getLong( $L ) ) )", objectVarName, method.getMethodName(),
        cursorVarName, indexVarName);
  }


  @Override public void generateContentValuesBuilderMethod(TypeSpec.Builder builder,
      TypeName type, String contentValuesVarName) {

    String methodName = method.getMethodName();
    if (methodName.matches("set[A-Z]")){
      methodName = methodName.substring(3).toLowerCase();
    }

    builder.addMethod(MethodSpec.methodBuilder(methodName)
        .addJavadoc("Adds the given value to this ContentValues \n *")
        .addJavadoc("@param value The value \n *")
        .addJavadoc("@return $T", type)
        .addModifiers(Modifier.PUBLIC)
        .addParameter(TypeName.get(method.getParameter().asType()), "value", Modifier.FINAL)
        .returns(type)
// Path: objectmapper-processor/src/main/java/com/hannesdorfmann/sqlbrite/objectmapper/processor/ColumnAnnotatedMethod.java
// public class ColumnAnnotatedMethod implements ColumnAnnotateable {
// 
//   private ExecutableElement method;
//   private String columnName;
//   private CodeGenerator codeGenerator;
//   private boolean throwOnColumnIndexNotFound;
// 
//   public ColumnAnnotatedMethod(ExecutableElement method, Column annotation)
//       throws ProcessingException {
// 
//     if (!method.getModifiers().contains(Modifier.PUBLIC)) {
//       throw new ProcessingException(method,
//           "Setter method %s in %s annotated with @%s is not public. Only PUBLIC setter methods are supported",
//           method.getSimpleName().toString(), method.getEnclosingElement().toString(),
//           Column.class.getSimpleName());
//     }
// 
//     if (method.getParameters().size() != 1) {
//       throw new ProcessingException(method,
//           "Setter method %s in %s annotated with @%s MUST have exactly one parameter!",
//           method.toString(), method.getEnclosingElement().toString(), Column.class.getSimpleName());
//     }
// 
//     columnName = annotation.value();
//     if (columnName == null || columnName.length() == 0) {
//       throw new ProcessingException(method, "The column name is unspecified for method %s in %s",
//           method.getSimpleName().toString(), method.getEnclosingElement().toString());
//     }
// 
//     throwOnColumnIndexNotFound = annotation.throwOnColumnIndexNotFound();
//     this.method = method;
// 
//     codeGenerator = MethodCodeFactory.get(this);
//   }
// 
//   @Override public void generateAssignStatement(CodeBlock.Builder builder, String objectVarName,
//       String cursorVarName, String indexVarName) {
// 
//     codeGenerator.generateAssignStatement(builder, objectVarName, cursorVarName, indexVarName);
//   }
// 
//   @Override public String getColumnName() {
//     return columnName;
//   }
// 
//   @Override public String getElementName() {
//     return method.toString();
//   }
// 
//   @Override public String getQualifiedSurroundingClassName() {
//     TypeElement typeElement = (TypeElement) method.getEnclosingElement();
//     return typeElement.getQualifiedName().toString();
//   }
// 
//   public String getMethodName() {
//     return method.getSimpleName().toString();
//   }
// 
//   public ExecutableElement getMethod() {
//     return method;
//   }
// 
//   public VariableElement getParameter() {
//     return method.getParameters().get(0);
//   }
// 
//   @Override public void generateContentValuesBuilderMethod(TypeSpec.Builder builder, TypeName type,
//       String contentValuesVarName) {
//     codeGenerator.generateContentValuesBuilderMethod(builder, type, contentValuesVarName);
//   }
// 
//   @Override public boolean isThrowOnColumnIndexNotFound() {
//     return throwOnColumnIndexNotFound;
//   }
// }
// 
// Path: objectmapper-processor/src/main/java/com/hannesdorfmann/sqlbrite/objectmapper/processor/generator/CodeGenerator.java
// public interface CodeGenerator {
// 
//   /**
//    * Generate the code for reading cursor into the object
//    *
//    * @param builder the {@link CodeBlock.Builder}
//    * @param objectVarName The variable name of the object that gets instantiated and filled with
//    * data from cursor
//    * @param cursorVarName The variable name of the cursor from which you should read
//    * @param indexVarName The variable name of the index of the column
//    */
//   void generateAssignStatement(CodeBlock.Builder builder, String objectVarName,
//       String cursorVarName, String indexVarName);
// 
//   void generateContentValuesBuilderMethod(TypeSpec.Builder builder, TypeName type,
//       String contentValuesVarName);
// }


// Path: objectmapper-processor/src/main/java/com/hannesdorfmann/sqlbrite/objectmapper/processor/generator/method/DateMethodCodeGenerator.java
import com.hannesdorfmann.sqlbrite.objectmapper.processor.ColumnAnnotatedMethod;
import com.hannesdorfmann.sqlbrite.objectmapper.processor.generator.CodeGenerator;
import com.squareup.javapoet.CodeBlock;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
import javax.lang.model.element.Modifier;

package com.hannesdorfmann.sqlbrite.objectmapper.processor.generator.method;


/**
 * Generates the code to assign cursor data throught setter methods
 *
 * @author Hannes Dorfmann
 */
public class DateMethodCodeGenerator implements CodeGenerator {

  protected ColumnAnnotatedMethod method;

  public DateMethodCodeGenerator(ColumnAnnotatedMethod method) {
    this.method = method;
  }

  @Override public void generateAssignStatement(CodeBlock.Builder builder, String objectVarName,
      String cursorVarName, String indexVarName) {

    builder.addStatement("$L.$L( new java.util.Date($L.getLong( $L ) ) )", objectVarName, method.getMethodName(),
        cursorVarName, indexVarName);
  }


  @Override public void generateContentValuesBuilderMethod(TypeSpec.Builder builder,
      TypeName type, String contentValuesVarName) {

    String methodName = method.getMethodName();
    if (methodName.matches("set[A-Z]")){
      methodName = methodName.substring(3).toLowerCase();
    }

    builder.addMethod(MethodSpec.methodBuilder(methodName)
        .addJavadoc("Adds the given value to this ContentValues \n *")
        .addJavadoc("@param value The value \n *")
        .addJavadoc("@return $T", type)
        .addModifiers(Modifier.PUBLIC)
        .addParameter(TypeName.get(method.getParameter().asType()), "value", Modifier.FINAL)
        .returns(type)
        .addStatement("$L.put($S, value.getTime())", contentValuesVarName, method.getColumnName())