summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTrygve Laugstøl <trygvis@inamo.no>2013-08-03 12:33:39 +0200
committerTrygve Laugstøl <trygvis@inamo.no>2013-08-03 12:33:39 +0200
commit34137b599dbea13c94224dff2955376b1394dbc9 (patch)
tree889b4c334014965e451f8d9b308b952a13b4d8d5
parent4e794b5ed03e5020770becb068d11e6838feec64 (diff)
downloadcontainer-playground-34137b599dbea13c94224dff2955376b1394dbc9.tar.gz
container-playground-34137b599dbea13c94224dff2955376b1394dbc9.tar.bz2
container-playground-34137b599dbea13c94224dff2955376b1394dbc9.tar.xz
container-playground-34137b599dbea13c94224dff2955376b1394dbc9.zip
wip
-rw-r--r--container-compiler-plugin/pom.xml5
-rw-r--r--container-compiler-plugin/src/main/java/io/trygvis/container/compiler/EntityHandler.java89
-rw-r--r--container-compiler-plugin/src/main/java/io/trygvis/container/compiler/MyProcessor.java53
-rw-r--r--container-compiler-plugin/src/main/java/io/trygvis/container/compiler/entity/EntityMirror.java38
-rw-r--r--container-compiler-plugin/src/main/java/io/trygvis/container/compiler/model/ClassG.java27
-rw-r--r--container-compiler-plugin/src/main/java/io/trygvis/container/compiler/model/MethodRef.java13
-rw-r--r--container-compiler-plugin/src/main/java/io/trygvis/persistence/EntityMirror.java65
-rw-r--r--container-compiler-plugin/src/main/java/io/trygvis/persistence/FieldMirror.java63
-rw-r--r--container-compiler-plugin/src/main/java/io/trygvis/persistence/GeneratorSupport.java41
-rw-r--r--container-compiler-plugin/src/main/java/io/trygvis/persistence/SqlEntity.java17
-rw-r--r--container-compiler-plugin/src/main/java/io/trygvis/persistence/TypeHandler.java26
-rw-r--r--container-compiler-plugin/src/test/java/io/trygvis/container/compiler/EntityHandlerTest.java1
-rw-r--r--container-compiler-plugin/src/test/java/io/trygvis/container/compiler/JavaSourceFromString.java32
-rw-r--r--container-compiler-plugin/src/test/java/io/trygvis/container/compiler/ProcessorTest.java35
-rw-r--r--container-compiler-plugin/src/test/java/io/trygvis/persistence/test/PersonTypeHandler.java11
-rw-r--r--container-compiler-plugin/src/test/resources/Person.java23
-rw-r--r--persistence-compile-time/pom.xml19
-rw-r--r--pom.xml1
18 files changed, 420 insertions, 139 deletions
diff --git a/container-compiler-plugin/pom.xml b/container-compiler-plugin/pom.xml
index f48d8fc..2e9fff9 100644
--- a/container-compiler-plugin/pom.xml
+++ b/container-compiler-plugin/pom.xml
@@ -16,6 +16,11 @@
<version>${project.version}</version>
</dependency>
<dependency>
+ <groupId>io.trygvis.container</groupId>
+ <artifactId>persistence-compile-time</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
<groupId>org.easytesting</groupId>
<artifactId>fest-assert</artifactId>
<version>1.4</version>
diff --git a/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/EntityHandler.java b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/EntityHandler.java
index df7a673..f9247e0 100644
--- a/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/EntityHandler.java
+++ b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/EntityHandler.java
@@ -1,43 +1,90 @@
package io.trygvis.container.compiler;
-import io.trygvis.container.compiler.entity.EntityMirror;
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.container.compiler.entity.EntityMirror.FieldMirror;
+import static io.trygvis.persistence.FieldMirror.PrimitiveFieldMirror;
import static java.lang.Character.isUpperCase;
import static javax.lang.model.util.ElementFilter.fieldsIn;
-import static org.springframework.util.StringUtils.collectionToDelimitedString;
public class EntityHandler extends AbstractHandler {
+ GeneratorSupport generatorSupport = new GeneratorSupport();
+
public EntityHandler(ProcessingEnvironment processingEnv) {
super(processingEnv);
}
+ public void phase1(Set<? extends Element> sqlEntities) throws Exception {
+ System.out.println("io.trygvis.container.compiler.EntityHandler.phase1");
+ for (Element entity : sqlEntities) {
+// SqlEntity sqlEntity = entity.getAnnotation(SqlEntity.class);
+// Class<? extends TypeHandler> typeHandlerClass = sqlEntity.value();
+
+ AnnotationMirror sqlEntity = findAnnotation(SqlEntity.class, entity.getAnnotationMirrors());
+ for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> 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<? extends AnnotationMirror> 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(sqlName(element.getSimpleName().toString()));
+ EntityMirror entityMirror = new EntityMirror(generatorSupport, element.asType(), sqlName(element.getSimpleName().toString()));
for (VariableElement f : fieldsIn(elements.getAllMembers(element))) {
- entityMirror.add(fromElement(f));
+ 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, "insertInto");
- String insertInto = insertInto(entityMirror);
+ g.addPublicFinalField(String.class, "insertIntoSql");
+ String insertInto = entityMirror.insertIntoSql();
List<String> body = new ArrayList<>();
- body.add("this.insertInto = \"" + insertInto + "\";");
+ 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);
@@ -46,25 +93,21 @@ public class EntityHandler extends AbstractHandler {
}
}
- public static String insertInto(EntityMirror entityMirror) {
- List<String> names = new ArrayList<>();
- List<String> placeholders = new ArrayList<>();
- for (FieldMirror field : entityMirror.fields) {
- names.add(field.sqlName);
- placeholders.add("?");
- }
- return "INSERT INTO " + entityMirror.tableName + "(" + collectionToDelimitedString(names, ", ") + ") " +
- "VALUES(" + collectionToDelimitedString(placeholders, ", ") + ");";
- }
-
- public FieldMirror fromElement(VariableElement var) {
- System.out.println("io.trygvis.container.compiler.entity.EntityMirror.FieldMirror.fromElement");
+ 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 = new FieldMirror(javaName, sqlName, notNull);
+ 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;
}
@@ -73,7 +116,7 @@ public class EntityHandler extends AbstractHandler {
StringBuilder builder = new StringBuilder();
for (char c : javaName.toCharArray()) {
char lower = Character.toLowerCase(c);
- if(isUpperCase(c) && builder.length() > 0) {
+ if (isUpperCase(c) && builder.length() > 0) {
builder.append("_");
}
builder.append(lower);
diff --git a/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/MyProcessor.java b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/MyProcessor.java
index 6843659..735d688 100644
--- a/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/MyProcessor.java
+++ b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/MyProcessor.java
@@ -1,6 +1,7 @@
package io.trygvis.container.compiler;
import io.trygvis.container.log.Log;
+import io.trygvis.persistence.SqlEntity;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.processing.Completion;
@@ -31,19 +32,16 @@ public class MyProcessor implements Processor {
@Override
public Set<String> getSupportedOptions() {
- System.out.println("io.trygvis.container.compiler.MyProcessor.getSupportedOptions");
return emptySet();
}
@Override
public SourceVersion getSupportedSourceVersion() {
- System.out.println("io.trygvis.container.compiler.MyProcessor.getSupportedSourceVersion");
return SourceVersion.RELEASE_7;
}
@Override
public void init(ProcessingEnvironment processingEnv) {
- System.out.println("io.trygvis.container.compiler.MyProcessor.init");
this.processingEnv = processingEnv;
elements = processingEnv.getElementUtils();
types = processingEnv.getTypeUtils();
@@ -51,13 +49,11 @@ public class MyProcessor implements Processor {
@Override
public Iterable<? extends Completion> getCompletions(Element element, AnnotationMirror annotation, ExecutableElement member, String userText) {
- System.out.println("io.trygvis.container.compiler.MyProcessor.getCompletions");
return emptyList();
}
@Override
public Set<String> getSupportedAnnotationTypes() {
- System.out.println("io.trygvis.container.compiler.MyProcessor.getSupportedAnnotationTypes");
return new HashSet<>(asList(
Transactional.class.getName(),
Log.class.getName(),
@@ -66,34 +62,39 @@ public class MyProcessor implements Processor {
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
- System.out.println("io.trygvis.container.compiler.MyProcessor.process");
- System.out.println("annotations = " + annotations);
-// Set<? extends Element> transactional = roundEnv.getElementsAnnotatedWith(Transactional.class);
+ try {
+ return work(annotations, roundEnv);
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ public boolean work(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) throws Exception {
TypeElement tx = elements.getTypeElement(Transactional.class.getCanonicalName());
TypeElement log = elements.getTypeElement(Log.class.getCanonicalName());
TypeElement entity = elements.getTypeElement(Entity.class.getCanonicalName());
+ EntityHandler entityHandler = new EntityHandler(processingEnv);
+
+ Set<? extends Element> sqlEntities = roundEnv.getElementsAnnotatedWith(SqlEntity.class);
+ entityHandler.phase1(sqlEntities);
+
for (Element element : roundEnv.getRootElements()) {
- try {
- System.out.println("Processing: " + element);
- for (AnnotationMirror annotationMirror : element.getAnnotationMirrors()) {
- DeclaredType annotationType = annotationMirror.getAnnotationType();
-
- if (types.isSameType(tx.asType(), annotationType)) {
- new TransactionalHandler(processingEnv).processTransactional((TypeElement) element);
- }
- if (types.isSameType(log.asType(), annotationType)) {
- new LogHandler(processingEnv).processLog((TypeElement) element);
- }
- if (types.isSameType(entity.asType(), annotationType)) {
- new EntityHandler(processingEnv).processEntity((TypeElement) element);
- }
+ System.out.println("Processing: " + element);
+ for (AnnotationMirror annotationMirror : element.getAnnotationMirrors()) {
+ DeclaredType annotationType = annotationMirror.getAnnotationType();
+
+ if (types.isSameType(tx.asType(), annotationType)) {
+ new TransactionalHandler(processingEnv).processTransactional((TypeElement) element);
+ }
+ if (types.isSameType(log.asType(), annotationType)) {
+ new LogHandler(processingEnv).processLog((TypeElement) element);
+ }
+ if (types.isSameType(entity.asType(), annotationType)) {
+ entityHandler.processEntity((TypeElement) element);
}
- } catch (RuntimeException e) {
- throw e;
- } catch (Exception e) {
- throw new RuntimeException(e);
}
}
return true;
diff --git a/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/entity/EntityMirror.java b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/entity/EntityMirror.java
deleted file mode 100644
index ae7077c..0000000
--- a/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/entity/EntityMirror.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package io.trygvis.container.compiler.entity;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class EntityMirror {
- public final List<FieldMirror> fields = new ArrayList<>();
- public final String tableName;
-
- public EntityMirror(String tableName) {
- this.tableName = tableName;
- }
-
- public void add(FieldMirror field) {
- fields.add(field);
- }
-
- public static class FieldMirror {
- private final String javaName;
- public final String sqlName;
- private final boolean notNull;
-
- public FieldMirror(String javaName, String sqlName, boolean notNull) {
- this.javaName = javaName;
- this.sqlName = sqlName;
- this.notNull = notNull;
- }
-
- @Override
- public String toString() {
- return "FieldMirror{" +
- "javaName='" + javaName + '\'' +
- ", sqlName='" + sqlName + '\'' +
- ", notNull=" + notNull +
- '}';
- }
- }
-}
diff --git a/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/model/ClassG.java b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/model/ClassG.java
index cf68cba..8ff91a0 100644
--- a/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/model/ClassG.java
+++ b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/model/ClassG.java
@@ -31,7 +31,6 @@ public class ClassG {
}
String canonicalName = type.toString();
- System.out.println("canonicalName = " + canonicalName);
for (TypeRef i : imports) {
if (i.canonicalName().equals(canonicalName)) {
@@ -45,10 +44,6 @@ public class ClassG {
}
public TypeRef addImport(Class<?> klass) {
-// if (klass.isPrimitive()) {
-// return TypeRef.PRIMITIVE;
-// }
-
String canonicalName = klass.getCanonicalName();
String simpleName = klass.getSimpleName();
String name = simpleName;
@@ -104,6 +99,9 @@ public class ClassG {
if (i.isPrimitive()) {
continue;
}
+ if(i.canonicalName().indexOf('.') == -1) {
+ continue;
+ }
writer.println("import " + i.canonicalName() + ";");
}
writer.println();
@@ -144,7 +142,24 @@ public class ClassG {
parameters.add("final " + p.klass.name + " " + p.name);
}
- writer.println(" public " + returnString + " " + method.name + "(" + collectionToDelimitedString(parameters, ", ") + ") {");
+ writer.print(" public " + returnString + " " + method.name + "(" + collectionToDelimitedString(parameters, ", ") + ")");
+ if(method.exceptions.isEmpty()) {
+ writer.println(" {");
+ }
+ else {
+ writer.println(" throws");
+ ArrayList<TypeRef> typeRefs = new ArrayList<>(method.exceptions);
+ for (int i = 0; i < typeRefs.size(); i++) {
+ TypeRef e = typeRefs.get(i);
+ writer.print(" " + e.name);
+ if(i < typeRefs.size() - 1) {
+ writer.println(",");
+ }
+ else {
+ writer.println(" {");
+ }
+ }
+ }
for (String s : method.body) {
writer.print(" ");
writer.println(s);
diff --git a/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/model/MethodRef.java b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/model/MethodRef.java
index 36f61e8..a59e9a6 100644
--- a/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/model/MethodRef.java
+++ b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/model/MethodRef.java
@@ -1,18 +1,27 @@
package io.trygvis.container.compiler.model;
import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+import static java.util.Collections.addAll;
public class MethodRef {
public final TypeRef returnType;
public final String name;
public final ParameterRef[] parameters;
+ public final Set<TypeRef> exceptions = new TreeSet<>();
public final List<String> body;
- public
- MethodRef(TypeRef returnType, String name, ParameterRef[] parameters, List<String> body) {
+ public MethodRef(TypeRef returnType, String name, ParameterRef[] parameters, List<String> body) {
this.returnType = returnType;
this.name = name;
this.parameters = parameters;
this.body = body;
}
+
+ public MethodRef exception(TypeRef... exceptions) {
+ addAll(this.exceptions, exceptions);
+ return this;
+ }
}
diff --git a/container-compiler-plugin/src/main/java/io/trygvis/persistence/EntityMirror.java b/container-compiler-plugin/src/main/java/io/trygvis/persistence/EntityMirror.java
new file mode 100644
index 0000000..fe50e17
--- /dev/null
+++ b/container-compiler-plugin/src/main/java/io/trygvis/persistence/EntityMirror.java
@@ -0,0 +1,65 @@
+package io.trygvis.persistence;
+
+import io.trygvis.container.compiler.model.ClassG;
+import io.trygvis.container.compiler.model.ParameterRef;
+import io.trygvis.container.compiler.model.TypeRef;
+
+import javax.lang.model.type.TypeMirror;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.apache.commons.lang.StringUtils.join;
+
+public class EntityMirror {
+ public final GeneratorSupport generatorSupport;
+ public final List<FieldMirror> fields = new ArrayList<>();
+ public final TypeMirror javaName;
+ public final String tableName;
+
+ public EntityMirror(GeneratorSupport generatorSupport, TypeMirror javaName, String tableName) {
+ this.generatorSupport = generatorSupport;
+ this.javaName = javaName;
+ this.tableName = tableName;
+ }
+
+ public void add(FieldMirror field) {
+ fields.add(field);
+ }
+
+ public String insertIntoSql() {
+ List<String> names = new ArrayList<>();
+ List<String> placeholders = new ArrayList<>();
+ for (FieldMirror field : fields) {
+ names.add(field.sqlName);
+ placeholders.add("?");
+ }
+
+ return "INSERT INTO " + tableName + "(" + join(names, ", ") + ") " +
+ "VALUES(" + join(placeholders, ", ") + ");";
+ }
+
+ public void insertInto(ClassG g) {
+ TypeRef conType = g.addImport(Connection.class);
+ TypeRef psType = g.addImport(PreparedStatement.class);
+ TypeRef objectType = g.addImport(javaName);
+ ParameterRef con = new ParameterRef(conType, "con");
+ ParameterRef object = new ParameterRef(objectType, "o");
+
+ List<String> body = new ArrayList<>();
+
+ body.add("try(" + psType.name + " stmt = " + con.name + ".prepareStatement(insertIntoSql)) {");
+ for (int i = 0; i < fields.size(); i++) {
+ FieldMirror field = fields.get(i);
+ TypeHandler typeHandler = generatorSupport.typeHandler(field.element);
+ body.add(" stmt." + typeHandler.resultSetSetter(i + 1, "o", field) + ";");
+ }
+ body.add(" stmt.executeUpdate();");
+ body.add("}");
+
+ g.addMethod(body, TypeRef.VOID, "insertInto", con, object).
+ exception(g.addImport(SQLException.class));
+ }
+}
diff --git a/container-compiler-plugin/src/main/java/io/trygvis/persistence/FieldMirror.java b/container-compiler-plugin/src/main/java/io/trygvis/persistence/FieldMirror.java
new file mode 100644
index 0000000..e14fb9f
--- /dev/null
+++ b/container-compiler-plugin/src/main/java/io/trygvis/persistence/FieldMirror.java
@@ -0,0 +1,63 @@
+package io.trygvis.persistence;
+
+import javax.lang.model.element.VariableElement;
+
+import static io.trygvis.persistence.FieldMirror.FieldType.PRIMITIVE;
+import static io.trygvis.persistence.FieldMirror.FieldType.REFERENCE;
+
+/**
+ * TODO: a single field might have to be mapped to multiple sql columns.
+ */
+public abstract class FieldMirror {
+ public final FieldType fieldType;
+ public final VariableElement element;
+ public final String javaName;
+ public final String sqlName;
+ public final boolean notNull;
+
+ public enum FieldType {
+ PRIMITIVE,
+ REFERENCE,
+ }
+
+ protected FieldMirror(FieldType fieldType, VariableElement element, String javaName, String sqlName, boolean notNull) {
+ this.fieldType = fieldType;
+ this.element = element;
+ this.javaName = javaName;
+ this.sqlName = sqlName;
+ this.notNull = notNull;
+ }
+
+ public static class PrimitiveFieldMirror extends FieldMirror {
+ public PrimitiveFieldMirror(VariableElement element, String javaName, String sqlName, boolean notNull) {
+ super(PRIMITIVE, element, javaName, sqlName, notNull);
+ }
+
+ @Override
+ public String toString() {
+ return "PrimitiveFieldMirror{" +
+ "javaName='" + javaName + '\'' +
+ ", sqlName='" + sqlName + '\'' +
+ ", notNull=" + notNull +
+ '}';
+ }
+ }
+
+ public static class ReferenceFieldMirror extends FieldMirror {
+ public ReferenceFieldMirror(VariableElement element, String javaName, String sqlName, boolean notNull) {
+ super(REFERENCE, element, javaName, sqlName, notNull);
+ }
+
+ @Override
+ public String toString() {
+ return "ReferenceFieldMirror{" +
+ "javaName='" + javaName + '\'' +
+ ", sqlName='" + sqlName + '\'' +
+ ", notNull=" + notNull +
+ '}';
+ }
+ }
+
+ @Override
+ public abstract String toString();
+}
diff --git a/container-compiler-plugin/src/main/java/io/trygvis/persistence/GeneratorSupport.java b/container-compiler-plugin/src/main/java/io/trygvis/persistence/GeneratorSupport.java
new file mode 100644
index 0000000..7ac30d9
--- /dev/null
+++ b/container-compiler-plugin/src/main/java/io/trygvis/persistence/GeneratorSupport.java
@@ -0,0 +1,41 @@
+package io.trygvis.persistence;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.TypeMirror;
+import java.util.HashMap;
+import java.util.Map;
+
+public class GeneratorSupport {
+
+ private final Map<String, TypeHandler> primitiveTypeHandlers = new HashMap<>();
+ private final Map<String, TypeHandler> typeHandlers = new HashMap<>();
+
+ {
+ typeHandlers.put("java.lang.Integer", new TypeHandler.IntTypeHandler());
+ typeHandlers.put("java.lang.Long", new TypeHandler.LongTypeHandler());
+ typeHandlers.put("java.util.Date", new TypeHandler.DateTypeHandler());
+
+ primitiveTypeHandlers.putAll(typeHandlers);
+ }
+
+ public void addTypeHandler(String type, TypeHandler typeHandler) {
+ typeHandlers.put(type, typeHandler);
+ }
+
+ public TypeHandler typeHandler(Element element) {
+ String type = element.asType().toString();
+ TypeHandler typeHandler = typeHandlers.get(type);
+ if (typeHandler == null)
+ throw new RuntimeException("Unsupported field type: " + type);
+ return typeHandler;
+ }
+
+ public boolean isPrimitive(TypeMirror type) {
+ return primitiveTypeHandlers.containsKey(type.toString());
+ }
+
+ public boolean hasTypeHandler(TypeMirror type) {
+ return typeHandlers.containsKey(type.toString());
+ }
+}
diff --git a/container-compiler-plugin/src/main/java/io/trygvis/persistence/SqlEntity.java b/container-compiler-plugin/src/main/java/io/trygvis/persistence/SqlEntity.java
new file mode 100644
index 0000000..e298eee
--- /dev/null
+++ b/container-compiler-plugin/src/main/java/io/trygvis/persistence/SqlEntity.java
@@ -0,0 +1,17 @@
+package io.trygvis.persistence;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.CLASS)
+@Target(ElementType.TYPE)
+public @interface SqlEntity {
+ /**
+ * The name of a class that implements {@link io.trygvis.persistence.TypeHandler}.
+ *
+ * The class needs to be available at compile time, but not runtime.
+ */
+ String value();
+}
diff --git a/container-compiler-plugin/src/main/java/io/trygvis/persistence/TypeHandler.java b/container-compiler-plugin/src/main/java/io/trygvis/persistence/TypeHandler.java
new file mode 100644
index 0000000..252f4b4
--- /dev/null
+++ b/container-compiler-plugin/src/main/java/io/trygvis/persistence/TypeHandler.java
@@ -0,0 +1,26 @@
+package io.trygvis.persistence;
+
+public interface TypeHandler {
+ String resultSetSetter(int i, String o, FieldMirror field);
+
+ public static class IntTypeHandler implements TypeHandler {
+ @Override
+ public String resultSetSetter(int i, String o, FieldMirror field) {
+ return "setInt(" + i + ", " + o + "." + field.javaName + ")";
+ }
+ }
+
+ public static class LongTypeHandler implements TypeHandler {
+ @Override
+ public String resultSetSetter(int i, String o, FieldMirror field) {
+ return "setLong(" + i + ", " + o + "." + field.javaName + ")";
+ }
+ }
+
+ public static class DateTypeHandler implements TypeHandler {
+ @Override
+ public String resultSetSetter(int i, String o, FieldMirror field) {
+ return "setTimestamp(" + i + ", new java.sql.Timestamp(" + o + "." + field.javaName + ".getTime()))";
+ }
+ }
+}
diff --git a/container-compiler-plugin/src/test/java/io/trygvis/container/compiler/EntityHandlerTest.java b/container-compiler-plugin/src/test/java/io/trygvis/container/compiler/EntityHandlerTest.java
index 98fcaea..e24a362 100644
--- a/container-compiler-plugin/src/test/java/io/trygvis/container/compiler/EntityHandlerTest.java
+++ b/container-compiler-plugin/src/test/java/io/trygvis/container/compiler/EntityHandlerTest.java
@@ -15,6 +15,7 @@ public class EntityHandlerTest {
new Object[]{"MyClass", "my_class"},
new Object[]{"myField", "my_field"},
new Object[]{"name", "name"},
+ new Object[]{"_first_name", "_first_name"},
new Object[]{"first_name", "first_name"},
new Object[]{"first_name_", "first_name_"},
};
diff --git a/container-compiler-plugin/src/test/java/io/trygvis/container/compiler/JavaSourceFromString.java b/container-compiler-plugin/src/test/java/io/trygvis/container/compiler/JavaSourceFromString.java
new file mode 100644
index 0000000..e07a11f
--- /dev/null
+++ b/container-compiler-plugin/src/test/java/io/trygvis/container/compiler/JavaSourceFromString.java
@@ -0,0 +1,32 @@
+package io.trygvis.container.compiler;
+
+import javax.tools.JavaFileObject;
+import javax.tools.SimpleJavaFileObject;
+import java.net.URI;
+
+/**
+ * A file object used to represent source coming from a string.
+ */
+public class JavaSourceFromString extends SimpleJavaFileObject {
+ /**
+ * The source code of this "file".
+ */
+ final String code;
+
+ /**
+ * Constructs a new JavaSourceFromString.
+ *
+ * @param name the name of the compilation unit represented by this file object
+ * @param code the source code for the compilation unit represented by this file object
+ */
+ JavaSourceFromString(String name, String code) {
+ super(URI.create("string:///" + name.replace('.', '/') + Kind.SOURCE.extension),
+ Kind.SOURCE);
+ this.code = code;
+ }
+
+ @Override
+ public CharSequence getCharContent(boolean ignoreEncodingErrors) {
+ return code;
+ }
+}
diff --git a/container-compiler-plugin/src/test/java/io/trygvis/container/compiler/ProcessorTest.java b/container-compiler-plugin/src/test/java/io/trygvis/container/compiler/ProcessorTest.java
index e070f3c..2205d52 100644
--- a/container-compiler-plugin/src/test/java/io/trygvis/container/compiler/ProcessorTest.java
+++ b/container-compiler-plugin/src/test/java/io/trygvis/container/compiler/ProcessorTest.java
@@ -7,10 +7,8 @@ import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
-import javax.tools.SimpleJavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
-import java.net.URI;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Locale;
@@ -21,33 +19,6 @@ import static org.fest.assertions.Assertions.assertThat;
public class ProcessorTest {
Charset UTF_8 = Charset.forName("utf-8");
- /**
- * A file object used to represent source coming from a string.
- */
- public class JavaSourceFromString extends SimpleJavaFileObject {
- /**
- * The source code of this "file".
- */
- final String code;
-
- /**
- * Constructs a new JavaSourceFromString.
- *
- * @param name the name of the compilation unit represented by this file object
- * @param code the source code for the compilation unit represented by this file object
- */
- JavaSourceFromString(String name, String code) {
- super(URI.create("string:///" + name.replace('.', '/') + JavaFileObject.Kind.SOURCE.extension),
- JavaFileObject.Kind.SOURCE);
- this.code = code;
- }
-
- @Override
- public CharSequence getCharContent(boolean ignoreEncodingErrors) {
- return code;
- }
- }
-
@Test
public void testBasic() throws Exception {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
@@ -66,6 +37,9 @@ public class ProcessorTest {
Boolean result = task.call();
+ assertThat(fileManager.codes.keySet()).containsOnly("Person_Sql");
+ System.out.println(fileManager.codes.get("Person_Sql"));
+
for (Diagnostic<? extends JavaFileObject> diagnostic : collector.getDiagnostics()) {
// System.out.println("diagnostic = " + diagnostic);
System.out.println("diagnostic.source = ->" + diagnostic.getSource().getName() + "<-");
@@ -76,8 +50,5 @@ public class ProcessorTest {
assertThat(result).isTrue();
fileManager.close();
-
- assertThat(fileManager.codes.keySet()).containsOnly("Person_Sql");
- System.out.println(fileManager.codes.get("Person_Sql"));
}
}
diff --git a/container-compiler-plugin/src/test/java/io/trygvis/persistence/test/PersonTypeHandler.java b/container-compiler-plugin/src/test/java/io/trygvis/persistence/test/PersonTypeHandler.java
new file mode 100644
index 0000000..68e17c3
--- /dev/null
+++ b/container-compiler-plugin/src/test/java/io/trygvis/persistence/test/PersonTypeHandler.java
@@ -0,0 +1,11 @@
+package io.trygvis.persistence.test;
+
+import io.trygvis.persistence.FieldMirror;
+import io.trygvis.persistence.TypeHandler;
+
+public class PersonTypeHandler implements TypeHandler {
+ @Override
+ public String resultSetSetter(int i, String o, FieldMirror field) {
+ return "setLong(" + i + ", o." + field.javaName + ".id)";
+ }
+}
diff --git a/container-compiler-plugin/src/test/resources/Person.java b/container-compiler-plugin/src/test/resources/Person.java
index 740b42d..4bdb882 100644
--- a/container-compiler-plugin/src/test/resources/Person.java
+++ b/container-compiler-plugin/src/test/resources/Person.java
@@ -1,26 +1,25 @@
+import io.trygvis.persistence.SqlEntity;
+
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
-import javax.persistence.OneToMany;
-import javax.persistence.OrderBy;
-import java.util.ArrayList;
import java.util.Date;
-import java.util.List;
@Entity
+@SqlEntity("io.trygvis.persistence.test.PersonTypeHandler")
public class Person {
@Id
- private Long id;
+ public Long id;
- private Date birthDate;
+ public Date birthDate;
@ManyToOne
- private Person mother;
+ public Person mother;
- @ManyToOne
- private Person father;
+// @ManyToOne
+// public Person father;
- @OneToMany(mappedBy = "id")
- @OrderBy("birthDate asc")
- private List<Person> children = new ArrayList<>();
+// @OneToMany(mappedBy = "id")
+// @OrderBy("birthDate asc")
+// private List<Person> children = new ArrayList<>();
}
diff --git a/persistence-compile-time/pom.xml b/persistence-compile-time/pom.xml
new file mode 100644
index 0000000..90f5b8a
--- /dev/null
+++ b/persistence-compile-time/pom.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>container-playground</artifactId>
+ <groupId>io.trygvis.container</groupId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>persistence-compile-time</artifactId>
+ <dependencies>
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ <version>2.6</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/pom.xml b/pom.xml
index 9997562..b8e3ab6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -27,5 +27,6 @@
<module>container-compiler-plugin</module>
<module>myapp</module>
<module>container-core</module>
+ <module>persistence-compile-time</module>
</modules>
</project>