diff options
author | Trygve Laugstøl <trygvis@inamo.no> | 2013-08-03 23:13:32 +0200 |
---|---|---|
committer | Trygve Laugstøl <trygvis@inamo.no> | 2013-08-03 23:13:32 +0200 |
commit | 2b1c32590db960be2b5f62897e65bb10d434cae0 (patch) | |
tree | 84623e4293f59f67331a7760a700121737313c48 /container-compiler-plugin/src/main/java/io | |
parent | df92538ab3d83da9839f08b28fc8a67317565463 (diff) | |
download | container-playground-2b1c32590db960be2b5f62897e65bb10d434cae0.tar.gz container-playground-2b1c32590db960be2b5f62897e65bb10d434cae0.tar.bz2 container-playground-2b1c32590db960be2b5f62897e65bb10d434cae0.tar.xz container-playground-2b1c32590db960be2b5f62897e65bb10d434cae0.zip |
wip
Diffstat (limited to 'container-compiler-plugin/src/main/java/io')
12 files changed, 378 insertions, 159 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 c623af7..19205b1 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 @@ -7,6 +7,7 @@ import io.trygvis.persistence.FieldMirror; import io.trygvis.persistence.GeneratorConfiguration; import io.trygvis.persistence.SqlEntity; import io.trygvis.persistence.TypeHandler; +import io.trygvis.persistence.sql.SqlEntityDesc; import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.AnnotationMirror; @@ -28,7 +29,9 @@ 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 java.lang.reflect.Modifier.PUBLIC; import static javax.lang.model.util.ElementFilter.fieldsIn; +import static org.apache.commons.lang.StringUtils.stripEnd; public class EntityHandler extends AbstractHandler { private GeneratorConfiguration generatorConfiguration = new GeneratorConfiguration(); @@ -49,7 +52,7 @@ public class EntityHandler extends AbstractHandler { TypeHandler typeHandler = (TypeHandler) typeHandlerClass.newInstance(); String type = entity.asType().toString(); - generatorConfiguration.addTypeHandler(new TypeRef(type, type), typeHandler); + generatorConfiguration.addTypeHandler(new TypeRef(type), typeHandler); System.out.println("Loaded TypeHandler for " + type + " through " + typeHandlerClass.getCanonicalName()); break; } @@ -105,18 +108,33 @@ public class EntityHandler extends AbstractHandler { } public void generate(EntityMirror entityMirror) throws IOException { - ClassG g = new ClassG(entityMirror.daoType); - g.addPublicStaticFinalField(String.class, "createTableSql").value(toJavaString(entityMirror.createTableSql(sqlUnit))); - 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())); + TypeRef stringType = new TypeRef(String.class); + TypeRef sqlEntityDescType = new TypeRef(SqlEntityDesc.class); + + ClassG g = new ClassG(PUBLIC, entityMirror.daoType); + g.addPublicStaticFinalField(stringType, "createTableSql"). + value(toJavaString(entityMirror.createTableSql(sqlUnit))); + g.addPublicStaticFinalField(stringType, "dropTableSql"). + value(toJavaString(entityMirror.dropTableSql())); + g.addPublicStaticFinalField(stringType, "insertIntoSql"). + value(toJavaString(entityMirror.insertIntoSql())); + g.addPublicStaticFinalField(stringType, "deleteFromSql"). + value(toJavaString(entityMirror.deleteFromSql())); + String desc = "new " + sqlEntityDescType + "(" + + toJavaString(entityMirror.tableName) + ", " + + toJavaString(entityMirror.defaultFields()) + + ")"; + g.addPublicStaticFinalField(sqlEntityDescType, "desc").value(desc); entityMirror.insertInto(sqlUnit, g); entityMirror.delete(g); entityMirror.deleteById(g); + entityMirror.query(sqlUnit, g); JavaFileObject sourceFile = processingEnv.getFiler().createSourceFile(entityMirror.daoType.fqName, sqlUnit.elementForEntity(entityMirror)); try (PrintWriter w = new PrintWriter(sourceFile.openWriter())) { - g.write(w); + for (String s : g.generate()) { + w.println(stripEnd(s, " ")); + } } } @@ -162,7 +180,7 @@ public class EntityHandler extends AbstractHandler { // TODO: Support a name prefix from @SqlEntitySet TypeRef type = new TypeRef(p + ".Session"); - ClassG g = new ClassG(type); + ClassG g = new ClassG(PUBLIC, type); /* TypeRef conType = g.addImport(Connection.class); @@ -180,7 +198,9 @@ public class EntityHandler extends AbstractHandler { JavaFileObject sourceFile = processingEnv.getFiler().createSourceFile(type.fqName, packageElement); try (PrintWriter w = new PrintWriter(sourceFile.openWriter())) { - g.write(w); + for (String s : g.generate()) { + w.println(stripEnd(s, " ")); + } } } 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 297b9d8..be0b446 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 @@ -69,12 +69,12 @@ public class MyProcessor implements Processor { @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { - System.out.println("io.trygvis.container.compiler.MyProcessor.process"); - System.out.println("annotations = " + annotations); - System.out.println("roundEnv = " + roundEnv); +// System.out.println("io.trygvis.container.compiler.MyProcessor.process"); +// System.out.println("annotations = " + annotations); +// System.out.println("roundEnv = " + roundEnv); try { boolean claimed = work(roundEnv); - System.out.println("claimed = " + claimed); +// System.out.println("claimed = " + claimed); return claimed; } catch (CompilerException e) { e.printStackTrace(System.err); 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 fbd7660..f944b1d 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 @@ -2,7 +2,6 @@ package io.trygvis.container.compiler; import io.trygvis.container.compiler.model.ClassG; import io.trygvis.container.compiler.model.FieldRef; -import io.trygvis.container.compiler.model.ParameterRef; import io.trygvis.container.compiler.model.Parameters; import io.trygvis.container.compiler.model.TypeRef; import io.trygvis.container.tx.PlatformTransactionManager; @@ -23,6 +22,7 @@ import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; +import static java.lang.reflect.Modifier.PUBLIC; import static javax.lang.model.util.ElementFilter.constructorsIn; import static org.springframework.util.StringUtils.collectionToDelimitedString; @@ -42,8 +42,8 @@ public class TransactionalHandler extends AbstractHandler { String p = elements.getPackageOf(element).getQualifiedName().toString(); - ClassG g = new ClassG(new TypeRef(p + "." + className), new TypeRef(targetClassName.toString())); - FieldRef transactionManager = g.addField(PlatformTransactionManager.class, "transactionManager"); + ClassG g = new ClassG(PUBLIC, new TypeRef(p + "." + className)).extendsType(new TypeRef(targetClassName.toString())); + FieldRef transactionManager = g.addField(new TypeRef(PlatformTransactionManager.class), "transactionManager"); for (ExecutableElement constructor : constructorsIn(elements.getAllMembers(element))) { if (!constructor.getModifiers().contains(Modifier.PUBLIC)) { @@ -79,12 +79,12 @@ public class TransactionalHandler extends AbstractHandler { boolean isVoid = kind == TypeKind.VOID; TypeRef returnType = isVoid ? TypeRef.VOID : g.addImport(returnTypeMirror); - List<ParameterRef> parameters = new ArrayList<>(); + Parameters parameters = new Parameters(); List<String> arguments = new ArrayList<>(); for (VariableElement ve : ee.getParameters()) { // parameters.add("final " + ve.asType().toString() + " " + ve.getSimpleName().toString()); TypeRef k = g.addImport(ve.asType()); - parameters.add(new ParameterRef(k, ve.getSimpleName().toString())); + parameters.addParameter(k, ve.getSimpleName().toString()); arguments.add(ve.getSimpleName().toString()); } @@ -107,12 +107,14 @@ public class TransactionalHandler extends AbstractHandler { body.add(" }"); body.add(" });"); - g.addMethod(body, returnType, ee.getSimpleName().toString(), parameters.toArray(new ParameterRef[arguments.size()])); + g.addMethod(body, returnType, ee.getSimpleName().toString(), parameters); } JavaFileObject sourceFile = processingEnv.getFiler().createSourceFile((p.length() == 0 ? "" : p + ".") + className, element); try (PrintWriter w = new PrintWriter(sourceFile.openWriter())) { - g.write(w); + for (String s : g.generate()) { + w.println(s); + } } } @@ -121,7 +123,7 @@ public class TransactionalHandler extends AbstractHandler { List<String> goesToSuper = new ArrayList<>(); TypeRef k = g.addImport(PlatformTransactionManager.class); - ParameterRef transactionManager = parameters.addParameter(k, "transactionManager"); + Parameters.ParameterRef transactionManager = parameters.addParameter(k, "transactionManager"); for (VariableElement p : constructor.getParameters()) { k = g.addImport(p.asType()); 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 857311d..e71bbb7 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 @@ -1,31 +1,60 @@ package io.trygvis.container.compiler.model; +import io.trygvis.container.compiler.Utils; +import org.apache.commons.lang.StringUtils; + +import javax.annotation.Generated; import javax.lang.model.type.TypeMirror; -import java.io.PrintWriter; import java.lang.reflect.Modifier; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.Set; import java.util.TreeSet; +import static io.trygvis.container.compiler.Utils.toJavaString; import static java.lang.reflect.Modifier.*; +import static java.util.Arrays.asList; +import static org.apache.commons.lang.StringUtils.join; import static org.springframework.util.StringUtils.collectionToDelimitedString; public class ClassG { + public final int modifiers; public final TypeRef type; - private final TypeRef extendsClass; + private TypeRef extendsType; + private List<TypeRef> implementsTypes = new ArrayList<>(); private final Set<TypeRef> imports = new TreeSet<>(); private final Set<FieldRef> fields = new TreeSet<>(); private final List<MethodRef> methods = new ArrayList<>(); private final List<Constructor> constructors = new ArrayList<>(); + private final List<InnerClassG> innerClasses = new ArrayList<>(); + + public static class InnerClassG extends ClassG { + public final ClassG parent; - public ClassG(TypeRef type) { - this(type, null); + public InnerClassG(ClassG parent, int modifiers, TypeRef type) { + super(modifiers, type); + this.parent = parent; + } } - public ClassG(TypeRef type, TypeRef extendsClass) { + public ClassG(int modifiers, TypeRef type) { + if ((Modifier.classModifiers() & modifiers) != modifiers) { + throw new RuntimeException("Invalid modifiers for class: " + Modifier.toString(modifiers)); + } + + this.modifiers = modifiers; this.type = type; - this.extendsClass = extendsClass; + } + + public ClassG extendsType(TypeRef extendsType) { + this.extendsType = extendsType; + return this; + } + + public ClassG implementsType(TypeRef... implementsTypes) { + this.implementsTypes.addAll(asList(implementsTypes)); + return this; } public TypeRef addImport(final TypeMirror type) { @@ -38,20 +67,20 @@ public class ClassG { public TypeRef addImport(TypeRef klass) { String fqName = klass.fqName; - String name = klass.name; + String name = klass.toString(); for (TypeRef i : imports) { if (i.fqName.equals(fqName)) { return i; } // If we've already found an import with the same name, use the fq version - if (i.name.equals(name)) { + if (i.plainName.equals(name)) { name = fqName; break; } } - TypeRef ref = new TypeRef(name, fqName); + TypeRef ref = new TypeRef(fqName, name); imports.add(ref); return ref; @@ -64,23 +93,23 @@ public class ClassG { return ref; } - public FieldRef addField(int modifiers, Class<?> klass, String name) { - TypeRef type = addImport(klass); - FieldRef ref = new FieldRef(modifiers, type, name); + public FieldRef addField(int modifiers, TypeRef type, String name) { + TypeRef t = addImport(type); + FieldRef ref = new FieldRef(modifiers, t, name); fields.add(ref); return ref; } - public FieldRef addField(Class<?> klass, String name) { - return addField(PRIVATE | FINAL, klass, name); + public FieldRef addField(TypeRef type, String name) { + return addField(PRIVATE | FINAL, type, name); } - public FieldRef addPublicFinalField(Class<?> klass, String name) { - return addField(PUBLIC | FINAL, klass, name); + public FieldRef addPublicFinalField(TypeRef type, String name) { + return addField(PUBLIC | FINAL, type, name); } - public FieldRef addPublicStaticFinalField(Class<?> klass, String name) { - return addField(PUBLIC | STATIC | FINAL, klass, name); + public FieldRef addPublicStaticFinalField(TypeRef type, String name) { + return addField(PUBLIC | STATIC | FINAL, type, name); } public Constructor addConstructor(Parameters parameters, List<String> body) { @@ -89,92 +118,129 @@ public class ClassG { return constructor; } - public MethodRef addMethod(List<String> body, TypeRef returnType, String name, ParameterRef... parameters) { + public MethodRef addMethod(List<String> body, TypeRef returnType, String name, Parameters parameters) { MethodRef ref = new MethodRef(PUBLIC, returnType, name, parameters, body); methods.add(ref); return ref; } - public MethodRef addStaticMethod(List<String> body, TypeRef returnType, String name, ParameterRef... parameters) { + public MethodRef addStaticMethod(List<String> body, TypeRef returnType, String name, Parameters parameters) { MethodRef ref = new MethodRef(PUBLIC | STATIC, returnType, name, parameters, body); methods.add(ref); return ref; } - public void write(PrintWriter writer) { - if (!type.inUnnamedPackage()) { - writer.println("package " + type.packageName() + ";"); - writer.println(); + public InnerClassG addInnerClass(int modifiers, TypeRef type) { + InnerClassG inner = new InnerClassG(this, modifiers, type); + innerClasses.add(inner); + return inner; + } + + public final List<String> generate() { + TypeRef generatedType = addImport(Generated.class); + + List<String> body = new ArrayList<>(); + boolean isInner = this instanceof InnerClassG; + if (!type.inUnnamedPackage() && !isInner) { + body.add("package " + type.packageName() + ";"); + body.add(""); } - for (TypeRef i : imports) { - if (i.isPrimitive() || i.inUnnamedPackage()) { - continue; + if (!isInner) { + // TODO: Add imports from inner classes + for (TypeRef i : getImports()) { + if (i.isPrimitive() || i.inUnnamedPackage()) { + continue; + } + body.add("import " + i.fqName + ";"); + } + if (!imports.isEmpty()) { + body.add(""); } - writer.println("import " + i.fqName + ";"); - } - if (!imports.isEmpty()) { - writer.println(); } - String extendsString = extendsClass == null ? "" : " extends " + extendsClass.name; + String extendsString = extendsType == null ? "" : " extends " + extendsType; + + if (!implementsTypes.isEmpty()) { + extendsString += " implements " + join(implementsTypes, ", "); + } - writer.println("public class " + type.className + extendsString + " {"); + body.add("@" + generatedType + "(" + toJavaString("SQL Persistence, yay!!") + ")"); + body.add(Modifier.toString(modifiers) + " class " + type.className + extendsString + " {"); for (FieldRef field : fields) { - writer.println(); - writer.println(" " + field.toJava() + ";"); + body.add(""); + body.add(" " + field.toJava() + ";"); + } + + for (InnerClassG innerClass : innerClasses) { + body.add(""); + addAll(1, body, innerClass.generate()); } for (Constructor constructor : constructors) { - writer.println(); - for (String s : constructor.write()) { - writer.println(s); - } + body.add(""); + addAll(1, body, constructor.write()); } for (MethodRef method : methods) { - writer.println(); - write(writer, method); + body.add(""); + addAll(1, body, write(method)); } - writer.println("}"); + body.add("}"); + return body; } - private void write(PrintWriter writer, MethodRef method) { + public static void addAll(int indent, List<String> body, List<String> innerBody) { + String prefix = StringUtils.leftPad("", indent * 4); + for (String s : innerBody) { + body.add(prefix + s); + } + } + + protected Collection<? extends TypeRef> getImports() { + List<TypeRef> imports = new ArrayList<>(this.imports); + for (InnerClassG c : innerClasses) { + imports.addAll(c.getImports()); + } + return imports; + } + + private List<String> write(MethodRef method) { + List<String> body = new ArrayList<>(); String returnString; if (method.returnType == TypeRef.VOID) { returnString = "void"; } else { - returnString = method.returnType.name; + returnString = method.returnType.toString(); } List<String> parameters = new ArrayList<>(); - for (ParameterRef p : method.parameters) { - parameters.add("final " + p.klass.name + " " + p.name); + for (Parameters.ParameterRef p : method.parameters) { + parameters.add("final " + p.klass + " " + p.name); } - writer.print(" " + - Modifier.toString(method.modifiers) + " " + + String m = Modifier.toString(method.modifiers) + " " + returnString + " " + - method.name + "(" + collectionToDelimitedString(parameters, ", ") + ")"); + method.name + "(" + collectionToDelimitedString(parameters, ", ") + ")"; if (method.exceptions.isEmpty()) { - writer.println(" {"); + body.add(m + " {"); } else { - writer.println(" throws"); ArrayList<TypeRef> typeRefs = new ArrayList<>(method.exceptions); - for (int i = 0; i < typeRefs.size(); i++) { + String end = typeRefs.size() == 1 ? " {" : ","; + body.add(m + " throws " + typeRefs.get(0).toString() + end); + for (int i = 1; i < typeRefs.size(); i++) { TypeRef e = typeRefs.get(i); - writer.print(" " + e.name); + String s = " " + e; if (i < typeRefs.size() - 1) { - writer.println(","); + s += ","; } else { - writer.println(" {"); + s += " {"; } + body.add(s); } } - for (String s : method.body) { - writer.print(" "); - writer.println(s); - } - writer.println(" }"); + addAll(1, body, method.body); + body.add("}"); + return body; } } 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 f669273..0f3ceeb 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 @@ -3,7 +3,8 @@ package io.trygvis.container.compiler.model; import java.util.ArrayList; import java.util.List; -import static org.springframework.util.StringUtils.collectionToDelimitedString; +import static io.trygvis.container.compiler.model.ClassG.addAll; +import static org.apache.commons.lang.StringUtils.join; public class Constructor { @@ -18,20 +19,15 @@ public class Constructor { } public List<String> write() { - List<String> body = new ArrayList<>(); - List<String> ps = new ArrayList<>(); - for (ParameterRef p : parameters) { - ps.add(p.klass.name + " " + p.name); + for (Parameters.ParameterRef p : parameters) { + ps.add(p.klass + " " + p.name); } - String params = collectionToDelimitedString(ps, ", "); - - body.add(" public " + g.type.className + "(" + params + ") {"); - for (String s : this.body) { - body.add(" " + s); - } - body.add(" }"); + List<String> body = new ArrayList<>(); + body.add("public " + g.type.className + "(" + join(ps, ", ") + ") {"); + addAll(1, body, this.body); + body.add("}"); return body; } diff --git a/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/model/FieldRef.java b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/model/FieldRef.java index 64bf032..b6df4f2 100644 --- a/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/model/FieldRef.java +++ b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/model/FieldRef.java @@ -4,18 +4,18 @@ import java.lang.reflect.Modifier; public class FieldRef implements Comparable<FieldRef> { public final int modifiers; - public final TypeRef klass; + public final TypeRef type; public final String name; public String value; - public FieldRef(int modifiers, TypeRef klass, String name) { + public FieldRef(int modifiers, TypeRef type, String name) { this.modifiers = modifiers; - this.klass = klass; + this.type = type; this.name = name; } public String toJava() { - String s = Modifier.toString(modifiers) + " " + klass.name + " " + name; + String s = Modifier.toString(modifiers) + " " + type + " " + name; if (value != null) { s += " = " + value; } diff --git a/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/model/MethodRef.java b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/model/MethodRef.java index ee83fa9..902d25a 100644 --- a/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/model/MethodRef.java +++ b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/model/MethodRef.java @@ -11,11 +11,11 @@ public class MethodRef { public final TypeRef returnType; public final String name; public final int modifiers; - public final ParameterRef[] parameters; + public final Parameters parameters; public final Set<TypeRef> exceptions = new TreeSet<>(); public final List<String> body; - public MethodRef(int modifiers, TypeRef returnType, String name, ParameterRef[] parameters, List<String> body) { + public MethodRef(int modifiers, TypeRef returnType, String name, Parameters parameters, List<String> body) { this.modifiers = modifiers; this.returnType = returnType; this.name = name; diff --git a/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/model/ParameterRef.java b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/model/ParameterRef.java deleted file mode 100644 index fc69cb1..0000000 --- a/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/model/ParameterRef.java +++ /dev/null @@ -1,11 +0,0 @@ -package io.trygvis.container.compiler.model; - -public class ParameterRef { - public final TypeRef klass; - public final String name; - - public ParameterRef(TypeRef klass, String name) { - this.klass = klass; - this.name = name; - } -} diff --git a/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/model/Parameters.java b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/model/Parameters.java index cfd29f9..8f76714 100644 --- a/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/model/Parameters.java +++ b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/model/Parameters.java @@ -4,13 +4,30 @@ import java.util.ArrayList; import java.util.List; import java.util.ListIterator; -public class Parameters implements Iterable<ParameterRef> { +public class Parameters implements Iterable<Parameters.ParameterRef> { public static final Parameters noParameters = new Parameters(); private final List<ParameterRef> parameters = new ArrayList<>(); - public ParameterRef addParameter(TypeRef klass, String name) { + public Parameters() { + } + + public Parameters(TypeRef type, String name) { + addParameter(type, name); + } + public Parameters(TypeRef typeA, String nameA, TypeRef typeB, String nameB) { + addParameter(typeA, nameA); + addParameter(typeB, nameB); + } + + public Parameters(TypeRef typeA, String nameA, TypeRef typeB, String nameB, TypeRef typeC, String nameC) { + addParameter(typeA, nameA); + addParameter(typeB, nameB); + addParameter(typeC, nameC); + } + + public ParameterRef addParameter(TypeRef klass, String name) { while (taken(name)) { name = name + "_"; } @@ -34,4 +51,14 @@ public class Parameters implements Iterable<ParameterRef> { public ListIterator<ParameterRef> iterator() { return parameters.listIterator(); } + + public static class ParameterRef { + public final TypeRef klass; + public final String name; + + ParameterRef(TypeRef klass, String name) { + this.klass = klass; + this.name = name; + } + } } 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 c6f958a..9c92e73 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 @@ -2,33 +2,48 @@ package io.trygvis.container.compiler.model; import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; +import java.util.Collections; +import java.util.List; + +import static java.util.Arrays.asList; +import static org.apache.commons.lang.StringUtils.join; public class TypeRef implements Comparable<TypeRef> { - public static final TypeRef VOID = new TypeRef("void", "void"); - public static final TypeRef BOOLEAN = new TypeRef("boolean", null); - public static final TypeRef BYTE = new TypeRef("byte", null); - public static final TypeRef SHORT = new TypeRef("short", null); - public static final TypeRef CHAR = new TypeRef("char", null); - public static final TypeRef INT = new TypeRef("int", null); - public static final TypeRef LONG = new TypeRef("long", null); - public static final TypeRef FLOAT = new TypeRef("float", null); - public static final TypeRef DOUBLE = new TypeRef("double", null); + public static final TypeRef VOID = new TypeRef("void"); + public static final TypeRef BOOLEAN = new PrimitiveTypeRef("boolean"); + public static final TypeRef BYTE = new PrimitiveTypeRef("byte"); + public static final TypeRef SHORT = new PrimitiveTypeRef("short"); + public static final TypeRef CHAR = new PrimitiveTypeRef("char"); + public static final TypeRef INT = new PrimitiveTypeRef("int"); + public static final TypeRef LONG = new PrimitiveTypeRef("long"); + public static final TypeRef FLOAT = new PrimitiveTypeRef("float"); + public static final TypeRef DOUBLE = new PrimitiveTypeRef("double"); + + private static class PrimitiveTypeRef extends TypeRef { + private PrimitiveTypeRef(String name) { + super(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; + public final String plainName; public final String className; 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; + public final List<TypeRef> args; + + private TypeRef(String fqName, String name, boolean primitive, List<TypeRef> args) { + this.fqName = fqName; + this.plainName = name; + this.primitive = primitive; + this.args = args; int i = this.fqName.lastIndexOf('.'); if (i == -1) { @@ -43,11 +58,15 @@ public class TypeRef implements Comparable<TypeRef> { } public TypeRef(Class<?> klass) { - this(klass.getCanonicalName(), klass.getCanonicalName()); + this(klass.getCanonicalName()); } public TypeRef(String fqName) { - this(fqName, fqName); + this(fqName, fqName, false, Collections.<TypeRef>emptyList()); + } + + public TypeRef(String fqName, String name) { + this(fqName, name, false, Collections.<TypeRef>emptyList()); } public boolean isPrimitive() { @@ -62,12 +81,20 @@ public class TypeRef implements Comparable<TypeRef> { int i = fqName.lastIndexOf('.'); if (i == -1) { - throw new RuntimeException("This type is in the unnamed package: " + name); + throw new RuntimeException("This type is in the unnamed package: " + toString()); } return fqName.substring(0, i); } + public TypeRef args(List<TypeRef> args) { + return new TypeRef(fqName, plainName, false, args); + } + + public TypeRef args(TypeRef... args) { + return args(asList(args)); + } + @Override public boolean equals(Object o) { if (this == o) return true; @@ -88,6 +115,14 @@ public class TypeRef implements Comparable<TypeRef> { return fqName.compareTo(o.fqName); } + public String toString() { + String s = plainName; + if(args.isEmpty()) { + return s; + } + return s + "<" + join(args, ", ") + ">"; + } + public static TypeRef find(TypeKind kind) { switch (kind) { case BOOLEAN: 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 8e1602c..74c4829 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,18 +3,26 @@ 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.ParameterRef; +import io.trygvis.container.compiler.model.Parameters; import io.trygvis.container.compiler.model.TypeRef; +import io.trygvis.persistence.sql.AbstractTypedQuery; +import io.trygvis.persistence.sql.SqlEntityDesc; +import javax.persistence.TypedQuery; import java.sql.Connection; import java.sql.PreparedStatement; +import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; +import static io.trygvis.container.compiler.model.Parameters.ParameterRef; import static io.trygvis.persistence.FieldMirror.PrimitiveFieldMirror; import static io.trygvis.persistence.FieldMirror.ReferenceFieldMirror; import static java.lang.String.format; +import static java.lang.reflect.Modifier.PUBLIC; +import static java.lang.reflect.Modifier.STATIC; +import static java.util.Collections.singletonList; import static org.apache.commons.lang.StringUtils.join; public class EntityMirror implements Comparable<EntityMirror> { @@ -30,7 +38,7 @@ public class EntityMirror implements Comparable<EntityMirror> { this.type = type; this.tableName = tableName; - this.daoType = new TypeRef(type.name + "Dao"); + this.daoType = new TypeRef(type.plainName + "Dao").args(type.args); } public void add(FieldMirror field) { @@ -111,41 +119,51 @@ public class EntityMirror implements Comparable<EntityMirror> { return "DELETE FROM " + tableName + " WHERE " + join(ss, " AND ") + ";"; } + public String defaultFields() { + List<String> names = new ArrayList<>(); + for (FieldMirror field : fields) { + names.add(field.sqlName); + } + + return join(names, ", "); + } + public void insertInto(SqlUnitModel unit, ClassG g) { TypeRef conType = g.addImport(Connection.class); TypeRef psType = g.addImport(PreparedStatement.class); - TypeRef objectType = g.addImport(type); - ParameterRef con = new ParameterRef(conType, "con"); - ParameterRef object = new ParameterRef(objectType, "o"); + Parameters p = new Parameters(); + ParameterRef con = p.addParameter(conType, "con"); + ParameterRef o = p.addParameter(type, "o"); List<String> body = new ArrayList<>(); - body.add("try(" + psType.name + " stmt = " + con.name + ".prepareStatement(insertIntoSql)) {"); + body.add("try(" + psType + " stmt = " + con.name + ".prepareStatement(insertIntoSql)) {"); for (int i = 0; i < fields.size(); i++) { FieldMirror field = fields.get(i); if(field instanceof PrimitiveFieldMirror) { TypeHandler typeHandler = generatorConfiguration.typeHandler(field.type); - body.add(" stmt." + typeHandler.setter(i + 1, "o." + field.javaName) + ";"); + body.add(" stmt." + typeHandler.setter(i + 1, o.name + "." + field.javaName) + ";"); } else if (field instanceof ReferenceFieldMirror) { ReferenceFieldMirror ref = (ReferenceFieldMirror) field; EntityMirror referenced = unit.get(ref.type); FieldMirror idField = referenced.getIdField(); TypeHandler typeHandler = generatorConfiguration.typeHandler(idField.type); - body.add(" stmt." + typeHandler.setter(i + 1, "o." + field.javaName + "." + idField.javaName) + ";"); + body.add(" stmt." + typeHandler.setter(i + 1, o.name + "." + field.javaName + "." + idField.javaName) + ";"); } } body.add(" stmt.executeUpdate();"); body.add("}"); - g.addStaticMethod(body, TypeRef.VOID, "insertInto", con, object). + g.addStaticMethod(body, TypeRef.VOID, "insertInto", p). exception(g.addImport(SQLException.class)); } public void delete(ClassG g) { TypeRef conType = g.addImport(Connection.class); TypeRef objectType = g.addImport(type); - ParameterRef con = new ParameterRef(conType, "con"); - ParameterRef o = new ParameterRef(objectType, "o"); + Parameters p = new Parameters(); + ParameterRef con = p.addParameter(conType, "con"); + ParameterRef o = p.addParameter(objectType, "o"); List<String> arguments = new ArrayList<>(); arguments.add(con.name); @@ -155,32 +173,76 @@ public class EntityMirror implements Comparable<EntityMirror> { List<String> body = new ArrayList<>(); body.add("deleteById(" + join(arguments, ", ") + ");"); - g.addStaticMethod(body, TypeRef.VOID, "delete", con, o). + g.addStaticMethod(body, TypeRef.VOID, "delete", p). exception(g.addImport(SQLException.class)); } public void deleteById(ClassG g) { TypeRef conType = g.addImport(Connection.class); TypeRef psType = g.addImport(PreparedStatement.class); - ParameterRef con = new ParameterRef(conType, "con"); - - ParameterRef[] parameters = new ParameterRef[idFields.size() + 1]; - parameters[0] = con; + Parameters p = new Parameters(); + ParameterRef con = p.addParameter(conType, "con"); List<String> body = new ArrayList<>(); - body.add("try(" + psType.name + " stmt = " + con.name + ".prepareStatement(deleteFromSql)) {"); + body.add("try(" + psType + " stmt = " + con.name + ".prepareStatement(deleteFromSql)) {"); for (int i = 0; i < idFields.size(); i++) { FieldMirror field = idFields.get(i); + p.addParameter(field.type, field.javaName); TypeHandler typeHandler = generatorConfiguration.typeHandler(field.type); - ParameterRef p = new ParameterRef(field.type, field.javaName); - parameters[i + 1] = p; body.add(" stmt." + typeHandler.setter(i + 1, field.javaName) + ";"); } body.add(" stmt.executeUpdate();"); body.add("}"); - g.addStaticMethod(body, TypeRef.VOID, "deleteById", parameters). + g.addStaticMethod(body, TypeRef.VOID, "deleteById", p). + exception(g.addImport(SQLException.class)); + } + + public void query(SqlUnitModel sqlUnit, ClassG g) { + TypeRef conType = g.addImport(Connection.class); + TypeRef abstractQueryType = g.addImport(AbstractTypedQuery.class).args(type); + TypeRef typedQueryType = g.addImport(TypedQuery.class).args(type); + + Parameters p = new Parameters(); + ParameterRef c = p.addParameter(conType, "c"); + + ClassG typedQuery = g.addInnerClass(PUBLIC | STATIC, new TypeRef(type.className + "TypedQuery")). + extendsType(abstractQueryType); + typedQuery.addConstructor(p, singletonList("super(" + c.name + ", " + daoType.className + ".desc);")); + fromResultSet(sqlUnit, typedQuery); + + List<String> body = new ArrayList<>(); + body.add("return new " + typedQuery.type + "(" + c.name + ");"); + g.addStaticMethod(body, typedQueryType, "query", p); + } + + public void fromResultSet(SqlUnitModel unit, ClassG g) { + TypeRef rsType = g.addImport(ResultSet.class); + Parameters p = new Parameters(); + ParameterRef rs = p.addParameter(rsType, "rs"); + + List<String> body = new ArrayList<>(); + List<String> names = new ArrayList<>(); + for (int i = 0; i < fields.size(); i++) { + FieldMirror field = fields.get(i); + if(field instanceof PrimitiveFieldMirror) { + TypeHandler typeHandler = generatorConfiguration.typeHandler(field.type); + body.add(field.type + " " + field.javaName + " = " + typeHandler.getter(rs.name, i + 1) + ";"); + } else if (field instanceof ReferenceFieldMirror) { + ReferenceFieldMirror ref = (ReferenceFieldMirror) field; + EntityMirror referenced = unit.get(ref.type); + FieldMirror idField = referenced.getIdField(); + TypeHandler typeHandler = generatorConfiguration.typeHandler(idField.type); +// body.add(field.type + " " + field.javaName + " = " + typeHandler.getter(rs.name, i + 1) + ";"); + body.add(field.type + " " + field.javaName + " = null;"); + } + names.add(field.javaName); + } + + body.add("return new " + type + "(" + join(names, ", ") + ");"); + + g.addMethod(body, type, "fromResultSet", p). exception(g.addImport(SQLException.class)); } @@ -200,7 +262,7 @@ public class EntityMirror implements Comparable<EntityMirror> { } @Override - public int compareTo(EntityMirror o) { + public int compareTo(@SuppressWarnings("NullableProblems") EntityMirror o) { return type.compareTo(o.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 3aacd7a..0454a96 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 @@ -1,14 +1,21 @@ package io.trygvis.persistence; public interface TypeHandler { - String setter(int i, String ref); + String setter(int i, String expr); + + String getter(String rs, int i); String sqlType(FieldMirror field); public static class IntTypeHandler implements TypeHandler { @Override - public String setter(int i, String ref) { - return "setInt(" + i + ", " + ref + ")"; + public String setter(int i, String expr) { + return "setInt(" + i + ", " + expr + ")"; + } + + @Override + public String getter(String rs, int i) { + return rs + ".getInt(" + i + ")"; } @Override @@ -19,8 +26,13 @@ public interface TypeHandler { public static class LongTypeHandler implements TypeHandler { @Override - public String setter(int i, String ref) { - return "setLong(" + i + ", " + ref + ")"; + public String setter(int i, String expr) { + return "setLong(" + i + ", " + expr + ")"; + } + + @Override + public String getter(String rs, int i) { + return rs + ".getLong(" + i + ")"; } @Override @@ -31,8 +43,13 @@ public interface TypeHandler { public static class StringTypeHandler implements TypeHandler { @Override - public String setter(int i, String ref) { - return "setString(" + i + ", " + ref + ")"; + public String setter(int i, String expr) { + return "setString(" + i + ", " + expr + ")"; + } + + @Override + public String getter(String rs, int i) { + return rs + ".getString(" + i + ")"; } @Override @@ -43,8 +60,13 @@ public interface TypeHandler { public static class DateTypeHandler implements TypeHandler { @Override - public String setter(int i, String ref) { - return "setTimestamp(" + i + ", new java.sql.Timestamp(" + ref + ".getTime()))"; + public String setter(int i, String expr) { + return "setTimestamp(" + i + ", new java.sql.Timestamp(" + expr + ".getTime()))"; + } + + @Override + public String getter(String rs, int i) { + return "new java.util.Date(" + rs + ".getTimestamp(" + i + ").getTime())"; } @Override |