From 26b01b500065634eb3133dc354a0ba71b13bff56 Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Wed, 7 Aug 2013 23:53:53 +0200 Subject: wip o Start of JPA implementation. --- .../java/io/trygvis/persistence/EntityMirror.java | 75 +++++++++--- .../java/io/trygvis/persistence/SqlEntitySet.java | 1 + .../generators/EntityManagerFactoryGenerator.java | 69 +++++++++++ .../generators/EntityManagerGenerator.java | 129 +++++++++++++++++++++ .../persistence/generators/SequencesGenerator.java | 41 +++++++ 5 files changed, 297 insertions(+), 18 deletions(-) create mode 100644 container-compiler-plugin/src/main/java/io/trygvis/persistence/generators/EntityManagerFactoryGenerator.java create mode 100644 container-compiler-plugin/src/main/java/io/trygvis/persistence/generators/EntityManagerGenerator.java create mode 100644 container-compiler-plugin/src/main/java/io/trygvis/persistence/generators/SequencesGenerator.java (limited to 'container-compiler-plugin/src/main/java/io/trygvis/persistence') 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 5d6defb..140a910 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 @@ -3,6 +3,7 @@ package io.trygvis.persistence; import io.trygvis.container.compiler.NotImplementedException; import io.trygvis.container.compiler.SqlUnitModel; import io.trygvis.container.compiler.model.ClassG; +import io.trygvis.container.compiler.model.Constructor; import io.trygvis.container.compiler.model.Imports; import io.trygvis.container.compiler.model.MethodRef; import io.trygvis.container.compiler.model.Parameters; @@ -38,6 +39,8 @@ public class EntityMirror implements Comparable { public final TypeRef type; public final String tableName; public final TypeRef daoType; + public final TypeRef utilsType; + public TypeRef idType; public EntityMirror(GeneratorConfiguration generatorConfiguration, TypeRef type, String tableName) { this.generatorConfiguration = generatorConfiguration; @@ -45,6 +48,7 @@ public class EntityMirror implements Comparable { this.tableName = tableName; this.daoType = new TypeRef(type.plainName + "Dao").args(type.args); + this.utilsType = new TypeRef(type.plainName + ".Utils").args(type.args); } public void add(FieldMirror... fields) { @@ -57,6 +61,10 @@ public class EntityMirror implements Comparable { } } + public void setIdType(TypeRef idType) { + this.idType = idType; + } + public FieldMirror getIdField() { return idFields.get(0); } @@ -180,7 +188,7 @@ public class EntityMirror implements Comparable { body.add(setter); } else { body.add(" " + field.type + " " + field.javaName + " = " + accessor + ";"); - body.add(" if(" + field.javaName + " == null) {"); + body.add(" if (" + field.javaName + " == null) {"); body.add(" stmt.setNull(" + i + ", " + typesType + "." + typeHandler.typeName() + ");"); body.add(" } else {"); body.add(" " + setter); @@ -189,7 +197,23 @@ public class EntityMirror implements Comparable { } body.add(" stmt.executeUpdate();"); body.add("}"); - return new MethodRef(PUBLIC | STATIC, TypeRef.VOID, "insertInto", p, body).exception(sqlExceptionType); + return new MethodRef(PUBLIC | STATIC, TypeRef.VOID, "insert" + type.className, p, body).exception(sqlExceptionType); + } + + public MethodRef selectById(Imports imports) { + Parameters p = new Parameters(); + p.addParameter(imports.add(Connection.class), "c"); + p.addParameter(idType, "id"); + return new MethodRef(PUBLIC | STATIC, type, "select" + type.className + "ById", p, + "throw new UnsupportedOperationException(\"Not implemented\");"); + } + + public MethodRef update(Imports imports) { + Parameters p = new Parameters(); + p.addParameter(imports.add(Connection.class), "c"); + p.addParameter(type, "entity"); + return new MethodRef(PUBLIC | STATIC, type, "update" + type.className, p, + "throw new UnsupportedOperationException(\"Not implemented\");"); } public MethodRef delete(Imports imports) { @@ -208,11 +232,9 @@ public class EntityMirror implements Comparable { arguments.add(o.name + "." + toGetterName(field.javaName) + "()"); } } - List body = new ArrayList<>(); - body.add("deleteById(" + join(arguments, ", ") + ");"); - return new MethodRef(PUBLIC | STATIC, TypeRef.VOID, "delete", p, body). - exception(imports.add(SQLException.class)); + return new MethodRef(PUBLIC | STATIC, TypeRef.VOID, "delete" + type.className, p, + "delete" + type.className + "ById(" + join(arguments, ", ") + ");").exception(imports.add(SQLException.class)); } public MethodRef deleteById(Imports imports) { @@ -233,22 +255,29 @@ public class EntityMirror implements Comparable { body.add(" stmt.executeUpdate();"); body.add("}"); - return new MethodRef(PUBLIC | STATIC, TypeRef.VOID, "deleteById", p, body). + return new MethodRef(PUBLIC | STATIC, TypeRef.VOID, "delete" + type.className + "ById", p, body). exception(imports.add(SQLException.class)); } public ClassG queryType(Imports imports) { - TypeRef abstractQueryType = imports.add(AbstractTypedQuery.class).args(type); + TypeRef sqlQueryType = imports.add(AbstractTypedQuery.class).args(type); TypeRef conType = imports.add(Connection.class); TypeRef entityTypedQuery = new TypeRef(type.className + "TypedQuery"); + TypeRef sqlExceptionType = new TypeRef(SQLException.class); Parameters p = new Parameters(); ParameterRef c = p.addParameter(conType, "c"); - - ClassG typedQuery = new ClassG(PUBLIC | STATIC, entityTypedQuery). - extendsType(abstractQueryType); - typedQuery.addConstructor(p, singletonList("super(" + c.name + ", " + daoType.className + ".desc);")); - return typedQuery; + Constructor constructor = new Constructor(p, singletonList("super(" + c.name + ", " + daoType.className + ".desc);")); + ClassG g = new ClassG(PUBLIC | STATIC, entityTypedQuery). + extendsType(sqlQueryType). + add(constructor); + p = new Parameters(); + ParameterRef rs = p.addParameter(new TypeRef(ResultSet.class), "rs"); + MethodRef fromResultSet = new MethodRef(PUBLIC, type, "fromResultSet", p, + "return " + utilsType.className + ".fromResultSet" + type.className + "(" + rs.name + ");"). + exception(sqlExceptionType); + g.add(fromResultSet); + return g; } public MethodRef query(Imports imports) { @@ -258,10 +287,8 @@ public class EntityMirror implements Comparable { Parameters p = new Parameters(); ParameterRef c = p.addParameter(conType, "c"); - - List body = new ArrayList<>(); - body.add("return new " + entityTypedQuery + "(" + c.name + ");"); - return new MethodRef(PUBLIC | STATIC, typedQueryType, "query", p, body); + return new MethodRef(PUBLIC | STATIC, typedQueryType, "query" + type.className, p, + "return new " + entityTypedQuery + "(" + c.name + ");"); } public MethodRef fromResultSet(Imports g) { @@ -313,7 +340,7 @@ public class EntityMirror implements Comparable { body.add("return returnValue;"); - return new MethodRef(PUBLIC, type, "fromResultSet", p, body). + return new MethodRef(PUBLIC | STATIC, type, "fromResultSet" + type.className, p, body). exception(g.add(SQLException.class)); } @@ -336,4 +363,16 @@ public class EntityMirror implements Comparable { public int compareTo(@SuppressWarnings("NullableProblems") EntityMirror o) { return type.compareTo(o.type); } + + public ClassG utils(SqlUnitModel unit) { + ClassG g = new ClassG(PUBLIC | STATIC, utilsType); + g.add(insertInto(unit, g.imports)); + g.add(selectById(g.imports)); + g.add(update(g.imports)); + g.add(delete(g.imports)); + g.add(deleteById(g.imports)); + g.add(query(g.imports)); + g.add(fromResultSet(g.imports)); + return g; + } } diff --git a/container-compiler-plugin/src/main/java/io/trygvis/persistence/SqlEntitySet.java b/container-compiler-plugin/src/main/java/io/trygvis/persistence/SqlEntitySet.java index 69176f8..455e3cd 100644 --- a/container-compiler-plugin/src/main/java/io/trygvis/persistence/SqlEntitySet.java +++ b/container-compiler-plugin/src/main/java/io/trygvis/persistence/SqlEntitySet.java @@ -1,4 +1,5 @@ package io.trygvis.persistence; public @interface SqlEntitySet { + String name(); } diff --git a/container-compiler-plugin/src/main/java/io/trygvis/persistence/generators/EntityManagerFactoryGenerator.java b/container-compiler-plugin/src/main/java/io/trygvis/persistence/generators/EntityManagerFactoryGenerator.java new file mode 100644 index 0000000..82e69e3 --- /dev/null +++ b/container-compiler-plugin/src/main/java/io/trygvis/persistence/generators/EntityManagerFactoryGenerator.java @@ -0,0 +1,69 @@ +package io.trygvis.persistence.generators; + +import io.trygvis.container.compiler.SqlUnitModel; +import io.trygvis.container.compiler.model.ClassG; +import io.trygvis.container.compiler.model.Constructor; +import io.trygvis.container.compiler.model.FieldRef; +import io.trygvis.container.compiler.model.Imports; +import io.trygvis.container.compiler.model.MethodRef; +import io.trygvis.container.compiler.model.Parameters; +import io.trygvis.container.compiler.model.TypeRef; +import io.trygvis.persistence.EntityMirror; +import io.trygvis.persistence.sql.SqlEntityManagerFactory; +import io.trygvis.persistence.sql.SqlEntityMeta; +import io.trygvis.persistence.sql.SqlUnit; + +import javax.persistence.EntityManager; +import javax.sql.DataSource; +import java.io.IOException; +import java.sql.Connection; +import java.util.ArrayList; +import java.util.List; + +import static io.trygvis.container.compiler.Utils.toClassName; +import static java.lang.reflect.Modifier.*; +import static org.apache.commons.lang.StringUtils.join; + +public class EntityManagerFactoryGenerator { + public static ClassG generateEntityManagerFactory(SqlUnitModel unit) throws IOException { + String prefix = unit.getPackageName() + "." + toClassName(unit.getName()); + TypeRef emfType = new TypeRef(prefix + "EntityManagerFactory"); + + ClassG g = new ClassG(PUBLIC, emfType). + extendsType(SqlEntityManagerFactory.class); + + List s = new ArrayList<>(); + for (EntityMirror entity : unit.getEntities().values()) { + s.add(entity.daoType.plainName + ".desc"); + } + TypeRef sqlEntityMetaArrayType = new TypeRef(SqlEntityMeta[].class); + FieldRef entities = g.addField(PUBLIC | STATIC, sqlEntityMetaArrayType, "entities"). + value("new " + sqlEntityMetaArrayType + "{" + join(s, ", ") + "}"); + + g.add(constructor(entities, g.imports)); + g.add(createEntityManager(unit, g.imports)); + return g; + } + + private static Constructor constructor(FieldRef entities, Imports imports) { + TypeRef dataSourceType = imports.add(DataSource.class); + TypeRef sqlUnitType = imports.add(SqlUnit.class); + Parameters p = new Parameters(); + Parameters.ParameterRef ds = p.addParameter(dataSourceType, "ds"); + ArrayList body = new ArrayList<>(); + body.add("super(new " + sqlUnitType.plainName + "(" + entities.name + "), " + ds.name + ");"); + return new Constructor(p, body); + } + + private static MethodRef createEntityManager(SqlUnitModel unit, Imports imports) { + String prefix = unit.getPackageName() + "." + toClassName(unit.getName()); + TypeRef entityManagerType = imports.add(EntityManager.class); + TypeRef connectionType = imports.add(Connection.class); + TypeRef emType = imports.add(new TypeRef(prefix + "EntityManager")); + + Parameters p = new Parameters(); + Parameters.ParameterRef c = p.addParameter(connectionType, "c"); + return new MethodRef(PROTECTED, entityManagerType, "createEntityManager", p, + "return new " + emType + "(this, " + c.name + ");"); + } +} diff --git a/container-compiler-plugin/src/main/java/io/trygvis/persistence/generators/EntityManagerGenerator.java b/container-compiler-plugin/src/main/java/io/trygvis/persistence/generators/EntityManagerGenerator.java new file mode 100644 index 0000000..f524b1a --- /dev/null +++ b/container-compiler-plugin/src/main/java/io/trygvis/persistence/generators/EntityManagerGenerator.java @@ -0,0 +1,129 @@ +package io.trygvis.persistence.generators; + +import io.trygvis.container.compiler.SqlUnitModel; +import io.trygvis.container.compiler.model.ClassG; +import io.trygvis.container.compiler.model.Constructor; +import io.trygvis.container.compiler.model.FieldRef; +import io.trygvis.container.compiler.model.Imports; +import io.trygvis.container.compiler.model.MethodRef; +import io.trygvis.container.compiler.model.Parameters; +import io.trygvis.container.compiler.model.TypeRef; +import io.trygvis.persistence.EntityMirror; +import io.trygvis.persistence.sql.SqlDao; +import io.trygvis.persistence.sql.SqlEntityManager; +import io.trygvis.persistence.sql.SqlEntityManagerFactory; + +import java.io.IOException; +import java.sql.Connection; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static io.trygvis.container.compiler.Utils.toClassName; +import static io.trygvis.container.compiler.Utils.toFieldName; +import static io.trygvis.container.compiler.model.Parameters.ParameterRef; +import static java.lang.reflect.Modifier.PUBLIC; + +public class EntityManagerGenerator { + public static ClassG generateEntityManager(SqlUnitModel unit) throws IOException { + String prefix = unit.getPackageName() + "." + toClassName(unit.getName()); + TypeRef emType = new TypeRef(prefix + "EntityManager"); + + ClassG g = new ClassG(PUBLIC, emType). + extendsType(SqlEntityManager.class); + + Map daoFields = new HashMap<>(); + for (EntityMirror entity : unit.getEntities().values()) { + daoFields.put(entity, g.addField(entity.daoType, toFieldName(entity.type.className))); + } + + g.add(constructor(unit, g.imports, daoFields)); + g.add(getSqlDao(unit, g.imports, daoFields)); + + return g; + } + + private static Constructor constructor(SqlUnitModel unit, Imports imports, Map daoFields) { + Parameters p = new Parameters(); + ParameterRef semf = p.addParameter(imports.add(SqlEntityManagerFactory.class), "emf"); + ParameterRef c = p.addParameter(imports.add(Connection.class), "c"); + List body = new ArrayList<>(); + body.add("super(" + semf.name + ", " + c.name + ");"); + + for (EntityMirror entity : unit.getEntities().values()) { + FieldRef f = daoFields.get(entity); + body.add("this." + f.name + " = new " + entity.daoType.plainName + "(" + c.name + ");"); + } + return new Constructor(p, body); + } + + public static MethodRef getSqlDao(SqlUnitModel unit, Imports imports, Map daoFields) { + TypeRef sqlDatoType = imports.add(new TypeRef(SqlDao.class)).args("Id", "T"); + Parameters p = new Parameters(); + TypeRef klassType = new TypeRef(Class.class).args("T"); + ParameterRef klass = p.addParameter(klassType, "klass"); + List body = new ArrayList<>(); + for (EntityMirror entity : unit.getEntities().values()) { + body.add("if (klass == " + entity.type.plainName + ".class) {"); + body.add(" @SuppressWarnings(\"unchecked\")"); + body.add(" SqlDao dao = (SqlDao) " + daoFields.get(entity).name + ";"); + body.add(" return (SqlDao) dao;"); + body.add("}"); + } + body.add("throw new RuntimeException(\"Type is not a part of this persistence unit: \" + klass);"); + return new MethodRef(PUBLIC, sqlDatoType, "getDao", p, body).typeArgs("Id", "T"); + } + + /* + public static ClassG sem(EntityMirror entity) { + ClassG g = new ClassG(PUBLIC, new TypeRef(entity.type.className + "SEM")); + g.implementsType(g.imports.add(new TypeRef(SqlDao.class)).args(entity.idType, entity.type)); + return g. + add(semFind(entity, g.imports)). + add(semPersist(entity, g.imports)). + add(semMerge(entity, g.imports)). + add(semRemove(entity, g.imports)); + } + + public static MethodRef semFind(EntityMirror entity, Imports imports) { + TypeRef type = imports.add(entity.type); + TypeRef sqlException = imports.add(SQLException.class); + Parameters p = new Parameters(); + ParameterRef primaryKey = p.addParameter(new TypeRef(Object.class), "primaryKey"); + List body = new ArrayList<>(); + body.add("throw new " + sqlException.plainName + "(\"Not implemented\");"); + return new MethodRef(PUBLIC, type, "find", p, tryCatchSqlException(imports, body)); + } + + public static MethodRef semPersist(EntityMirror entity, Imports imports) { + TypeRef type = imports.add(entity.type); + TypeRef dao = imports.add(entity.daoType); + Parameters p = new Parameters(); + ParameterRef e = p.addParameter(type, "entity"); + List body = new ArrayList<>(); + body.add(dao.plainName + ".insertInto(currentConnection(), " + e.name + ");"); + return new MethodRef(PUBLIC, VOID, "persist", p, tryCatchSqlException(imports, body)); + } + + public static MethodRef semMerge(EntityMirror entity, Imports imports) { + TypeRef type = imports.add(entity.type); + TypeRef sqlException = imports.add(SQLException.class); + Parameters p = new Parameters(); + ParameterRef e = p.addParameter(type, "entity"); + List body = new ArrayList<>(); + body.add("throw new " + sqlException.plainName + "(\"Not implemented\");"); + return new MethodRef(PUBLIC, type, "merge", p, tryCatchSqlException(imports, body)); + } + + public static MethodRef semRemove(EntityMirror entity, Imports imports) { + TypeRef type = imports.add(entity.type); + TypeRef sqlException = imports.add(SQLException.class); + Parameters p = new Parameters(); + ParameterRef e = p.addParameter(type, "entity"); + List body = new ArrayList<>(); + body.add("throw new " + sqlException.plainName + "(\"Not implemented\");"); + return new MethodRef(PUBLIC, VOID, "remove", p, tryCatchSqlException(imports, body)); + } + */ +} diff --git a/container-compiler-plugin/src/main/java/io/trygvis/persistence/generators/SequencesGenerator.java b/container-compiler-plugin/src/main/java/io/trygvis/persistence/generators/SequencesGenerator.java new file mode 100644 index 0000000..07823af --- /dev/null +++ b/container-compiler-plugin/src/main/java/io/trygvis/persistence/generators/SequencesGenerator.java @@ -0,0 +1,41 @@ +package io.trygvis.persistence.generators; + +import io.trygvis.container.compiler.SqlUnitModel; +import io.trygvis.container.compiler.model.ClassG; +import io.trygvis.container.compiler.model.FieldRef; +import io.trygvis.container.compiler.model.TypeRef; +import io.trygvis.persistence.SequenceMirror; + +import java.util.ArrayList; +import java.util.List; + +import static io.trygvis.container.compiler.Utils.toJavaString; +import static java.lang.reflect.Modifier.PUBLIC; +import static org.apache.commons.lang.StringUtils.capitalize; +import static org.apache.commons.lang.StringUtils.join; + +public class SequencesGenerator { + public static ClassG generateSequences(SqlUnitModel unit) { + TypeRef sequences = new TypeRef(unit.getPackageName() + ".Sequences"); + ClassG g = new ClassG(PUBLIC, sequences); + 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.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), "createSequences"). + value("new String[]{" + join(creates, ", ") + "}"); + g.addPublicStaticFinalField(new TypeRef(String[].class), "dropSequences"). + value("new String[]{" + join(drops, ", ") + "}"); + return g; + } +} -- cgit v1.2.3