summaryrefslogtreecommitdiff
path: root/container-compiler-plugin/src/main/java/io/trygvis/container
diff options
context:
space:
mode:
Diffstat (limited to 'container-compiler-plugin/src/main/java/io/trygvis/container')
-rw-r--r--container-compiler-plugin/src/main/java/io/trygvis/container/compiler/EntityHandler.java111
-rw-r--r--container-compiler-plugin/src/main/java/io/trygvis/container/compiler/MyProcessor.java27
-rw-r--r--container-compiler-plugin/src/main/java/io/trygvis/container/compiler/Utils.java31
-rw-r--r--container-compiler-plugin/src/main/java/io/trygvis/container/compiler/model/ClassG.java51
-rw-r--r--container-compiler-plugin/src/main/java/io/trygvis/container/compiler/model/FieldRef.java11
-rw-r--r--container-compiler-plugin/src/main/java/io/trygvis/container/compiler/model/MethodRef.java9
-rw-r--r--container-compiler-plugin/src/main/java/io/trygvis/container/compiler/model/Parameters.java2
7 files changed, 199 insertions, 43 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 f9247e0..fc7ca4f 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,7 +1,10 @@
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.persistence.EntityMirror;
import io.trygvis.persistence.FieldMirror;
import io.trygvis.persistence.GeneratorSupport;
@@ -11,35 +14,37 @@ import io.trygvis.persistence.TypeHandler;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
-import javax.lang.model.element.Element;
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;
import java.io.PrintWriter;
+import java.sql.Connection;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import static io.trygvis.container.compiler.Utils.toFieldName;
import static io.trygvis.persistence.FieldMirror.PrimitiveFieldMirror;
import static java.lang.Character.isUpperCase;
import static javax.lang.model.util.ElementFilter.fieldsIn;
public class EntityHandler extends AbstractHandler {
- GeneratorSupport generatorSupport = new GeneratorSupport();
+ private GeneratorSupport generatorSupport = new GeneratorSupport();
+ private List<EntityMirror> entities = new ArrayList<>();
+ private PackageElement packageElement;
public EntityHandler(ProcessingEnvironment processingEnv) {
super(processingEnv);
}
- public void phase1(Set<? extends Element> sqlEntities) throws Exception {
- System.out.println("io.trygvis.container.compiler.EntityHandler.phase1");
- for (Element entity : sqlEntities) {
-// SqlEntity sqlEntity = entity.getAnnotation(SqlEntity.class);
-// Class<? extends TypeHandler> typeHandlerClass = sqlEntity.value();
-
+ public void phase1(Set<TypeElement> sqlEntities, Set<PackageElement> packages) throws Exception {
+ for (TypeElement entity : sqlEntities) {
AnnotationMirror sqlEntity = findAnnotation(SqlEntity.class, entity.getAnnotationMirrors());
for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> v : sqlEntity.getElementValues().entrySet()) {
switch (v.getKey().getSimpleName().toString()) {
@@ -53,8 +58,18 @@ public class EntityHandler extends AbstractHandler {
break;
}
}
- System.out.println("sqlEntity.getElementValues() = " + sqlEntity.getElementValues());
+// System.out.println("sqlEntity.getElementValues() = " + sqlEntity.getElementValues());
+ }
+
+ System.out.println("packages = " + packages);
+ if (packages.size() == 0) {
+ throw new RuntimeException("There has to be exactly one @SqlEntitySet annotated package.");
+ }
+ if (packages.size() != 1) {
+ throw new RuntimeException("There can only be one @SqlEntitySet annotated package.");
}
+
+ packageElement = packages.iterator().next();
}
private AnnotationMirror findAnnotation(Class<?> c, List<? extends AnnotationMirror> annotations) {
@@ -69,49 +84,103 @@ public class EntityHandler extends AbstractHandler {
}
public void processEntity(TypeElement element) throws Exception {
- EntityMirror entityMirror = new EntityMirror(generatorSupport, element.asType(), sqlName(element.getSimpleName().toString()));
+ DeclaredType declaredType = types.getDeclaredType(element);
+ EntityMirror entityMirror = new EntityMirror(generatorSupport, declaredType, sqlName(element.getSimpleName().toString()));
for (VariableElement f : fieldsIn(elements.getAllMembers(element))) {
entityMirror.add(fromElement(generatorSupport, f));
}
+ List<FieldMirror> idFields = new ArrayList<>();
+ for (FieldMirror field : entityMirror.fields) {
+ if (field.id) {
+ idFields.add(field);
+ }
+ }
+
+ if (idFields.size() == 0) {
+ throw new RuntimeException("An @Entity is required to have at least one @Id field.");
+ }
+ if (idFields.size() != 1) {
+ throw new RuntimeException("This implementation only support a single @Id annotated field.");
+ }
+
String p = elements.getPackageOf(element).getQualifiedName().toString();
- String className = element.getSimpleName() + "_Sql";
- ClassG g = new ClassG(p, className, null);
- g.addPublicFinalField(String.class, "insertIntoSql");
+ ClassG g = new ClassG(p, entityMirror.daoName);
String insertInto = entityMirror.insertIntoSql();
- List<String> body = new ArrayList<>();
- body.add("this.insertIntoSql = \"" + insertInto + "\";");
- g.addConstructor(new Parameters(), body);
+ g.addPublicStaticFinalField(String.class, "insertIntoSql").value("\"" + insertInto + "\"");
+// List<String> body = new ArrayList<>();
+// body.add("this.insertIntoSql = \"" + insertInto + "\";");
+// g.addConstructor(new Parameters(), body);
entityMirror.insertInto(g);
- String fileName = (p.length() == 0 ? "" : p + ".") + className;
+ String fileName = (p.length() == 0 ? "" : p + ".") + entityMirror.daoName;
JavaFileObject sourceFile = processingEnv.getFiler().createSourceFile(fileName, element);
try (PrintWriter w = new PrintWriter(sourceFile.openWriter())) {
g.write(w);
}
+
+ entities.add(entityMirror);
}
public FieldMirror fromElement(GeneratorSupport generatorSupport, VariableElement var) {
- System.out.print("element = ");
TypeMirror type = var.asType();
- elements.printElements(new PrintWriter(System.out), var);
+// System.out.print("element = ");
+// elements.printElements(new PrintWriter(System.out), var);
String javaName = var.getSimpleName().toString();
String sqlName = sqlName(javaName);
boolean notNull = false;
FieldMirror field;
+ boolean id = isId(var);
if (generatorSupport.isPrimitive(type)) {
- field = new PrimitiveFieldMirror(var, javaName, sqlName, notNull);
+ field = new PrimitiveFieldMirror(var, javaName, sqlName, id, notNull);
} else if (generatorSupport.hasTypeHandler(type)) {
+ if (id) {
+ throw new RuntimeException("A @Id field has to be a primitive or embedded.");
+ }
+
field = new FieldMirror.ReferenceFieldMirror(var, javaName, sqlName, notNull);
} else {
throw new RuntimeException("Missing type handler for type: " + type);
}
- System.out.println("field = " + field);
+// System.out.println("field = " + field);
return field;
}
+ public static boolean isId(VariableElement var) {
+ return var.getAnnotation(Id.class) != null;
+ }
+
+ public void phase3() throws Exception {
+ String p = packageElement.getQualifiedName().toString();
+
+ // TODO: Support a name prefix from @SqlEntitySet
+ String className = "Daos";
+
+ String fileName = (p.length() == 0 ? "" : p + ".") + className;
+ ClassG g = new ClassG(p, className);
+
+/*
+ TypeRef conType = g.addImport(Connection.class);
+ Parameters parameters = new Parameters();
+ ParameterRef c = parameters.addParameter(conType, "c");
+
+ List<String> body = new ArrayList<>();
+ for (EntityMirror entity : entities) {
+ FieldRef fieldRef = g.addField(entity.javaName.asElement().asType(), toFieldName(entity.daoName));
+ body.add("this." + fieldRef.name + " = new " + entity.daoName + "(" + c.name + ");");
+ }
+
+ g.addConstructor(parameters, body);
+*/
+
+ JavaFileObject sourceFile = processingEnv.getFiler().createSourceFile(fileName, packageElement);
+ try (PrintWriter w = new PrintWriter(sourceFile.openWriter())) {
+ g.write(w);
+ }
+ }
+
public static String sqlName(String javaName) {
StringBuilder builder = new StringBuilder();
for (char c : javaName.toCharArray()) {
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 735d688..43ba49e 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
@@ -2,6 +2,7 @@ package io.trygvis.container.compiler;
import io.trygvis.container.log.Log;
import io.trygvis.persistence.SqlEntity;
+import io.trygvis.persistence.SqlEntitySet;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.processing.Completion;
@@ -12,8 +13,10 @@ import javax.lang.model.SourceVersion;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
+import javax.lang.model.util.ElementFilter;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import javax.persistence.Entity;
@@ -23,6 +26,7 @@ import java.util.Set;
import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
import static java.util.Collections.emptySet;
+import static javax.lang.model.util.ElementFilter.typesIn;
public class MyProcessor implements Processor {
@@ -57,13 +61,14 @@ public class MyProcessor implements Processor {
return new HashSet<>(asList(
Transactional.class.getName(),
Log.class.getName(),
- Entity.class.getName()));
+ Entity.class.getName(),
+ SqlEntitySet.class.getName()));
}
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
try {
- return work(annotations, roundEnv);
+ return work(roundEnv);
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
@@ -71,18 +76,25 @@ public class MyProcessor implements Processor {
}
}
- public boolean work(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) throws Exception {
+ boolean first = true;
+ public boolean work(RoundEnvironment roundEnv) throws Exception {
+ if (!first) {
+ return false;
+ }
+ first = false;
+
TypeElement tx = elements.getTypeElement(Transactional.class.getCanonicalName());
TypeElement log = elements.getTypeElement(Log.class.getCanonicalName());
TypeElement entity = elements.getTypeElement(Entity.class.getCanonicalName());
EntityHandler entityHandler = new EntityHandler(processingEnv);
- Set<? extends Element> sqlEntities = roundEnv.getElementsAnnotatedWith(SqlEntity.class);
- entityHandler.phase1(sqlEntities);
+ Set<TypeElement> sqlEntities = typesIn(roundEnv.getElementsAnnotatedWith(SqlEntity.class));
+ Set<PackageElement> packages = ElementFilter.packagesIn(roundEnv.getElementsAnnotatedWith(SqlEntitySet.class));
+ entityHandler.phase1(sqlEntities, packages);
for (Element element : roundEnv.getRootElements()) {
- System.out.println("Processing: " + element);
+ System.out.println("Processing: " + element.asType());
for (AnnotationMirror annotationMirror : element.getAnnotationMirrors()) {
DeclaredType annotationType = annotationMirror.getAnnotationType();
@@ -97,6 +109,9 @@ public class MyProcessor implements Processor {
}
}
}
+
+ entityHandler.phase3();
+
return true;
}
}
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
new file mode 100644
index 0000000..8bd0de3
--- /dev/null
+++ b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/Utils.java
@@ -0,0 +1,31 @@
+package io.trygvis.container.compiler;
+
+import static java.lang.Character.toLowerCase;
+import static java.lang.Character.toUpperCase;
+
+public class Utils {
+ public static String toFieldName(String s) {
+ if (s.length() < 1) {
+ return s.toLowerCase();
+ }
+ char[] chars = s.toCharArray();
+
+ boolean toUpper = false;
+
+ int j = 0;
+ for (int i = 0; i < chars.length; i++) {
+ char c = chars[i];
+ if (c == '_') {
+ toUpper = true;
+ } else {
+ if (j == 0) {
+ chars[j++] = toLowerCase(c);
+ } else {
+ chars[j++] = toUpper ? toUpperCase(c) : c;
+ }
+ toUpper = false;
+ }
+ }
+ return new String(chars, 0, j);
+ }
+}
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 8ff91a0..6bfd0be 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
@@ -8,6 +8,7 @@ import java.util.List;
import java.util.Set;
import java.util.TreeSet;
+import static java.lang.reflect.Modifier.*;
import static org.springframework.util.StringUtils.collectionToDelimitedString;
public class ClassG {
@@ -19,6 +20,10 @@ public class ClassG {
private final List<MethodRef> methods = new ArrayList<>();
private final List<Constructor> constructors = new ArrayList<>();
+ public ClassG(String packageName, String className) {
+ this(packageName, className, null);
+ }
+
public ClassG(String packageName, String className, String extendsClass) {
this.packageName = packageName;
this.className = className;
@@ -64,20 +69,32 @@ public class ClassG {
return ref;
}
- public FieldRef addField(Class<?> klass, String name) {
+ public FieldRef addField(TypeMirror klass, String name) {
TypeRef type = addImport(klass);
- FieldRef ref = new FieldRef(Modifier.PRIVATE | Modifier.FINAL, type, name);
+ FieldRef ref = new FieldRef(PRIVATE | FINAL, type, name);
fields.add(ref);
return ref;
}
- public FieldRef addPublicFinalField(Class<?> klass, String name) {
+ public FieldRef addField(int modifiers, Class<?> klass, String name) {
TypeRef type = addImport(klass);
- FieldRef ref = new FieldRef(Modifier.PUBLIC | Modifier.FINAL, type, name);
+ FieldRef ref = new FieldRef(modifiers, type, name);
fields.add(ref);
return ref;
}
+ public FieldRef addField(Class<?> klass, String name) {
+ return addField(PRIVATE | FINAL, klass, name);
+ }
+
+ public FieldRef addPublicFinalField(Class<?> klass, String name) {
+ return addField(PUBLIC | FINAL, klass, name);
+ }
+
+ public FieldRef addPublicStaticFinalField(Class<?> klass, String name) {
+ return addField(PUBLIC | STATIC | FINAL, klass, name);
+ }
+
public Constructor addConstructor(Parameters parameters, List<String> body) {
Constructor constructor = new Constructor(this, parameters, body);
constructors.add(constructor);
@@ -85,13 +102,19 @@ public class ClassG {
}
public MethodRef addMethod(List<String> body, TypeRef returnType, String name, ParameterRef... parameters) {
- MethodRef ref = new MethodRef(returnType, name, parameters, body);
+ 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) {
+ MethodRef ref = new MethodRef(PUBLIC | STATIC, returnType, name, parameters, body);
methods.add(ref);
return ref;
}
public void write(PrintWriter writer) {
- if(packageName.length() > 0) {
+ if (packageName.length() > 0) {
writer.println("package " + packageName + ";");
writer.println();
}
@@ -99,12 +122,14 @@ public class ClassG {
if (i.isPrimitive()) {
continue;
}
- if(i.canonicalName().indexOf('.') == -1) {
+ if (i.canonicalName().indexOf('.') == -1) {
continue;
}
writer.println("import " + i.canonicalName() + ";");
}
- writer.println();
+ if (!imports.isEmpty()) {
+ writer.println();
+ }
String extendsString = extendsClass == null ? "" : " extends " + extendsClass;
@@ -143,19 +168,17 @@ public class ClassG {
}
writer.print(" public " + returnString + " " + method.name + "(" + collectionToDelimitedString(parameters, ", ") + ")");
- if(method.exceptions.isEmpty()) {
+ if (method.exceptions.isEmpty()) {
writer.println(" {");
- }
- else {
+ } else {
writer.println(" throws");
ArrayList<TypeRef> typeRefs = new ArrayList<>(method.exceptions);
for (int i = 0; i < typeRefs.size(); i++) {
TypeRef e = typeRefs.get(i);
writer.print(" " + e.name);
- if(i < typeRefs.size() - 1) {
+ if (i < typeRefs.size() - 1) {
writer.println(",");
- }
- else {
+ } else {
writer.println(" {");
}
}
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 c6b81a0..64bf032 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
@@ -6,6 +6,7 @@ public class FieldRef implements Comparable<FieldRef> {
public final int modifiers;
public final TypeRef klass;
public final String name;
+ public String value;
public FieldRef(int modifiers, TypeRef klass, String name) {
this.modifiers = modifiers;
@@ -14,7 +15,11 @@ public class FieldRef implements Comparable<FieldRef> {
}
public String toJava() {
- return Modifier.toString(modifiers) + " " + klass.name + " " + name;
+ String s = Modifier.toString(modifiers) + " " + klass.name + " " + name;
+ if (value != null) {
+ s += " = " + value;
+ }
+ return s;
}
@Override
@@ -36,4 +41,8 @@ public class FieldRef implements Comparable<FieldRef> {
public int compareTo(FieldRef o) {
return name.compareTo(o.name);
}
+
+ public void value(String value) {
+ this.value = 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 a59e9a6..ee83fa9 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
@@ -1,5 +1,6 @@
package io.trygvis.container.compiler.model;
+import java.lang.reflect.Modifier;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
@@ -9,15 +10,21 @@ import static java.util.Collections.addAll;
public class MethodRef {
public final TypeRef returnType;
public final String name;
+ public final int modifiers;
public final ParameterRef[] parameters;
public final Set<TypeRef> exceptions = new TreeSet<>();
public final List<String> body;
- public MethodRef(TypeRef returnType, String name, ParameterRef[] parameters, List<String> body) {
+ public MethodRef(int modifiers, TypeRef returnType, String name, ParameterRef[] parameters, List<String> body) {
+ this.modifiers = modifiers;
this.returnType = returnType;
this.name = name;
this.parameters = parameters;
this.body = body;
+
+ if ((Modifier.methodModifiers() & modifiers) != modifiers) {
+ throw new RuntimeException("Invalid modifiers for method: " + Modifier.toString(modifiers));
+ }
}
public MethodRef exception(TypeRef... exceptions) {
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 7c1ab5b..cfd29f9 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
@@ -5,6 +5,8 @@ import java.util.List;
import java.util.ListIterator;
public class Parameters implements Iterable<ParameterRef> {
+ public static final Parameters noParameters = new Parameters();
+
private final List<ParameterRef> parameters = new ArrayList<>();
public ParameterRef addParameter(TypeRef klass, String name) {