From 6d4c6960e69b53c124bd84beb3d008bd5a4bb319 Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Sun, 4 Aug 2013 18:50:18 +0200 Subject: wip o Adding Joda time's DateTime and UUID. o Registering @SequenceGenerator's on fields and getters. o Skipping static methods. o Generating SQL to drop sequences. --- .../trygvis/container/compiler/EntityHandler.java | 133 +++++++++++++++------ .../io/trygvis/container/compiler/MyProcessor.java | 4 +- .../trygvis/container/compiler/SqlUnitModel.java | 8 +- 3 files changed, 105 insertions(+), 40 deletions(-) (limited to 'container-compiler-plugin/src/main/java/io/trygvis/container') 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 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 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 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 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 fields = new ArrayList<>(); + List creates = new ArrayList<>(); + List 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 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; -- cgit v1.2.3