package pocketknife.internal.codegen.builder;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.TypeSpec;
import org.apache.commons.lang3.StringUtils;
import pocketknife.internal.codegen.BaseGenerator;
import pocketknife.internal.codegen.KeySpec;
import pocketknife.internal.codegen.MethodBinding;
import pocketknife.internal.codegen.TypeUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import static javax.lang.model.element.Modifier.FINAL;
import static javax.lang.model.element.Modifier.PRIVATE;
import static javax.lang.model.element.Modifier.PUBLIC;
import static javax.lang.model.element.Modifier.STATIC;
public class BuilderGenerator extends BaseGenerator {
public static final String CONTEXT = "context";
private final String classPackage;
private final String className;
private final String interfaceName;
private List<MethodBinding> methods = new ArrayList<MethodBinding>();
private boolean contextRequired = false;
public BuilderGenerator(String classPackage, String className, String interfaceName, TypeUtil typeUtil) {
super(typeUtil);
this.classPackage = classPackage;
this.className = className;
this.interfaceName = interfaceName;
}
public JavaFile generate() {
TypeSpec.Builder classBuilder = TypeSpec.classBuilder(className)
.addSuperinterface(ClassName.get(classPackage, interfaceName))
.addModifiers(PUBLIC)
.addJavadoc(getGeneratedComment(BuilderGenerator.class));
generateKeys(classBuilder);
if (contextRequired) {
classBuilder.addField(ClassName.get(typeUtil.contextType), CONTEXT, PRIVATE, FINAL);
classBuilder.addMethod(MethodSpec.constructorBuilder()
.addModifiers(PUBLIC)
.addParameter(ClassName.get(typeUtil.contextType), CONTEXT)
.addStatement("this.$N = $N", CONTEXT, CONTEXT)
.build());
}
generateMethods(classBuilder);
return JavaFile.builder(classPackage, classBuilder.build()).build();
}
private void generateKeys(TypeSpec.Builder classBuilder) {
Set<KeySpec> keys = new TreeSet<KeySpec>();
for (MethodBinding method : methods) {
keys.addAll(method.getKeys());
}
for (KeySpec key : keys) {
if (StringUtils.isNotBlank(key.getName())) {
classBuilder.addField(FieldSpec.builder(String.class, key.getName(), PUBLIC, STATIC, FINAL)
.initializer("$S", key.getValue())
.build());
}
}
}
private void generateMethods(TypeSpec.Builder classBuilder) {
for (MethodBinding method : methods) {
classBuilder.addMethod(method.generateMethodSpec(typeUtil));
}
}
public void addMethod(MethodBinding method) {
contextRequired |= method instanceof IntentMethodBinding;
this.methods.add(method);
}
}