From 8cca2127e0e11486cc45ae1a8198bd778301f935 Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Mon, 19 Aug 2013 19:45:28 +0200 Subject: o Dropping the Sequences class. Moving more stuff into SqlUnit to make it easier available in a generic form. o Fixing the complicated cases where the generation got confused with both setter and constructor injection. --- .../trygvis/container/compiler/EntityHandler.java | 135 +++++++++++++++------ .../io/trygvis/container/compiler/MyProcessor.java | 2 - 2 files changed, 99 insertions(+), 38 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 ba9f100..5eb404b 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 @@ -9,6 +9,7 @@ import io.trygvis.persistence.SqlEntity; import io.trygvis.persistence.SqlEntitySet; import io.trygvis.persistence.TypeHandler; import io.trygvis.persistence.generators.DaoGenerator; +import io.trygvis.persistence.sql.SqlConstructor; import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.AnnotationMirror; @@ -22,6 +23,7 @@ import javax.lang.model.element.TypeElement; import javax.lang.model.element.VariableElement; import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; +import javax.persistence.AccessType; import javax.persistence.Id; import javax.persistence.SequenceGenerator; import java.util.ArrayList; @@ -37,13 +39,12 @@ import static io.trygvis.container.compiler.Utils.toFieldName; import static io.trygvis.container.compiler.Utils.writeFile; import static io.trygvis.persistence.FieldMirror.FieldType.PRIMITIVE; import static io.trygvis.persistence.FieldMirror.FieldType.REFERENCE; -import static io.trygvis.persistence.FieldMirror.GetterType; -import static io.trygvis.persistence.FieldMirror.SetterType; import static io.trygvis.persistence.TypeHandler.StringEnumTypeHandler; import static java.lang.Character.isUpperCase; import static java.lang.String.format; -import static javax.lang.model.util.ElementFilter.fieldsIn; -import static javax.lang.model.util.ElementFilter.methodsIn; +import static javax.lang.model.util.ElementFilter.*; +import static javax.persistence.AccessType.FIELD; +import static javax.persistence.AccessType.PROPERTY; import static org.apache.commons.lang.StringUtils.join; public class EntityHandler extends AbstractHandler { @@ -116,6 +117,10 @@ public class EntityHandler extends AbstractHandler { } public EntityMirror buildMirror(TypeElement element, boolean concrete) throws Exception { + // ----------------------------------------------------------------------- + // Figure out inheritage and ancestry + // ----------------------------------------------------------------------- + EntityMirror superEntity = null; Set ancestry = new TreeSet<>(new TypeMirrorComparator()); @@ -135,11 +140,48 @@ public class EntityHandler extends AbstractHandler { superType = superTypeMirror.getSuperclass(); } + // ----------------------------------------------------------------------- + // Find constructor + // ----------------------------------------------------------------------- + + ExecutableElement constructor = null; + List constructors = constructorsIn(elements.getAllMembers(element)); + if (constructors.size() == 1) { + constructor = constructors.get(0); + } else { + for (ExecutableElement c : constructors) { + AnnotationMirror sqlConstructor = findAnnotation(SqlConstructor.class, c); + if (sqlConstructor == null) { + continue; + } + + if (constructor != null) { + throw new CompilerException(c, "There can only be one @SqlConstructor annotated constructor."); + } + + constructor = c; + } + } + + System.out.println("element = " + element); + System.out.println("constructor = " + constructor); + + List constructorParameters = new ArrayList<>(); + for (VariableElement p : constructor.getParameters()) { + String name = p.getSimpleName().toString(); + constructorParameters.add(name); + } + + // ----------------------------------------------------------------------- + // + // ----------------------------------------------------------------------- + EntityMirror entity = new EntityMirror( generatorConfiguration, new TypeRef(types.getDeclaredType(element)), concrete, superEntity, + constructor, constructorParameters, concrete ? Utils.sqlName(element.getSimpleName().toString()) : null); Map getters = new TreeMap<>(); @@ -166,7 +208,6 @@ public class EntityHandler extends AbstractHandler { } for (VariableElement f : fieldsIn(elements.getAllMembers(element))) { - System.out.println("f.getEnclosingElement() = " + f.getEnclosingElement()); if (!ancestry.contains(f.getEnclosingElement().asType())) { continue; } @@ -174,7 +215,7 @@ public class EntityHandler extends AbstractHandler { String name = f.getSimpleName().toString(); ExecutableElement getter = getters.remove(name); ExecutableElement setter = setters.remove(name); - FieldMirror field = fromElement(generatorConfiguration, f, getter, setter); + FieldMirror field = fromElement(generatorConfiguration, entity, f, getter, setter); if (field == null) { continue; } @@ -191,7 +232,7 @@ public class EntityHandler extends AbstractHandler { continue; } - FieldMirror field = fromElement(generatorConfiguration, null, getter, setter); + FieldMirror field = fromElement(generatorConfiguration, entity, null, getter, setter); if (field == null) { continue; } @@ -221,25 +262,40 @@ public class EntityHandler extends AbstractHandler { } public void validate(Element element, EntityMirror entity) { - if (!entity.concrete) { - return; - } + if (entity.concrete) { + List idFields = new ArrayList<>(); + List constructorFields = new ArrayList<>(); + for (FieldMirror field : entity.getFields()) { + if (field.id) { + idFields.add(field); + } + if (field.constructorParam) { + constructorFields.add(field); + } + } - List idFields = new ArrayList<>(); - for (FieldMirror field : entity.getFields()) { - if (field.id) { - idFields.add(field); + if (idFields.size() == 0) { + throw new CompilerException(element, "An @Entity is required to have at least one @Id field."); + } + if (idFields.size() != 1) { + throw new CompilerException(element, "This implementation only support a single @Id annotated field."); } - } - if (idFields.size() == 0) { - throw new CompilerException(element, "An @Entity is required to have at least one @Id field."); - } - if (idFields.size() != 1) { - throw new CompilerException(element, "This implementation only support a single @Id annotated field."); - } + entity.setIdType(idFields.get(0).type); - entity.setIdType(idFields.get(0).type); + System.out.println("constructorFields = " + constructorFields); + System.out.println("entity.getConstructorParameters() = " + entity.getConstructorParameters()); + List constructorParameters = new ArrayList<>(entity.getConstructorParameters()); + for (FieldMirror f : constructorFields) { + if (!constructorParameters.remove(f.javaName)) { + throw new CompilerException(entity.constructor, "Unknown field used in constructor: " + f.javaName); + } + } + + if (!constructorParameters.isEmpty()) { + throw new CompilerException(entity.constructor, "Unknown field used in constructor: " + join(constructorParameters, ", ")); + } + } } private void processSequenceGenerators(Element element) { @@ -278,12 +334,13 @@ public class EntityHandler extends AbstractHandler { } } - public FieldMirror fromElement(GeneratorConfiguration generatorConfiguration, VariableElement var, - ExecutableElement getter, ExecutableElement setter) { + public FieldMirror fromElement(GeneratorConfiguration generatorConfiguration, EntityMirror entity, + VariableElement var, ExecutableElement getter, ExecutableElement setter) { // TODO: check the setter for annotations too // TODO: check for transient and @Transient - final SetterType setterType; - final GetterType getterType; + boolean isConstructorParameter; + final AccessType setterType; + final AccessType getterType; TypeRef type; Element element; String javaName; @@ -294,16 +351,19 @@ public class EntityHandler extends AbstractHandler { if (var.getModifiers().contains(Modifier.STATIC)) { return null; } + javaName = var.getSimpleName().toString(); + isConstructorParameter = entity.hasConstructorParameter(javaName); + boolean isFinal = var.getModifiers().contains(Modifier.FINAL); if (isFinal) { - setterType = SetterType.CONSTRUCTOR; - } else { - setterType = setter != null ? SetterType.METHOD : SetterType.FIELD; + if (!isConstructorParameter) { + throw new CompilerException(var, "The field " + javaName + " is final, but not a constructor parameter. Constructor parameters: " + join(entity.getConstructorParameters(), ", ")); + } } - getterType = getter != null ? GetterType.METHOD : GetterType.FIELD; + setterType = setter != null ? PROPERTY : FIELD; + getterType = getter != null ? PROPERTY : FIELD; type = new TypeRef(var.asType()); element = types.asElement(var.asType()); - javaName = var.getSimpleName().toString(); id = isId(var); processSequenceGenerators(var); } else { @@ -314,8 +374,9 @@ public class EntityHandler extends AbstractHandler { // Skipping fields is closer to what hibernate does. return null; } - setterType = SetterType.METHOD; - getterType = GetterType.METHOD; + isConstructorParameter = false; + setterType = PROPERTY; + getterType = PROPERTY; type = new TypeRef(getter.getReturnType()); element = types.asElement(getter.getReturnType()); id = isId(getter); @@ -348,11 +409,11 @@ public class EntityHandler extends AbstractHandler { TypeHandler typeHandler = generatorConfiguration.typeHandler(type); // TODO: check for configuration conflict notNull = !typeHandler.nullable; - field = new FieldMirror(PRIMITIVE, setterType, getterType, type, javaName, sqlName, id, notNull, unique); + field = new FieldMirror(PRIMITIVE, isConstructorParameter, setterType, getterType, type, javaName, sqlName, id, notNull, unique); } else if (generatorConfiguration.hasTypeHandler(type)) { throw new CompilerException(var, "Missing type handler for type: " + type.fqName); } else { - field = new FieldMirror(REFERENCE, setterType, getterType, type, javaName, sqlName, id, notNull, unique); + field = new FieldMirror(REFERENCE, isConstructorParameter, setterType, getterType, type, javaName, sqlName, id, notNull, unique); } return field; } @@ -378,7 +439,6 @@ public class EntityHandler extends AbstractHandler { continue; } - System.out.println("entity.type = " + entity.type); DaoGenerator daoGenerator = new DaoGenerator(generatorConfiguration, sqlUnit, entity); writeFile(processingEnv, daoGenerator.generate(), sqlUnit.element(entity)); writeFile(processingEnv, daoGenerator.generateRow(), sqlUnit.element(entity)); @@ -392,6 +452,9 @@ public class EntityHandler extends AbstractHandler { } } + /** + * @return Returns null if the annotation could not be found. + */ private AnnotationMirror findAnnotation(Class c, Element type) { TypeMirror annotationType = elements.getTypeElement(c.getCanonicalName()).asType(); for (AnnotationMirror a : type.getAnnotationMirrors()) { 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 80b7283..e9029c7 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 @@ -27,7 +27,6 @@ import java.util.HashSet; import java.util.Set; import static io.trygvis.container.compiler.Utils.writeFile; -import static io.trygvis.persistence.generators.SequencesGenerator.generateSequences; import static io.trygvis.persistence.generators.SqlSessionFactoryGenerator.generateSqlSessionFactory; import static io.trygvis.persistence.generators.SqlSessionGenerator.generateSqlSession; import static java.util.Arrays.asList; @@ -145,7 +144,6 @@ public class MyProcessor implements Processor { } entityHandler.phase3(hadErrors); - writeFile(processingEnv, generateSequences(unit), null); // writeFile(processingEnv, generateEntityManagerFactory(unit), null); // writeFile(processingEnv, generateEntityManager(unit), null); writeFile(processingEnv, generateSqlSession(unit), null); -- cgit v1.2.3