package isobuilder.compiler;

import com.google.auto.common.BasicAnnotationProcessor;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.SetMultimap;
import isobuilder.Builder;

import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import java.lang.annotation.Annotation;
import java.util.Set;

import static com.google.auto.common.MoreElements.asType;
import static com.google.common.base.Preconditions.checkState;
import static isobuilder.compiler.BuilderInfo.factoryInfo;
import static javax.lang.model.util.ElementFilter.methodsIn;

public class BuilderStep implements BasicAnnotationProcessor.ProcessingStep {

  private final BuilderGenerator factoryGenerator;

  BuilderStep(BuilderGenerator factoryGenerator) {
    this.factoryGenerator = factoryGenerator;
  }

  @Override
  public Set<? extends Class<? extends Annotation>> annotations() {
    return ImmutableSet.of(Builder.class);
  }

  @Override
  public Set<Element> process(SetMultimap<Class<? extends Annotation>, Element> elementsByAnnotation) {
    Set<Element> elements = elementsByAnnotation.get(Builder.class);
    Set<ExecutableElement> methods = methodsIn(elements);
    checkState(methods.size() == 1, "currently only one method allowed");
    for (ExecutableElement element : methods) {
      try {
        checkState(element.getModifiers().contains(Modifier.STATIC), "target must be static");
        checkState(!element.getModifiers().contains(Modifier.PRIVATE), "target cannot be private");
        TypeElement typeElement = asType(element.getEnclosingElement());
        factoryGenerator.generate(factoryInfo(typeElement, element.getParameters()));
      } catch (SourceFileGenerationException e) {
        e.printStackTrace();
      }
    }
    return ImmutableSet.of();
  }

}

@@ -79,16 +79,101 @@
 cessor;%0A
+import com.google.auto.common.MoreElements;%0Aimport com.google.auto.common.MoreTypes;%0A
 import c
@@ -257,16 +257,56 @@
 ltimap;%0A
+import com.squareup.javapoet.ClassName;%0A
 import i
@@ -421,50 +421,8 @@
 nt;%0A
-import javax.lang.model.element.Modifier;%0A
 impo
@@ -454,32 +454,116 @@
 nt.TypeElement;%0A
+import javax.lang.model.type.DeclaredType;%0Aimport javax.lang.model.type.TypeMirror;%0A
 import java.lang
@@ -663,24 +663,83 @@
 nts.asType;%0A
+import static com.google.auto.common.MoreTypes.asDeclared;%0A
 import stati
@@ -807,51 +807,224 @@
 tic 
-isobuilder.compiler.BuilderInfo.factoryInfo
+com.google.common.collect.Iterables.getFirst;%0Aimport static isobuilder.compiler.BuilderInfo.factoryInfo;%0Aimport static javax.lang.model.element.Modifier.PRIVATE;%0Aimport static javax.lang.model.element.Modifier.STATIC
 ;%0Aim
@@ -1750,16 +1750,26 @@
  method 
+per class 
 allowed%22
@@ -1779,13 +1779,8 @@
     
-for (
 Exec
@@ -1797,28 +1797,41 @@
 ent 
-element : methods) %7B
+method = getFirst(methods, null);
 %0A   
@@ -1858,23 +1858,22 @@
 ckState(
-element
+method
 .getModi
@@ -1889,25 +1889,16 @@
 ontains(
-Modifier.
 STATIC),
@@ -1899,22 +1899,22 @@
 ATIC), %22
-target
+method
  must be
@@ -1944,23 +1944,22 @@
 kState(!
-element
+method
 .getModi
@@ -1975,25 +1975,16 @@
 ontains(
-Modifier.
 PRIVATE)
@@ -1990,14 +1990,14 @@
 ), %22
-target
+method
  can
@@ -2010,24 +2010,94 @@
  private%22);%0A
+        DeclaredType returnType = asDeclared(method.getReturnType());%0A
         Type
@@ -2129,28 +2129,21 @@
 ype(
-element.getEnclosing
+returnType.as
 Elem
@@ -2209,23 +2209,22 @@
 lement, 
-element
+method
 .getPara
@@ -2322,22 +2322,16 @@
       %7D%0A
-    %7D%0A
     retu

use return value