summaryrefslogtreecommitdiff
path: root/container-compiler-plugin/src
diff options
context:
space:
mode:
Diffstat (limited to 'container-compiler-plugin/src')
-rw-r--r--container-compiler-plugin/src/main/java/io/trygvis/container/compiler/EntityHandler.java133
-rw-r--r--container-compiler-plugin/src/main/java/io/trygvis/container/compiler/MyProcessor.java4
-rw-r--r--container-compiler-plugin/src/main/java/io/trygvis/container/compiler/SqlUnitModel.java8
-rw-r--r--container-compiler-plugin/src/main/java/io/trygvis/persistence/EntityMirror.java11
-rw-r--r--container-compiler-plugin/src/main/java/io/trygvis/persistence/GeneratorConfiguration.java2
-rw-r--r--container-compiler-plugin/src/main/java/io/trygvis/persistence/SequenceMirror.java30
-rw-r--r--container-compiler-plugin/src/main/java/io/trygvis/persistence/TypeHandler.java32
-rw-r--r--container-compiler-plugin/src/test/java/io/trygvis/container/compiler/ProcessorTest.java3
-rw-r--r--container-compiler-plugin/src/test/java/io/trygvis/persistence/EntityMirrorTest.java11
-rw-r--r--container-compiler-plugin/src/test/resources/io/trygvis/persistence/test/ChildEntity.java18
-rw-r--r--container-compiler-plugin/src/test/resources/io/trygvis/persistence/test/ParentEntity.java6
11 files changed, 206 insertions, 52 deletions
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 98090a4..53811d9 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
@@ -16,6 +16,7 @@ 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.Modifier;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
@@ -27,6 +28,7 @@ import javax.tools.JavaFileObject;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -43,6 +45,7 @@ import static java.lang.String.format;
import static java.lang.reflect.Modifier.PUBLIC;
import static javax.lang.model.util.ElementFilter.fieldsIn;
import static javax.lang.model.util.ElementFilter.methodsIn;
+import static org.apache.commons.lang.StringUtils.capitalize;
import static org.apache.commons.lang.StringUtils.join;
import static org.apache.commons.lang.StringUtils.stripEnd;
@@ -87,7 +90,7 @@ public class EntityHandler extends AbstractHandler {
}
public void recordEntity(TypeElement element) throws Exception {
- EntityMirror entityMirror = new EntityMirror(
+ EntityMirror entity = new EntityMirror(
generatorConfiguration,
new TypeRef(types.getDeclaredType(element)),
sqlName(element.getSimpleName().toString()));
@@ -125,7 +128,7 @@ public class EntityHandler extends AbstractHandler {
if (field == null) {
continue;
}
- entityMirror.add(field);
+ entity.add(field);
System.out.println("Field: " + field);
}
@@ -137,44 +140,34 @@ public class EntityHandler extends AbstractHandler {
if (field == null) {
continue;
}
- entityMirror.add(field);
+ entity.add(field);
System.out.println("Field: " + field);
}
+ Iterator<ExecutableElement> it = setters.values().iterator();
+ while (it.hasNext()) {
+ ExecutableElement setter = it.next();
+ if (setter.getModifiers().contains(Modifier.STATIC)) {
+ it.remove();
+ }
+ }
+
if (!setters.isEmpty()) {
- throw new CompilerException(element, "Missing getters for setters: " + join(setters.keySet(), ", "));
+ throw new CompilerException(element, "Missing getters for these setters: " + join(setters.keySet(), ", "));
}
// -----------------------------------------------------------------------
// Process any extra annotations
// -----------------------------------------------------------------------
- AnnotationMirror sequenceGenerator = findAnnotation(SequenceGenerator.class, element);
-
- if (sequenceGenerator != null) {
- String name = null;
- for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> v : sequenceGenerator.getElementValues().entrySet()) {
- String field = v.getKey().getSimpleName().toString();
- switch (field) {
- case "name":
- name = v.getValue().getValue().toString();
-
- break;
- default:
- throw new InternalErrorException("Unsupported field on @SequenceGenerator: " + field);
- }
- }
- if (name != null) {
- sqlUnit.add(new SequenceMirror(name));
- }
- }
+ processSequenceGenerators(element);
// -----------------------------------------------------------------------
// Validation
// -----------------------------------------------------------------------
List<FieldMirror> idFields = new ArrayList<>();
- for (FieldMirror field : entityMirror.fields) {
+ for (FieldMirror field : entity.fields) {
if (field.id) {
idFields.add(field);
}
@@ -187,7 +180,42 @@ public class EntityHandler extends AbstractHandler {
throw new CompilerException(element, "This implementation only support a single @Id annotated field.");
}
- sqlUnit.add(entityMirror, element);
+ sqlUnit.add(entity, element);
+ }
+
+ private void processSequenceGenerators(Element element) {
+ AnnotationMirror sequenceGenerator = findAnnotation(SequenceGenerator.class, element);
+
+ if (sequenceGenerator != null) {
+ String name = null;
+ String sequenceName = null;
+ int initialValue = 0;
+ int allocationSize = 0;
+
+ for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> v : sequenceGenerator.getElementValues().entrySet()) {
+ String field = v.getKey().getSimpleName().toString();
+ switch (field) {
+ case "name":
+ name = v.getValue().getValue().toString();
+ break;
+ case "sequenceName":
+ sequenceName = v.getValue().getValue().toString();
+ break;
+ case "initialValue":
+ initialValue = Integer.valueOf(v.getValue().getValue().toString());
+ break;
+ case "allocationSize":
+ allocationSize = Integer.valueOf(v.getValue().getValue().toString());
+ break;
+ default:
+ throw new InternalErrorException("Unsupported field on @SequenceGenerator: " + field);
+ }
+ }
+ if (name != null) {
+ sequenceName = sequenceName == null ? sqlName(name) : sequenceName;
+ sqlUnit.add(new SequenceMirror(name, sequenceName, initialValue, allocationSize), element);
+ }
+ }
}
public ClassG phase3(EntityMirror entityMirror) throws IOException {
@@ -230,14 +258,27 @@ public class EntityHandler extends AbstractHandler {
boolean id;
if (var != null) {
+ if (var.getModifiers().contains(Modifier.STATIC)) {
+ return null;
+ }
accessorType = FIELD;
type = new TypeRef(var.asType());
javaName = var.getSimpleName().toString();
id = isId(var);
+ processSequenceGenerators(var);
} else {
+ if (getter.getModifiers().contains(Modifier.STATIC)) {
+ return null;
+ }
+ if (setter == null) {
+ // Skipping fields is closer to what hibernate does.
+ return null;
+// throw new CompilerException(getter, "Missing setter for getter: " + getter.getSimpleName());
+ }
accessorType = METHOD;
type = new TypeRef(getter.getReturnType());
id = isId(getter);
+ processSequenceGenerators(getter);
// TODO: this might be relaxed, just find the common type and use that.
if (!types.isSameType(getter.getReturnType(), setter.getParameters().get(0).asType())) {
throw new CompilerException(format("The setter and getter %s/%s must access the same types.",
@@ -269,26 +310,44 @@ public class EntityHandler extends AbstractHandler {
return var.getAnnotation(Id.class) != null;
}
- public void phase3() throws Exception {
- for (EntityMirror entity : sqlUnit.getEntities().values()) {
- writeFile(phase3(entity), sqlUnit.element(entity));
+ public void phase3(boolean errorRaised) throws Exception {
+ System.out.println("errorRaised = " + errorRaised);
+ try {
+ for (EntityMirror entity : sqlUnit.getEntities().values()) {
+ writeFile(phase3(entity), sqlUnit.element(entity));
+ }
+ writeFile(generateSequences(sqlUnit), null);
+ writeFile(generateSession(), null);
+ } catch (CompilerException | InternalErrorException e) {
+ // Ignore any exceptions if we had an error from before
+ if (errorRaised) {
+ return;
+ }
+ throw e;
}
- writeFile(generateSequences(sqlUnit), null);
- writeFile(generateSession(), null);
}
private ClassG generateSequences(SqlUnitModel unit) {
TypeRef sequences = new TypeRef(unit.getPackageName() + ".Sequences");
ClassG g = new ClassG(PUBLIC, sequences);
- List<String> fields = new ArrayList<>();
+ List<String> creates = new ArrayList<>();
+ List<String> drops = new ArrayList<>();
for (SequenceMirror sequence : unit.getSequences().values()) {
TypeRef stringType = g.imports.add(String.class);
- String value = "CREATE SEQUENCE " + sequence.name + ";";
- FieldRef f = g.addPublicStaticFinalField(stringType, sequence.name).value(toJavaString(value));
- fields.add(f.name);
+ String value = "CREATE SEQUENCE " + sequence.sequenceName + ";";
+ FieldRef f = g.addPublicStaticFinalField(stringType, "create" + capitalize(sequence.name)).
+ value(toJavaString(value));
+ creates.add(f.name);
+
+ f = g.addPublicStaticFinalField(stringType, "drop" + capitalize(sequence.name)).
+ value(toJavaString("DROP SEQUENCE " + sequence.sequenceName) + ";");
+ drops.add(f.name);
+
}
- g.addPublicStaticFinalField(new TypeRef(String[].class), "sequences").
- value("new String[]{" + join(fields, ", ") + "}");
+ g.addPublicStaticFinalField(new TypeRef(String[].class), "createSequences").
+ value("new String[]{" + join(creates, ", ") + "}");
+ g.addPublicStaticFinalField(new TypeRef(String[].class), "dropSequences").
+ value("new String[]{" + join(drops, ", ") + "}");
return g;
}
@@ -336,7 +395,7 @@ public class EntityHandler extends AbstractHandler {
return builder.toString();
}
- private AnnotationMirror findAnnotation(Class<?> c, TypeElement type) {
+ private AnnotationMirror findAnnotation(Class<?> c, Element type) {
TypeMirror annotationType = elements.getTypeElement(c.getCanonicalName()).asType();
for (AnnotationMirror a : type.getAnnotationMirrors()) {
if (types.isSameType(a.getAnnotationType(), annotationType)) {
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 89da439..fbbc56d 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
@@ -110,6 +110,7 @@ public class MyProcessor implements Processor {
Set<PackageElement> packages = ElementFilter.packagesIn(roundEnv.getElementsAnnotatedWith(SqlEntitySet.class));
entityHandler.phase1(sqlEntities, packages);
+ boolean hadErrors = false;
for (Element element : roundEnv.getRootElements()) {
System.out.println("Processing: " + element.asType());
for (AnnotationMirror annotationMirror : element.getAnnotationMirrors()) {
@@ -128,12 +129,13 @@ public class MyProcessor implements Processor {
// e.printStackTrace(System.out);
Messager messager = processingEnv.getMessager();
messager.printMessage(Diagnostic.Kind.ERROR, e.getMessage(), e.element);
+ hadErrors = true;
}
}
}
}
- entityHandler.phase3();
+ entityHandler.phase3(hadErrors);
return true;
}
diff --git a/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/SqlUnitModel.java b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/SqlUnitModel.java
index 568bbe7..1bd2535 100644
--- a/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/SqlUnitModel.java
+++ b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/SqlUnitModel.java
@@ -67,13 +67,17 @@ public class SqlUnitModel {
// -----------------------------------------------------------------------
public SqlUnitModel add(SequenceMirror sequence, Element element) {
+ Element e = sequenceElements.get(sequence);
+ if (e != null && !e.equals(element)) {
+ throw new CompilerException(element, "This unit already contains a sequence called '" + sequence.name + "'.");
+ }
sequences.put(sequence.name, sequence);
sequenceElements.put(sequence, element);
return this;
}
- public SqlUnitModel add(SequenceMirror... sequenceMirrors) {
- for (SequenceMirror sequenceMirror : sequenceMirrors) {
+ public SqlUnitModel add(SequenceMirror... sequences) {
+ for (SequenceMirror sequenceMirror : sequences) {
this.sequences.put(sequenceMirror.name, sequenceMirror);
}
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
index f1970f7..f0f4ae7 100644
--- a/container-compiler-plugin/src/main/java/io/trygvis/persistence/EntityMirror.java
+++ b/container-compiler-plugin/src/main/java/io/trygvis/persistence/EntityMirror.java
@@ -111,7 +111,7 @@ public class EntityMirror implements Comparable<EntityMirror> {
for (FieldMirror field : fields) {
columns.add(field.sqlName);
if (field.id) {
- values.add("nextval('" + unit.getDefaultSequence().name + "')");
+ values.add("nextval('" + unit.getDefaultSequence().sequenceName + "')");
} else {
values.add("?");
}
@@ -162,7 +162,12 @@ public class EntityMirror implements Comparable<EntityMirror> {
if (field.fieldType == PRIMITIVE) {
TypeHandler typeHandler = generatorConfiguration.typeHandler(field.type);
- String access = o.name + "." + field.javaName;
+ String access;
+ if (field.accessorType == FIELD) {
+ access = o.name + "." + field.javaName;
+ } else {
+ access = o.name + "." + toGetterName(field.javaName) + "()";
+ }
String setter = " stmt." + typeHandler.setter(i, access) + ";";
if (field.notNull) {
@@ -283,7 +288,6 @@ public class EntityMirror implements Comparable<EntityMirror> {
body.add(field.type + " " + field.javaName + " = null;");
}
names.add(field.javaName);
- i++;
}
body.add(type + " returnValue = new " + type + "(" + join(names, ", ") + ");");
@@ -305,7 +309,6 @@ public class EntityMirror implements Comparable<EntityMirror> {
body.add("returnValue." + toSetterName(field.javaName) + "(" + null + ");");
}
names.add(field.javaName);
- i++;
}
body.add("return returnValue;");
diff --git a/container-compiler-plugin/src/main/java/io/trygvis/persistence/GeneratorConfiguration.java b/container-compiler-plugin/src/main/java/io/trygvis/persistence/GeneratorConfiguration.java
index 37d8146..9df6c35 100644
--- a/container-compiler-plugin/src/main/java/io/trygvis/persistence/GeneratorConfiguration.java
+++ b/container-compiler-plugin/src/main/java/io/trygvis/persistence/GeneratorConfiguration.java
@@ -17,6 +17,8 @@ public class GeneratorConfiguration {
typeHandlers.put(new TypeRef(Long.class), new TypeHandler.LongTypeHandler());
typeHandlers.put(new TypeRef(String.class), new TypeHandler.StringTypeHandler());
typeHandlers.put(new TypeRef(Date.class), new TypeHandler.DateTypeHandler());
+ typeHandlers.put(new TypeRef("org.joda.time.DateTime"), new TypeHandler.JodaDateTimeTypeHandler());
+ typeHandlers.put(new TypeRef("java.util.UUID"), new TypeHandler.UuidTypeHandler());
primitiveTypeHandlers.putAll(typeHandlers);
}
diff --git a/container-compiler-plugin/src/main/java/io/trygvis/persistence/SequenceMirror.java b/container-compiler-plugin/src/main/java/io/trygvis/persistence/SequenceMirror.java
index 9ae6781..6a9da6c 100644
--- a/container-compiler-plugin/src/main/java/io/trygvis/persistence/SequenceMirror.java
+++ b/container-compiler-plugin/src/main/java/io/trygvis/persistence/SequenceMirror.java
@@ -1,9 +1,35 @@
package io.trygvis.persistence;
-public class SequenceMirror {
+public class SequenceMirror implements Comparable<SequenceMirror> {
public final String name;
+ public final String sequenceName;
+ public final int initialValue;
+ public final int allocationSize;
- public SequenceMirror(String name) {
+ public SequenceMirror(String name, String sequenceName, int initialValue, int allocationSize) {
this.name = name;
+ this.sequenceName = sequenceName;
+ this.initialValue = initialValue == 0 ? 10000 : initialValue;
+ this.allocationSize = allocationSize == 0 ? 1000 : allocationSize;
+ }
+
+ @Override
+ public int compareTo(@SuppressWarnings("NullableProblems") SequenceMirror o) {
+ return name.compareTo(o.name);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof SequenceMirror)) return false;
+
+ SequenceMirror that = (SequenceMirror) o;
+
+ return name.equals(that.name);
+ }
+
+ @Override
+ public int hashCode() {
+ return name.hashCode();
}
}
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
index 72941f2..31eba4b 100644
--- a/container-compiler-plugin/src/main/java/io/trygvis/persistence/TypeHandler.java
+++ b/container-compiler-plugin/src/main/java/io/trygvis/persistence/TypeHandler.java
@@ -116,4 +116,36 @@ public abstract class TypeHandler {
return "new java.util.Date(" + rs + ".getTimestamp(" + i + ").getTime())";
}
}
+
+ public static class JodaDateTimeTypeHandler extends TypeHandler {
+ protected JodaDateTimeTypeHandler() {
+ super("TIMESTAMP", TIMESTAMP);
+ }
+
+ @Override
+ public String setter(int i, String expr) {
+ return "setTimestamp(" + i + ", new java.sql.Timestamp(" + expr + ".getTime()))";
+ }
+
+ @Override
+ public String getter(String rs, int i) {
+ return "new org.joda.time.DateTime(" + rs + ".getTimestamp(" + i + ").getTime())";
+ }
+ }
+
+ public static class UuidTypeHandler extends TypeHandler {
+ protected UuidTypeHandler() {
+ super("CHAR(36)", CHAR);
+ }
+
+ @Override
+ public String setter(int i, String expr) {
+ return "setString(" + i + ", " + expr + ".toString())";
+ }
+
+ @Override
+ public String getter(String rs, int i) {
+ return "java.util.UUID.fromString(" + rs + ".getString(" + i + "))";
+ }
+ }
}
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 c7891fc..f30b731 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
@@ -62,7 +62,8 @@ public class ProcessorTest {
assertThat(fileManager.codes.keySet()).containsOnly(
"io.trygvis.persistence.test.Sequences",
"io.trygvis.persistence.test.Session",
- "io.trygvis.persistence.test.PersonDao");
+ "io.trygvis.persistence.test.PersonDao",
+ "io.trygvis.persistence.test.ChildEntityDao");
assertThat(collector.getDiagnostics()).isEmpty();
assertThat(result).isTrue();
diff --git a/container-compiler-plugin/src/test/java/io/trygvis/persistence/EntityMirrorTest.java b/container-compiler-plugin/src/test/java/io/trygvis/persistence/EntityMirrorTest.java
index 52b33ca..85e3741 100644
--- a/container-compiler-plugin/src/test/java/io/trygvis/persistence/EntityMirrorTest.java
+++ b/container-compiler-plugin/src/test/java/io/trygvis/persistence/EntityMirrorTest.java
@@ -71,7 +71,7 @@ public class EntityMirrorTest {
myTable.add(field);
}
- SqlUnitModel unit = new SqlUnitModel().add(myTable).add(new SequenceMirror("id_seq"));
+ SqlUnitModel unit = new SqlUnitModel().add(myTable).add(new SequenceMirror("seq-gen", "id_seq", 0, 0));
assertEquals(myTable.insertIntoSql(unit), insert);
assertEquals(myTable.deleteFromSql(), delete);
@@ -92,9 +92,16 @@ public class EntityMirrorTest {
" stmt.executeUpdate();",
"}")
},
- new Object[]{new FieldMirror[]{age}, join(
+ new Object[]{new FieldMirror[]{year}, join(
+ "try(java.sql.PreparedStatement stmt = con.prepareStatement(insertIntoSql)) {",
+ " stmt.setInt(1, o.getYear());",
+ " stmt.executeUpdate();",
+ "}")
+ },
+ new Object[]{new FieldMirror[]{age, year, idLong}, join(
"try(java.sql.PreparedStatement stmt = con.prepareStatement(insertIntoSql)) {",
" stmt.setInt(1, o.age);",
+ " stmt.setInt(2, o.getYear());",
" stmt.executeUpdate();",
"}")
},
diff --git a/container-compiler-plugin/src/test/resources/io/trygvis/persistence/test/ChildEntity.java b/container-compiler-plugin/src/test/resources/io/trygvis/persistence/test/ChildEntity.java
index d886fca..a341fd2 100644
--- a/container-compiler-plugin/src/test/resources/io/trygvis/persistence/test/ChildEntity.java
+++ b/container-compiler-plugin/src/test/resources/io/trygvis/persistence/test/ChildEntity.java
@@ -10,4 +10,22 @@ public class ChildEntity extends ParentEntity {
super(id);
this.name = name;
}
+
+ // -----------------------------------------------------------------------
+ // These static versions shouldn't affect anything
+ // -----------------------------------------------------------------------
+
+ public static void setSetterOnly(int x) {
+ }
+
+ public static int getAccessorPair() {
+ return 0;
+ }
+
+ public static void setAccessorPair(int x) {
+ }
+
+ public static int getGetterOnly() {
+ return 0;
+ }
}
diff --git a/container-compiler-plugin/src/test/resources/io/trygvis/persistence/test/ParentEntity.java b/container-compiler-plugin/src/test/resources/io/trygvis/persistence/test/ParentEntity.java
index 4695739..9925f7e 100644
--- a/container-compiler-plugin/src/test/resources/io/trygvis/persistence/test/ParentEntity.java
+++ b/container-compiler-plugin/src/test/resources/io/trygvis/persistence/test/ParentEntity.java
@@ -4,14 +4,14 @@ import javax.persistence.Id;
public class ParentEntity {
@Id
- public final Long id;
+ public Long id;
+
+ private Integer age;
public ParentEntity(Long id) {
this.id = id;
}
- private Integer age;
-
public Integer getAge() {
return age;
}