com.kyle.component.kdb.annotation.compiler.ORMAnnotationProcessor Maven / Gradle / Ivy
package com.kyle.component.kdb.annotation.compiler;
import com.google.auto.service.AutoService;
import com.kyle.component.kdb.annotation.Column;
import com.kyle.component.kdb.annotation.ORMAnnotation;
import com.kyle.component.kdb.condition.ORMMapper;
import com.kyle.component.kdb.condition.ValueSet;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Filer;
import javax.annotation.processing.Messager;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
import javax.tools.Diagnostic;
@AutoService(Processor.class)
public class ORMAnnotationProcessor extends AbstractProcessor {
private Filer filer;
private Messager mMessager;
private Elements elementUtils;
private Map> annotationMap = new HashMap<>();
@Override
public synchronized void init(ProcessingEnvironment processingEnvironment) {
super.init(processingEnvironment);
mMessager = processingEnv.getMessager();
filer = processingEnv.getFiler();
elementUtils = processingEnv.getElementUtils();
}
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latestSupported();
}
@Override
public Set getSupportedAnnotationTypes() {
Set annotations = new LinkedHashSet<>();
annotations.add(ORMAnnotation.class.getCanonicalName());
annotations.add(Column.class.getCanonicalName());
return annotations;
}
private void error(Element e, String msg, Object... args) {
mMessager.printMessage(Diagnostic.Kind.ERROR, String.format(msg, args), e);
}
private void analysisAnnotated() {
for (String key : annotationMap.keySet()) {
List fields = annotationMap.get(key);
if (!fields.isEmpty()) {
builderMapperClass(key, fields);
builderValueClass(key, fields);
}
}
}
public void builderMapperClass(String clsName, List fields) {
String newClsName = clsName.substring(clsName.lastIndexOf(".") + 1) + "Mapper";
String pkgName = clsName.substring(0, clsName.lastIndexOf(".") + 1) + "mapper";
TypeSpec.Builder typeCls = TypeSpec.classBuilder(newClsName).addModifiers(Modifier.PUBLIC).superclass(ORMMapper.class);
List allMethods = new ArrayList<>();
ClassName staticName = ClassName.get(pkgName, newClsName);
allMethods.add(MapperFieldBuilder.builderCreateMethod(staticName));
allMethods.addAll(MapperFieldBuilder.builderPrimaryKeyMethod(staticName));
for (AnnotationField annotationField : fields) {
allMethods.addAll(MapperFieldBuilder.builderMethod(staticName, annotationField));
}
allMethods.add(MapperFieldBuilder.builderLimitMethod(staticName));
writeJavaFile(typeCls, pkgName, allMethods);
}
public void builderValueClass(String clsName, List fields) {
String newClsName = clsName.substring(clsName.lastIndexOf(".") + 1) + "ValueSet";
String pkgName = clsName.substring(0, clsName.lastIndexOf(".") + 1) + "value.set";
TypeSpec.Builder typeCls = TypeSpec.classBuilder(newClsName).addModifiers(Modifier.PUBLIC).superclass(ValueSet.class);
List allMethods = new ArrayList<>();
ClassName staticName = ClassName.get(pkgName, newClsName);
allMethods.add(com.kyle.component.kdb.annotation.compiler.ValueSetFieldBuilder.builderCreateMethod(staticName));
for (AnnotationField annotationField : fields) {
allMethods.addAll(ValueSetFieldBuilder.builderMethod(staticName, annotationField));
}
writeJavaFile(typeCls, pkgName, allMethods);
}
private void writeJavaFile(TypeSpec.Builder builder, String pkgName, List methodSpecs) {
try {
builder.addMethods(methodSpecs);
JavaFile javaFile = JavaFile.builder(pkgName, builder.build())
.addFileComment(" This codes are generated automatically. Do not modify!")
.build();
javaFile.writeTo(filer);
} catch (IOException e) {
e.printStackTrace();
}
}
private void annotationField(Element element) {
TypeElement classElement = (TypeElement) element.getEnclosingElement();
PackageElement packageElement = elementUtils.getPackageOf(classElement);
String clsName = classElement.getSimpleName().toString();
String pkgName = packageElement.getQualifiedName().toString();
String key = pkgName + "." + clsName;
List fields = annotationMap.get(key);
if (fields == null)
return;
TypeMirror typeMirror = element.asType();
String fieldName = element.getAnnotation(Column.class).name();
fieldName = (fieldName == null || fieldName.isEmpty()) ? element.getSimpleName().toString() : fieldName;
fields.add(new AnnotationField(fieldName.isEmpty() ? element.getSimpleName().toString() : fieldName, TypeName.get(typeMirror)));
}
@Override
public boolean process(Set extends TypeElement> set, RoundEnvironment roundEnvironment) {
annotationMap.clear();
for (Element annotatedElement : roundEnvironment.getElementsAnnotatedWith(ORMAnnotation.class)) {
if (annotatedElement.getKind() == ElementKind.CLASS) {
PackageElement packageElement = (PackageElement) annotatedElement.getEnclosingElement();
String key = packageElement.getQualifiedName().toString() + "." + annotatedElement.getSimpleName().toString();
annotationMap.put(key, new ArrayList());
}
}
if (annotationMap.isEmpty())
return false;
for (Element annotatedElement : roundEnvironment.getElementsAnnotatedWith(Column.class)) {
if (annotatedElement.getKind() == ElementKind.FIELD) {
annotationField(annotatedElement);
}
}
analysisAnnotated();
return false;
}
}