summaryrefslogtreecommitdiff
path: root/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/EntityHandler.java
diff options
context:
space:
mode:
Diffstat (limited to 'container-compiler-plugin/src/main/java/io/trygvis/container/compiler/EntityHandler.java')
-rw-r--r--container-compiler-plugin/src/main/java/io/trygvis/container/compiler/EntityHandler.java135
1 files changed, 99 insertions, 36 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 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<TypeMirror> ancestry = new TreeSet<>(new TypeMirrorComparator());
@@ -135,11 +140,48 @@ public class EntityHandler extends AbstractHandler {
superType = superTypeMirror.getSuperclass();
}
+ // -----------------------------------------------------------------------
+ // Find constructor
+ // -----------------------------------------------------------------------
+
+ ExecutableElement constructor = null;
+ List<ExecutableElement> 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<String> 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<String, ExecutableElement> 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<FieldMirror> idFields = new ArrayList<>();
+ List<FieldMirror> constructorFields = new ArrayList<>();
+ for (FieldMirror field : entity.getFields()) {
+ if (field.id) {
+ idFields.add(field);
+ }
+ if (field.constructorParam) {
+ constructorFields.add(field);
+ }
+ }
- List<FieldMirror> 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<String> 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()) {