package io.trygvis.container.compiler; import io.trygvis.container.compiler.model.ClassG; import io.trygvis.container.compiler.model.Parameters; import io.trygvis.persistence.EntityMirror; import io.trygvis.persistence.FieldMirror; import io.trygvis.persistence.GeneratorSupport; import io.trygvis.persistence.SqlEntity; import io.trygvis.persistence.TypeHandler; import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.AnnotationValue; import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; import javax.lang.model.element.VariableElement; import javax.lang.model.type.TypeMirror; import javax.tools.JavaFileObject; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; import static io.trygvis.persistence.FieldMirror.PrimitiveFieldMirror; import static java.lang.Character.isUpperCase; import static javax.lang.model.util.ElementFilter.fieldsIn; public class EntityHandler extends AbstractHandler { GeneratorSupport generatorSupport = new GeneratorSupport(); public EntityHandler(ProcessingEnvironment processingEnv) { super(processingEnv); } public void phase1(Set sqlEntities) throws Exception { System.out.println("io.trygvis.container.compiler.EntityHandler.phase1"); for (Element entity : sqlEntities) { // SqlEntity sqlEntity = entity.getAnnotation(SqlEntity.class); // Class typeHandlerClass = sqlEntity.value(); AnnotationMirror sqlEntity = findAnnotation(SqlEntity.class, entity.getAnnotationMirrors()); for (Map.Entry v : sqlEntity.getElementValues().entrySet()) { switch (v.getKey().getSimpleName().toString()) { case "value": Class typeHandlerClass = getClass().getClassLoader().loadClass(v.getValue().getValue().toString()); TypeHandler typeHandler = (TypeHandler) typeHandlerClass.newInstance(); String type = entity.asType().toString(); generatorSupport.addTypeHandler(type, typeHandler); System.out.println("Loaded TypeHandler for " + type + " through " + typeHandlerClass.getCanonicalName()); break; } } System.out.println("sqlEntity.getElementValues() = " + sqlEntity.getElementValues()); } } private AnnotationMirror findAnnotation(Class c, List annotations) { TypeElement t = elements.getTypeElement(c.getCanonicalName()); for (AnnotationMirror a : annotations) { if (types.isSameType(a.getAnnotationType(), t.asType())) { return a; } } throw new RuntimeException("Could not find annotation " + c.getSimpleName()); } public void processEntity(TypeElement element) throws Exception { EntityMirror entityMirror = new EntityMirror(generatorSupport, element.asType(), sqlName(element.getSimpleName().toString())); for (VariableElement f : fieldsIn(elements.getAllMembers(element))) { entityMirror.add(fromElement(generatorSupport, f)); } String p = elements.getPackageOf(element).getQualifiedName().toString(); String className = element.getSimpleName() + "_Sql"; ClassG g = new ClassG(p, className, null); g.addPublicFinalField(String.class, "insertIntoSql"); String insertInto = entityMirror.insertIntoSql(); List body = new ArrayList<>(); body.add("this.insertIntoSql = \"" + insertInto + "\";"); g.addConstructor(new Parameters(), body); entityMirror.insertInto(g); String fileName = (p.length() == 0 ? "" : p + ".") + className; JavaFileObject sourceFile = processingEnv.getFiler().createSourceFile(fileName, element); try (PrintWriter w = new PrintWriter(sourceFile.openWriter())) { g.write(w); } } public FieldMirror fromElement(GeneratorSupport generatorSupport, VariableElement var) { System.out.print("element = "); TypeMirror type = var.asType(); elements.printElements(new PrintWriter(System.out), var); String javaName = var.getSimpleName().toString(); String sqlName = sqlName(javaName); boolean notNull = false; FieldMirror field; if (generatorSupport.isPrimitive(type)) { field = new PrimitiveFieldMirror(var, javaName, sqlName, notNull); } else if (generatorSupport.hasTypeHandler(type)) { field = new FieldMirror.ReferenceFieldMirror(var, javaName, sqlName, notNull); } else { throw new RuntimeException("Missing type handler for type: " + type); } System.out.println("field = " + field); return field; } public static String sqlName(String javaName) { StringBuilder builder = new StringBuilder(); for (char c : javaName.toCharArray()) { char lower = Character.toLowerCase(c); if (isUpperCase(c) && builder.length() > 0) { builder.append("_"); } builder.append(lower); } return builder.toString(); } }