From e1cf8889628d2d31cf7067b8c002f229fc22007d Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Sat, 3 Aug 2013 18:00:10 +0200 Subject: wip --- .../trygvis/container/compiler/EntityHandler.java | 36 ++++++------- .../container/compiler/TransactionalHandler.java | 2 +- .../java/io/trygvis/container/compiler/Utils.java | 25 +++++++++ .../trygvis/container/compiler/model/ClassG.java | 63 +++++++++------------- .../container/compiler/model/Constructor.java | 2 +- .../trygvis/container/compiler/model/TypeRef.java | 56 ++++++++++++++----- .../java/io/trygvis/persistence/EntityMirror.java | 49 ++++++++++++++--- .../java/io/trygvis/persistence/FieldMirror.java | 22 ++++---- .../io/trygvis/persistence/GeneratorSupport.java | 31 ++++++----- .../java/io/trygvis/persistence/TypeHandler.java | 22 ++++++++ .../io/trygvis/persistence/EntityMirrorTest.java | 47 ++++++++++++++++ .../persistence/test/PersonTypeHandler.java | 5 ++ .../io/trygvis/container/myapp/AddressBook.java | 47 ++++++++++++++-- 13 files changed, 295 insertions(+), 112 deletions(-) create mode 100644 container-compiler-plugin/src/test/java/io/trygvis/persistence/EntityMirrorTest.java 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 ad36988..cf21887 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 @@ -1,6 +1,7 @@ package io.trygvis.container.compiler; import io.trygvis.container.compiler.model.ClassG; +import io.trygvis.container.compiler.model.TypeRef; import io.trygvis.persistence.EntityMirror; import io.trygvis.persistence.FieldMirror; import io.trygvis.persistence.GeneratorSupport; @@ -14,7 +15,6 @@ import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.PackageElement; import javax.lang.model.element.TypeElement; import javax.lang.model.element.VariableElement; -import javax.lang.model.type.DeclaredType; import javax.lang.model.type.TypeMirror; import javax.persistence.Id; import javax.tools.JavaFileObject; @@ -24,6 +24,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import static io.trygvis.container.compiler.Utils.toJavaString; import static io.trygvis.persistence.FieldMirror.PrimitiveFieldMirror; import static java.lang.Character.isUpperCase; import static javax.lang.model.util.ElementFilter.fieldsIn; @@ -47,7 +48,7 @@ public class EntityHandler extends AbstractHandler { TypeHandler typeHandler = (TypeHandler) typeHandlerClass.newInstance(); String type = entity.asType().toString(); - generatorSupport.addTypeHandler(type, typeHandler); + generatorSupport.addTypeHandler(new TypeRef(type, type), typeHandler); System.out.println("Loaded TypeHandler for " + type + " through " + typeHandlerClass.getCanonicalName()); break; } @@ -78,8 +79,8 @@ public class EntityHandler extends AbstractHandler { } public void processEntity(TypeElement element) throws Exception { - DeclaredType declaredType = types.getDeclaredType(element); - EntityMirror entityMirror = new EntityMirror(generatorSupport, declaredType, sqlName(element.getSimpleName().toString())); + EntityMirror entityMirror = new EntityMirror(generatorSupport, new TypeRef(types.getDeclaredType(element)), + sqlName(element.getSimpleName().toString())); for (VariableElement f : fieldsIn(elements.getAllMembers(element))) { entityMirror.add(fromElement(generatorSupport, f)); @@ -101,16 +102,14 @@ public class EntityHandler extends AbstractHandler { String p = elements.getPackageOf(element).getQualifiedName().toString(); - ClassG g = new ClassG(p, entityMirror.daoName); - String insertInto = entityMirror.insertIntoSql(); - g.addPublicStaticFinalField(String.class, "insertIntoSql").value("\"" + insertInto + "\""); -// List body = new ArrayList<>(); -// body.add("this.insertIntoSql = \"" + insertInto + "\";"); -// g.addConstructor(new Parameters(), body); + ClassG g = new ClassG(entityMirror.daoType); + g.addPublicStaticFinalField(String.class, "createTableSql").value(toJavaString(entityMirror.createTableSql())); + g.addPublicStaticFinalField(String.class, "dropTableSql").value(toJavaString(entityMirror.dropTableSql())); + g.addPublicStaticFinalField(String.class, "insertIntoSql").value(toJavaString(entityMirror.insertIntoSql())); + g.addPublicStaticFinalField(String.class, "deleteFromSql").value(toJavaString(entityMirror.deleteFromSql())); entityMirror.insertInto(g); - String fileName = (p.length() == 0 ? "" : p + ".") + entityMirror.daoName; - JavaFileObject sourceFile = processingEnv.getFiler().createSourceFile(fileName, element); + JavaFileObject sourceFile = processingEnv.getFiler().createSourceFile(entityMirror.daoType.fqName, element); try (PrintWriter w = new PrintWriter(sourceFile.openWriter())) { g.write(w); } @@ -119,7 +118,7 @@ public class EntityHandler extends AbstractHandler { } public FieldMirror fromElement(GeneratorSupport generatorSupport, VariableElement var) { - TypeMirror type = var.asType(); + TypeRef type = new TypeRef(var.asType().toString()); // System.out.print("element = "); // elements.printElements(new PrintWriter(System.out), var); String javaName = var.getSimpleName().toString(); @@ -128,13 +127,13 @@ public class EntityHandler extends AbstractHandler { FieldMirror field; boolean id = isId(var); if (generatorSupport.isPrimitive(type)) { - field = new PrimitiveFieldMirror(var, javaName, sqlName, id, notNull); + field = new PrimitiveFieldMirror(type, javaName, sqlName, id, notNull); } else if (generatorSupport.hasTypeHandler(type)) { if (id) { throw new CompilerException(var, "A @Id field has to be a primitive or embedded."); } - field = new FieldMirror.ReferenceFieldMirror(var, javaName, sqlName, notNull); + field = new FieldMirror.ReferenceFieldMirror(type, javaName, sqlName, notNull); } else { throw new CompilerException(var, "Missing type handler for type: " + type); } @@ -151,10 +150,9 @@ public class EntityHandler extends AbstractHandler { String p = packageElement.getQualifiedName().toString(); // TODO: Support a name prefix from @SqlEntitySet - String className = "Daos"; + TypeRef type = new TypeRef(p + ".Daos"); - String fileName = (p.length() == 0 ? "" : p + ".") + className; - ClassG g = new ClassG(p, className); + ClassG g = new ClassG(type); /* TypeRef conType = g.addImport(Connection.class); @@ -170,7 +168,7 @@ public class EntityHandler extends AbstractHandler { g.addConstructor(parameters, body); */ - JavaFileObject sourceFile = processingEnv.getFiler().createSourceFile(fileName, packageElement); + JavaFileObject sourceFile = processingEnv.getFiler().createSourceFile(type.fqName, packageElement); try (PrintWriter w = new PrintWriter(sourceFile.openWriter())) { g.write(w); } diff --git a/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/TransactionalHandler.java b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/TransactionalHandler.java index d24a697..fbd7660 100644 --- a/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/TransactionalHandler.java +++ b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/TransactionalHandler.java @@ -42,7 +42,7 @@ public class TransactionalHandler extends AbstractHandler { String p = elements.getPackageOf(element).getQualifiedName().toString(); - ClassG g = new ClassG(p, className, targetClassName.toString()); + ClassG g = new ClassG(new TypeRef(p + "." + className), new TypeRef(targetClassName.toString())); FieldRef transactionManager = g.addField(PlatformTransactionManager.class, "transactionManager"); for (ExecutableElement constructor : constructorsIn(elements.getAllMembers(element))) { diff --git a/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/Utils.java b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/Utils.java index 8bd0de3..5057968 100644 --- a/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/Utils.java +++ b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/Utils.java @@ -1,5 +1,9 @@ package io.trygvis.container.compiler; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.StringReader; + import static java.lang.Character.toLowerCase; import static java.lang.Character.toUpperCase; @@ -28,4 +32,25 @@ public class Utils { } return new String(chars, 0, j); } + + public static String toJavaString(String s) { + try { + BufferedReader reader = new BufferedReader(new StringReader(s)); + String line = reader.readLine(); + StringBuilder buffer = new StringBuilder(); + while (line != null) { + buffer.append('"'); + buffer.append(line.replace("\"", "\\\"")); + buffer.append('"'); + line = reader.readLine(); + if(line != null) { + buffer.append(" +\n"); + } + } + + return buffer.toString(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } } diff --git a/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/model/ClassG.java b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/model/ClassG.java index 9befa36..857311d 100644 --- a/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/model/ClassG.java +++ b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/model/ClassG.java @@ -12,58 +12,46 @@ import static java.lang.reflect.Modifier.*; import static org.springframework.util.StringUtils.collectionToDelimitedString; public class ClassG { - private final String packageName; - public final String className; - private final String extendsClass; + public final TypeRef type; + private final TypeRef extendsClass; private final Set imports = new TreeSet<>(); private final Set fields = new TreeSet<>(); private final List methods = new ArrayList<>(); private final List constructors = new ArrayList<>(); - public ClassG(String packageName, String className) { - this(packageName, className, null); + public ClassG(TypeRef type) { + this(type, null); } - public ClassG(String packageName, String className, String extendsClass) { - this.packageName = packageName; - this.className = className; + public ClassG(TypeRef type, TypeRef extendsClass) { + this.type = type; this.extendsClass = extendsClass; } public TypeRef addImport(final TypeMirror type) { - if (type.getKind().isPrimitive()) { - return TypeRef.find(type.getKind()); - } - - String canonicalName = type.toString(); - - for (TypeRef i : imports) { - if (i.canonicalName().equals(canonicalName)) { - return i; - } - } + return addImport(new TypeRef(type)); + } - TypeRef ref = new TypeRef(canonicalName, canonicalName); - imports.add(ref); - return ref; + public TypeRef addImport(Class c) { + return addImport(new TypeRef(c)); } - public TypeRef addImport(Class klass) { - String canonicalName = klass.getCanonicalName(); - String simpleName = klass.getSimpleName(); - String name = simpleName; + public TypeRef addImport(TypeRef klass) { + String fqName = klass.fqName; + String name = klass.name; for (TypeRef i : imports) { - if (i.canonicalName().equals(canonicalName)) { + if (i.fqName.equals(fqName)) { return i; } - if (i.name.equals(simpleName)) { - name = canonicalName; + // If we've already found an import with the same name, use the fq version + if (i.name.equals(name)) { + name = fqName; break; } } - TypeRef ref = new TypeRef(name, canonicalName); + TypeRef ref = new TypeRef(name, fqName); imports.add(ref); return ref; @@ -114,26 +102,23 @@ public class ClassG { } public void write(PrintWriter writer) { - if (packageName.length() > 0) { - writer.println("package " + packageName + ";"); + if (!type.inUnnamedPackage()) { + writer.println("package " + type.packageName() + ";"); writer.println(); } for (TypeRef i : imports) { - if (i.isPrimitive()) { - continue; - } - if (i.canonicalName().indexOf('.') == -1) { + if (i.isPrimitive() || i.inUnnamedPackage()) { continue; } - writer.println("import " + i.canonicalName() + ";"); + writer.println("import " + i.fqName + ";"); } if (!imports.isEmpty()) { writer.println(); } - String extendsString = extendsClass == null ? "" : " extends " + extendsClass; + String extendsString = extendsClass == null ? "" : " extends " + extendsClass.name; - writer.println("public class " + className + extendsString + " {"); + writer.println("public class " + type.className + extendsString + " {"); for (FieldRef field : fields) { writer.println(); writer.println(" " + field.toJava() + ";"); diff --git a/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/model/Constructor.java b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/model/Constructor.java index 43800ce..f669273 100644 --- a/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/model/Constructor.java +++ b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/model/Constructor.java @@ -27,7 +27,7 @@ public class Constructor { String params = collectionToDelimitedString(ps, ", "); - body.add(" public " + g.className + "(" + params + ") {"); + body.add(" public " + g.type.className + "(" + params + ") {"); for (String s : this.body) { body.add(" " + s); } diff --git a/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/model/TypeRef.java b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/model/TypeRef.java index aabfb45..c6f958a 100644 --- a/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/model/TypeRef.java +++ b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/model/TypeRef.java @@ -1,6 +1,7 @@ package io.trygvis.container.compiler.model; import javax.lang.model.type.TypeKind; +import javax.lang.model.type.TypeMirror; public class TypeRef implements Comparable { @@ -15,27 +16,56 @@ public class TypeRef implements Comparable { public static final TypeRef DOUBLE = new TypeRef("double", null); /** - * The name of a class used within a class file. Is either the simple name or the canonical name. + * The name of a class used within a class file. Is either the just the name or the fully qualified name. */ public final String name; - private final String canonicalName; + public final String className; - public String canonicalName() { - if (canonicalName == null) { - throw new RuntimeException("This type doesn't have a canonical name"); + public final String fqName; + private final boolean primitive; + + public TypeRef(String name, String fqName) { + this.name = name; + this.primitive = fqName == null; + this.fqName = fqName == null ? name : fqName; + + int i = this.fqName.lastIndexOf('.'); + if (i == -1) { + this.className = this.fqName; + } else { + this.className = this.fqName.substring(i + 1, this.fqName.length()); } + } + + public TypeRef(TypeMirror type) { + this(type.toString()); + } + + public TypeRef(Class klass) { + this(klass.getCanonicalName(), klass.getCanonicalName()); + } - return canonicalName; + public TypeRef(String fqName) { + this(fqName, fqName); } public boolean isPrimitive() { - return canonicalName == null; + return primitive; } - public TypeRef(String name, String canonicalName) { - this.name = name; - this.canonicalName = canonicalName; + public boolean inUnnamedPackage() { + return fqName.indexOf('.') == -1; + } + + public String packageName() { + int i = fqName.lastIndexOf('.'); + + if (i == -1) { + throw new RuntimeException("This type is in the unnamed package: " + name); + } + + return fqName.substring(0, i); } @Override @@ -45,17 +75,17 @@ public class TypeRef implements Comparable { TypeRef classRef = (TypeRef) o; - return canonicalName.equals(classRef.canonicalName); + return fqName.equals(classRef.fqName); } @Override public int hashCode() { - return canonicalName.hashCode(); + return fqName.hashCode(); } @Override public int compareTo(TypeRef o) { - return canonicalName.compareTo(o.canonicalName); + return fqName.compareTo(o.fqName); } public static TypeRef find(TypeKind kind) { 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 41ae1d4..2a4952f 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 @@ -4,32 +4,56 @@ 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.DeclaredType; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; +import static java.lang.String.format; import static org.apache.commons.lang.StringUtils.join; public class EntityMirror { public final GeneratorSupport generatorSupport; public final List fields = new ArrayList<>(); - public final DeclaredType javaName; + public final List idFields = new ArrayList<>(); + public final TypeRef type; public final String tableName; - public final String daoName; + public final TypeRef daoType; - public EntityMirror(GeneratorSupport generatorSupport, DeclaredType javaName, String tableName) { + public EntityMirror(GeneratorSupport generatorSupport, TypeRef type, String tableName) { this.generatorSupport = generatorSupport; - this.javaName = javaName; + this.type = type; this.tableName = tableName; - this.daoName = javaName.asElement().getSimpleName() + "Dao"; + this.daoType = new TypeRef(type.name + "Dao"); } public void add(FieldMirror field) { fields.add(field); + if(field.id) { + idFields.add(field); + } + } + + public String createTableSql() { + List columns = new ArrayList<>(); + for (FieldMirror field : fields) { + TypeHandler typeHandler = generatorSupport.typeHandler(field.type); + String s = " " + field.sqlName + " " + typeHandler.sqlType(field); + if(field.id) { + s += " PRIMARY KEY"; + } + columns.add(s); + } + + return format("CREATE TABLE " + tableName + "(%n" + + join(columns, ",%n") + + "%n);"); + } + + public String dropTableSql() { + return "DROP TABLE " + tableName + ";"; } public String insertIntoSql() { @@ -44,10 +68,19 @@ public class EntityMirror { "VALUES(" + join(placeholders, ", ") + ");"; } + public String deleteFromSql() { + List ss = new ArrayList<>(); + for (FieldMirror field : idFields) { + ss.add(field.sqlName + "=?"); + } + + return "DELETE FROM " + tableName + " WHERE " + join(ss, " AND ") + ";"; + } + public void insertInto(ClassG g) { TypeRef conType = g.addImport(Connection.class); TypeRef psType = g.addImport(PreparedStatement.class); - TypeRef objectType = g.addImport(javaName); + TypeRef objectType = g.addImport(type); ParameterRef con = new ParameterRef(conType, "con"); ParameterRef object = new ParameterRef(objectType, "o"); @@ -56,7 +89,7 @@ public class EntityMirror { 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); + TypeHandler typeHandler = generatorSupport.typeHandler(field.type); body.add(" stmt." + typeHandler.resultSetSetter(i + 1, "o", field) + ";"); } body.add(" stmt.executeUpdate();"); 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 index c2e5f35..bf0a0c3 100644 --- a/container-compiler-plugin/src/main/java/io/trygvis/persistence/FieldMirror.java +++ b/container-compiler-plugin/src/main/java/io/trygvis/persistence/FieldMirror.java @@ -1,6 +1,6 @@ package io.trygvis.persistence; -import javax.lang.model.element.VariableElement; +import io.trygvis.container.compiler.model.TypeRef; import static io.trygvis.persistence.FieldMirror.FieldType.PRIMITIVE; import static io.trygvis.persistence.FieldMirror.FieldType.REFERENCE; @@ -10,7 +10,7 @@ import static io.trygvis.persistence.FieldMirror.FieldType.REFERENCE; */ public abstract class FieldMirror { public final FieldType fieldType; - public final VariableElement element; + public final TypeRef type; public final String javaName; public final String sqlName; public final boolean id; @@ -21,9 +21,9 @@ public abstract class FieldMirror { REFERENCE, } - protected FieldMirror(FieldType fieldType, VariableElement element, String javaName, String sqlName, boolean id, boolean notNull) { + protected FieldMirror(FieldType fieldType, TypeRef type, String javaName, String sqlName, boolean id, boolean notNull) { this.fieldType = fieldType; - this.element = element; + this.type = type; this.javaName = javaName; this.sqlName = sqlName; this.id = id; @@ -31,14 +31,15 @@ public abstract class FieldMirror { } public static class PrimitiveFieldMirror extends FieldMirror { - public PrimitiveFieldMirror(VariableElement element, String javaName, String sqlName, boolean id, boolean notNull) { - super(PRIMITIVE, element, javaName, sqlName, id, notNull); + public PrimitiveFieldMirror(TypeRef typeRef, String javaName, String sqlName, boolean id, boolean notNull) { + super(PRIMITIVE, typeRef, javaName, sqlName, id, notNull); } @Override public String toString() { return "PrimitiveFieldMirror{" + - "javaName='" + javaName + '\'' + + "type='" + type + '\'' + + ", javaName='" + javaName + '\'' + ", sqlName='" + sqlName + '\'' + ", notNull=" + notNull + '}'; @@ -46,14 +47,15 @@ public abstract class FieldMirror { } public static class ReferenceFieldMirror extends FieldMirror { - public ReferenceFieldMirror(VariableElement element, String javaName, String sqlName, boolean notNull) { - super(REFERENCE, element, javaName, sqlName, false, notNull); + public ReferenceFieldMirror(TypeRef typeRef, String javaName, String sqlName, boolean notNull) { + super(REFERENCE, typeRef, javaName, sqlName, false, notNull); } @Override public String toString() { return "ReferenceFieldMirror{" + - "javaName='" + javaName + '\'' + + "type='" + type + '\'' + + ", javaName='" + javaName + '\'' + ", sqlName='" + sqlName + '\'' + ", notNull=" + notNull + '}'; 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 index 379f6f6..0563691 100644 --- a/container-compiler-plugin/src/main/java/io/trygvis/persistence/GeneratorSupport.java +++ b/container-compiler-plugin/src/main/java/io/trygvis/persistence/GeneratorSupport.java @@ -1,42 +1,41 @@ package io.trygvis.persistence; -import javax.lang.model.element.Element; -import javax.lang.model.type.TypeMirror; +import io.trygvis.container.compiler.model.TypeRef; + import java.util.Date; -import java.util.HashMap; import java.util.Map; +import java.util.TreeMap; public class GeneratorSupport { - private final Map primitiveTypeHandlers = new HashMap<>(); - private final Map typeHandlers = new HashMap<>(); + private final Map primitiveTypeHandlers = new TreeMap<>(); + private final Map typeHandlers = new TreeMap<>(); { - typeHandlers.put(Integer.class.getName(), new TypeHandler.IntTypeHandler()); - typeHandlers.put(Long.class.getName(), new TypeHandler.LongTypeHandler()); - typeHandlers.put(String.class.getName(), new TypeHandler.StringTypeHandler()); - typeHandlers.put(Date.class.getName(), new TypeHandler.DateTypeHandler()); + typeHandlers.put(new TypeRef(Integer.class), new TypeHandler.IntTypeHandler()); + typeHandlers.put(new TypeRef(Long.class), new TypeHandler.LongTypeHandler()); + typeHandlers.put(new TypeRef(String.class), new TypeHandler.StringTypeHandler()); + typeHandlers.put(new TypeRef(Date.class), new TypeHandler.DateTypeHandler()); primitiveTypeHandlers.putAll(typeHandlers); } - public void addTypeHandler(String type, TypeHandler typeHandler) { + public void addTypeHandler(TypeRef type, TypeHandler typeHandler) { typeHandlers.put(type, typeHandler); } - public TypeHandler typeHandler(Element element) { - String type = element.asType().toString(); + public TypeHandler typeHandler(TypeRef type) { 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 isPrimitive(TypeRef type) { + return primitiveTypeHandlers.containsKey(type); } - public boolean hasTypeHandler(TypeMirror type) { - return typeHandlers.containsKey(type.toString()); + public boolean hasTypeHandler(TypeRef type) { + return typeHandlers.containsKey(type); } } 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 index 1d7d424..ff2ad0a 100644 --- a/container-compiler-plugin/src/main/java/io/trygvis/persistence/TypeHandler.java +++ b/container-compiler-plugin/src/main/java/io/trygvis/persistence/TypeHandler.java @@ -3,11 +3,18 @@ package io.trygvis.persistence; public interface TypeHandler { String resultSetSetter(int i, String o, FieldMirror field); + String sqlType(FieldMirror field); + public static class IntTypeHandler implements TypeHandler { @Override public String resultSetSetter(int i, String o, FieldMirror field) { return "setInt(" + i + ", " + o + "." + field.javaName + ")"; } + + @Override + public String sqlType(FieldMirror field) { + return "INTEGER"; + } } public static class LongTypeHandler implements TypeHandler { @@ -15,6 +22,11 @@ public interface TypeHandler { public String resultSetSetter(int i, String o, FieldMirror field) { return "setLong(" + i + ", " + o + "." + field.javaName + ")"; } + + @Override + public String sqlType(FieldMirror field) { + return "BIGINT"; + } } public static class StringTypeHandler implements TypeHandler { @@ -22,6 +34,11 @@ public interface TypeHandler { public String resultSetSetter(int i, String o, FieldMirror field) { return "setString(" + i + ", " + o + "." + field.javaName + ")"; } + + @Override + public String sqlType(FieldMirror field) { + return "VARCHAR(1000)"; + } } public static class DateTypeHandler implements TypeHandler { @@ -29,5 +46,10 @@ public interface TypeHandler { public String resultSetSetter(int i, String o, FieldMirror field) { return "setTimestamp(" + i + ", new java.sql.Timestamp(" + o + "." + field.javaName + ".getTime()))"; } + + @Override + public String sqlType(FieldMirror field) { + return "TIMESTAMP"; + } } } diff --git a/container-compiler-plugin/src/test/java/io/trygvis/persistence/EntityMirrorTest.java b/container-compiler-plugin/src/test/java/io/trygvis/persistence/EntityMirrorTest.java new file mode 100644 index 0000000..33db82b --- /dev/null +++ b/container-compiler-plugin/src/test/java/io/trygvis/persistence/EntityMirrorTest.java @@ -0,0 +1,47 @@ +package io.trygvis.persistence; + +import io.trygvis.container.compiler.model.TypeRef; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static io.trygvis.persistence.FieldMirror.PrimitiveFieldMirror; +import static java.lang.String.format; +import static org.testng.Assert.assertEquals; + +public class EntityMirrorTest { + + static FieldMirror idLong = new PrimitiveFieldMirror(new TypeRef(Long.class), "id", "id", true, false); + static FieldMirror idString = new PrimitiveFieldMirror(new TypeRef(String.class), "id", "id", true, false); + + @DataProvider(name = "insertIntoSql", parallel = true) + public static Object[][] insertIntoProvider() { + return new Object[][]{ + new Object[]{ + new FieldMirror[]{idString}, + "INSERT INTO my_table(id) VALUES(?);", + "DELETE FROM my_table WHERE id=?;", format( + "CREATE TABLE my_table(%n" + + " id VARCHAR(1000) PRIMARY KEY%n" + + ");")}, + new Object[]{ + new FieldMirror[]{idLong}, + "INSERT INTO my_table(id) VALUES(?);", + "DELETE FROM my_table WHERE id=?;", format( + "CREATE TABLE my_table(%n" + + " id BIGINT PRIMARY KEY%n" + + ");")}, + }; + } + + @Test(dataProvider = "insertIntoSql") + public void testInsertIntoSql(FieldMirror[] fields, String insert, String delete, String create) throws Exception { + EntityMirror myTable = new EntityMirror(new GeneratorSupport(), new TypeRef("Wat"), "my_table"); + for (FieldMirror field : fields) { + myTable.add(field); + } + + assertEquals(myTable.insertIntoSql(), insert); + assertEquals(myTable.deleteFromSql(), delete); + assertEquals(myTable.createTableSql(), create); + } +} diff --git a/container-compiler-plugin/src/test/java/io/trygvis/persistence/test/PersonTypeHandler.java b/container-compiler-plugin/src/test/java/io/trygvis/persistence/test/PersonTypeHandler.java index 68e17c3..fa803da 100644 --- a/container-compiler-plugin/src/test/java/io/trygvis/persistence/test/PersonTypeHandler.java +++ b/container-compiler-plugin/src/test/java/io/trygvis/persistence/test/PersonTypeHandler.java @@ -8,4 +8,9 @@ public class PersonTypeHandler implements TypeHandler { public String resultSetSetter(int i, String o, FieldMirror field) { return "setLong(" + i + ", o." + field.javaName + ".id)"; } + + @Override + public String sqlType(FieldMirror field) { + return "LONG"; + } } diff --git a/myapp/src/main/java/io/trygvis/container/myapp/AddressBook.java b/myapp/src/main/java/io/trygvis/container/myapp/AddressBook.java index 218f25f..0d05989 100644 --- a/myapp/src/main/java/io/trygvis/container/myapp/AddressBook.java +++ b/myapp/src/main/java/io/trygvis/container/myapp/AddressBook.java @@ -1,10 +1,16 @@ package io.trygvis.container.myapp; +import java.io.BufferedReader; import java.io.EOFException; +import java.io.InputStreamReader; import java.sql.Connection; import java.sql.DriverManager; +import java.sql.Statement; public class AddressBook { + + private BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); + public static void main(String[] args) throws Exception { try { new AddressBook().work(); @@ -17,6 +23,12 @@ public class AddressBook { while (!done) { String cmd = Character.toString(menu()); switch (cmd) { + case "c": + run(new CreateTablesCommand()); + break; + case "d": + run(new DropTablesCommand()); + break; case "l": run(new ListCommand()); break; @@ -34,22 +46,47 @@ public class AddressBook { } public void run(Command command) throws Exception { - try (Connection c = DriverManager.getConnection("jdbc:h2:mem")) { + try (Connection c = DriverManager.getConnection("jdbc:h2:mem:address-book;DB_CLOSE_DELAY=-1")) { c.setAutoCommit(false); command.run(c); + c.commit(); + System.out.println("OK"); } } private char menu() throws Exception { System.out.println("Menu:"); + System.out.println("c Create"); + System.out.println("d Drop"); System.out.println("l List"); System.out.println("a Add"); System.out.println("q Quit"); - int read = System.in.read(); - if (read == -1) { - throw new EOFException(); + while (true) { + String read = reader.readLine(); + if (read == null) { + throw new EOFException(); + } + read = read.trim(); + if (read.length() != 0) { + return read.charAt(0); + } + } + } + + public static class CreateTablesCommand implements Command { + @Override + public void run(Connection c) throws Exception { + Statement statement = c.createStatement(); + statement.executeUpdate(PersonDao.createTableSql); + } + } + + public static class DropTablesCommand implements Command { + @Override + public void run(Connection c) throws Exception { + Statement statement = c.createStatement(); + statement.executeUpdate(PersonDao.dropTableSql); } - return (char) read; } public static class ListCommand implements Command { -- cgit v1.2.3