package com.tale.prettybundleprocessor;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeSpec;
import com.squareup.javapoet.TypeVariableName;
import com.tale.prettybundle.ExtraBinder;
import com.tale.prettybundle.Injector;
import com.tale.prettybundle.PrettyBundle;
import java.io.IOException;
import java.util.List;
import javax.annotation.processing.Filer;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.Elements;
/**
* Created by tale on 2/5/15.
*/
public class ExtraInjectorClassBuilder {
private final ExtraClassesGrouped extraClassesGrouped;
public ExtraInjectorClassBuilder(ExtraClassesGrouped extraClassesGrouped) throws IllegalAccessException, NullPointerException {
if (extraClassesGrouped == null) {
throw new NullPointerException("activityExtrasGrouped must not be null");
} else if (extraClassesGrouped.getExtraAnnotatedClassName() == null
|| extraClassesGrouped.getExtraAnnotatedClassName().trim().equals("")) {
throw new IllegalAccessException("ActivityExtrasGrouped.getExtraAnnotatedClassName() must not return null");
}
this.extraClassesGrouped = extraClassesGrouped;
}
public void generateCode(Elements elementUtils, Filer filer) throws IOException {
final String activityQualifiedClassName = extraClassesGrouped.getExtraAnnotatedClassName();
final TypeElement typeElement = elementUtils.getTypeElement(activityQualifiedClassName);
final String activityName = typeElement.getSimpleName().toString();
final MethodSpec injectMethod = buildInjectMethod(elementUtils);
ClassName injector = ClassName.get(Injector.class);
ClassName activity = ClassName.get(extraClassesGrouped.getPackageName(), activityName);
final TypeSpec activityInjectorClass = TypeSpec.classBuilder(activityName + PrettyBundle.INJECTOR_SUFFIX)
.addModifiers(Modifier.PUBLIC)
.addSuperinterface(ParameterizedTypeName.get(injector, activity))
.addMethod(injectMethod).build();
JavaFile javaFile = JavaFile.builder(extraClassesGrouped.getPackageName(), activityInjectorClass)
.build();
javaFile.writeTo(filer);
}
private MethodSpec buildInjectMethod(Elements elementUtils) {
final MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder("inject")
.addAnnotation(Override.class)
.addModifiers(Modifier.PUBLIC)
.addParameter(TypeVariableName.get(extraClassesGrouped.getExtraAnnotatedClassName()), "target")
.addParameter(Androids.bundleClass(), "extras");
addInjectStatement(methodBuilder, "target", elementUtils);
return methodBuilder
.build();
}
private void addInjectStatement(MethodSpec.Builder methodBuilder, String targetName, Elements elementUtils) {
final List<ExtraAnnotatedClass> extraAnnotatedClasses = extraClassesGrouped.getExtraAnnotatedClasses();
if (extraAnnotatedClasses == null || extraAnnotatedClasses.size() == 0) {
return;
}
methodBuilder.beginControlFlow("if(extras == null)")
.addStatement("return")
.endControlFlow();
for (ExtraAnnotatedClass extraAnnotatedClass : extraAnnotatedClasses) {
final ExtraBinder extraBinder = extraAnnotatedClass.getExtraBinder();
methodBuilder
.beginControlFlow("if(extras.containsKey($S))", extraAnnotatedClass.getKey())
.addStatement("$L.setDataTypeClass($L.class)", ExtraBinder.class.getName() + "." + extraBinder.toString(), extraAnnotatedClass.getDataTypeQualifiedClassName())
.addStatement("$L.$L = $L.get(extras, $S)", targetName, extraAnnotatedClass.getKey(), ExtraBinder.class.getName() + "." + extraBinder.toString(), extraAnnotatedClass.getKey())
.endControlFlow();
}
}
}