diff options
Diffstat (limited to 'container-compiler-plugin/src/main/java/io/trygvis/persistence')
5 files changed, 212 insertions, 0 deletions
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()))"; + } + } +} |