summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--container-compiler-plugin/pom.xml25
-rw-r--r--container-compiler-plugin/src/main/java/io/trygvis/container/compiler/AbstractHandler.java17
-rw-r--r--container-compiler-plugin/src/main/java/io/trygvis/container/compiler/EntityHandler.java83
-rw-r--r--container-compiler-plugin/src/main/java/io/trygvis/container/compiler/MyProcessor.java31
-rw-r--r--container-compiler-plugin/src/main/java/io/trygvis/container/compiler/TransactionalHandler.java126
-rw-r--r--container-compiler-plugin/src/main/java/io/trygvis/container/compiler/entity/EntityMirror.java38
-rw-r--r--container-compiler-plugin/src/main/java/io/trygvis/container/compiler/model/ClassG.java27
-rw-r--r--container-compiler-plugin/src/main/java/io/trygvis/container/compiler/model/FieldRef.java10
-rw-r--r--container-compiler-plugin/src/test/java/io/trygvis/container/compiler/EntityHandlerTest.java27
-rw-r--r--container-compiler-plugin/src/test/java/io/trygvis/container/compiler/InMemoryJavaFileManager.java74
-rw-r--r--container-compiler-plugin/src/test/java/io/trygvis/container/compiler/ProcessorTest.java83
-rw-r--r--container-compiler-plugin/src/test/resources/Car.java6
-rw-r--r--container-compiler-plugin/src/test/resources/Person.java26
-rw-r--r--container-core/pom.xml5
-rw-r--r--myapp/src/main/java/io/trygvis/container/myapp/MyEntity.java10
15 files changed, 504 insertions, 84 deletions
diff --git a/container-compiler-plugin/pom.xml b/container-compiler-plugin/pom.xml
index beb4b55..f48d8fc 100644
--- a/container-compiler-plugin/pom.xml
+++ b/container-compiler-plugin/pom.xml
@@ -15,5 +15,30 @@
<artifactId>container-core</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.easytesting</groupId>
+ <artifactId>fest-assert</artifactId>
+ <version>1.4</version>
+ </dependency>
+ <dependency>
+ <groupId>org.testng</groupId>
+ <artifactId>testng</artifactId>
+ <version>6.8.5</version>
+ <scope>test</scope>
+ </dependency>
+ <!--
+ <dependency>
+ <groupId>org.eclipse.tycho</groupId>
+ <artifactId>org.eclipse.jdt.core</artifactId>
+ <version>3.9.0.v20130604-1421</version>
+ <scope>test</scope>
+ </dependency>
+ -->
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>2.4</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
diff --git a/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/AbstractHandler.java b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/AbstractHandler.java
new file mode 100644
index 0000000..0a558ea
--- /dev/null
+++ b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/AbstractHandler.java
@@ -0,0 +1,17 @@
+package io.trygvis.container.compiler;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.util.Elements;
+import javax.lang.model.util.Types;
+
+public abstract class AbstractHandler {
+ protected final ProcessingEnvironment processingEnv;
+ protected final Elements elements;
+ protected final Types types;
+
+ public AbstractHandler(ProcessingEnvironment processingEnv) {
+ this.processingEnv = processingEnv;
+ this.elements = processingEnv.getElementUtils();
+ this.types = processingEnv.getTypeUtils();
+ }
+}
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
new file mode 100644
index 0000000..df7a673
--- /dev/null
+++ b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/EntityHandler.java
@@ -0,0 +1,83 @@
+package io.trygvis.container.compiler;
+
+import io.trygvis.container.compiler.entity.EntityMirror;
+import io.trygvis.container.compiler.model.ClassG;
+import io.trygvis.container.compiler.model.Parameters;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.tools.JavaFileObject;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+import static io.trygvis.container.compiler.entity.EntityMirror.FieldMirror;
+import static java.lang.Character.isUpperCase;
+import static javax.lang.model.util.ElementFilter.fieldsIn;
+import static org.springframework.util.StringUtils.collectionToDelimitedString;
+
+public class EntityHandler extends AbstractHandler {
+ public EntityHandler(ProcessingEnvironment processingEnv) {
+ super(processingEnv);
+ }
+
+ public void processEntity(TypeElement element) throws Exception {
+ EntityMirror entityMirror = new EntityMirror(sqlName(element.getSimpleName().toString()));
+
+ for (VariableElement f : fieldsIn(elements.getAllMembers(element))) {
+ entityMirror.add(fromElement(f));
+ }
+
+ String p = elements.getPackageOf(element).getQualifiedName().toString();
+ String className = element.getSimpleName() + "_Sql";
+
+ ClassG g = new ClassG(p, className, null);
+ g.addPublicFinalField(String.class, "insertInto");
+ String insertInto = insertInto(entityMirror);
+ List<String> body = new ArrayList<>();
+ body.add("this.insertInto = \"" + insertInto + "\";");
+ g.addConstructor(new Parameters(), body);
+
+ String fileName = (p.length() == 0 ? "" : p + ".") + className;
+ JavaFileObject sourceFile = processingEnv.getFiler().createSourceFile(fileName, element);
+ try (PrintWriter w = new PrintWriter(sourceFile.openWriter())) {
+ g.write(w);
+ }
+ }
+
+ public static String insertInto(EntityMirror entityMirror) {
+ List<String> names = new ArrayList<>();
+ List<String> placeholders = new ArrayList<>();
+ for (FieldMirror field : entityMirror.fields) {
+ names.add(field.sqlName);
+ placeholders.add("?");
+ }
+ return "INSERT INTO " + entityMirror.tableName + "(" + collectionToDelimitedString(names, ", ") + ") " +
+ "VALUES(" + collectionToDelimitedString(placeholders, ", ") + ");";
+ }
+
+ public FieldMirror fromElement(VariableElement var) {
+ System.out.println("io.trygvis.container.compiler.entity.EntityMirror.FieldMirror.fromElement");
+ 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 = new FieldMirror(javaName, sqlName, notNull);
+ System.out.println("field = " + field);
+ return field;
+ }
+
+ public static String sqlName(String javaName) {
+ StringBuilder builder = new StringBuilder();
+ for (char c : javaName.toCharArray()) {
+ char lower = Character.toLowerCase(c);
+ if(isUpperCase(c) && builder.length() > 0) {
+ builder.append("_");
+ }
+ builder.append(lower);
+ }
+ return builder.toString();
+ }
+}
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 729a0ee..6843659 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
@@ -12,8 +12,10 @@ import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.DeclaredType;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
+import javax.persistence.Entity;
import java.util.HashSet;
import java.util.Set;
@@ -29,16 +31,19 @@ public class MyProcessor implements Processor {
@Override
public Set<String> getSupportedOptions() {
+ System.out.println("io.trygvis.container.compiler.MyProcessor.getSupportedOptions");
return emptySet();
}
@Override
public SourceVersion getSupportedSourceVersion() {
- return SourceVersion.RELEASE_5;
+ System.out.println("io.trygvis.container.compiler.MyProcessor.getSupportedSourceVersion");
+ return SourceVersion.RELEASE_7;
}
@Override
public void init(ProcessingEnvironment processingEnv) {
+ System.out.println("io.trygvis.container.compiler.MyProcessor.init");
this.processingEnv = processingEnv;
elements = processingEnv.getElementUtils();
types = processingEnv.getTypeUtils();
@@ -46,32 +51,44 @@ public class MyProcessor implements Processor {
@Override
public Iterable<? extends Completion> getCompletions(Element element, AnnotationMirror annotation, ExecutableElement member, String userText) {
+ System.out.println("io.trygvis.container.compiler.MyProcessor.getCompletions");
return emptyList();
}
@Override
public Set<String> getSupportedAnnotationTypes() {
- return new HashSet<>(asList(Transactional.class.getName(), Log.class.getName()));
+ System.out.println("io.trygvis.container.compiler.MyProcessor.getSupportedAnnotationTypes");
+ return new HashSet<>(asList(
+ Transactional.class.getName(),
+ Log.class.getName(),
+ Entity.class.getName()));
}
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
- Set<? extends Element> transactional = roundEnv.getElementsAnnotatedWith(Transactional.class);
+ System.out.println("io.trygvis.container.compiler.MyProcessor.process");
+ System.out.println("annotations = " + annotations);
+// Set<? extends Element> transactional = roundEnv.getElementsAnnotatedWith(Transactional.class);
TypeElement tx = elements.getTypeElement(Transactional.class.getCanonicalName());
- TypeElement log = elements.getTypeElement(Transactional.class.getCanonicalName());
+ TypeElement log = elements.getTypeElement(Log.class.getCanonicalName());
+ TypeElement entity = elements.getTypeElement(Entity.class.getCanonicalName());
- for (Element element : transactional) {
+ for (Element element : roundEnv.getRootElements()) {
try {
System.out.println("Processing: " + element);
for (AnnotationMirror annotationMirror : element.getAnnotationMirrors()) {
+ DeclaredType annotationType = annotationMirror.getAnnotationType();
- if (types.isSameType(tx.asType(), annotationMirror.getAnnotationType())) {
+ if (types.isSameType(tx.asType(), annotationType)) {
new TransactionalHandler(processingEnv).processTransactional((TypeElement) element);
}
- if (types.isSameType(log.asType(), annotationMirror.getAnnotationType())) {
+ if (types.isSameType(log.asType(), annotationType)) {
new LogHandler(processingEnv).processLog((TypeElement) element);
}
+ if (types.isSameType(entity.asType(), annotationType)) {
+ new EntityHandler(processingEnv).processEntity((TypeElement) element);
+ }
}
} catch (RuntimeException e) {
throw e;
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 2877e15..d24a697 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
@@ -17,8 +17,6 @@ import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
-import javax.lang.model.util.Elements;
-import javax.lang.model.util.Types;
import javax.tools.JavaFileObject;
import java.io.IOException;
import java.io.PrintWriter;
@@ -28,16 +26,10 @@ import java.util.List;
import static javax.lang.model.util.ElementFilter.constructorsIn;
import static org.springframework.util.StringUtils.collectionToDelimitedString;
-public class TransactionalHandler {
-
- private final ProcessingEnvironment processingEnv;
- private final Elements elements;
- private final Types types;
+public class TransactionalHandler extends AbstractHandler {
public TransactionalHandler(ProcessingEnvironment processingEnv) {
- this.processingEnv = processingEnv;
- this.elements = processingEnv.getElementUtils();
- this.types = processingEnv.getTypeUtils();
+ super(processingEnv);
}
public void processTransactional(TypeElement element) throws IOException {
@@ -46,80 +38,80 @@ public class TransactionalHandler {
Transactional transactional = element.getAnnotation(Transactional.class);
- String p = elements.getPackageOf(element).getQualifiedName().toString();
-
String className = targetClassName + "_Transactional";
- JavaFileObject sourceFile = processingEnv.getFiler().createSourceFile(p + "." + className, element);
-
- try (PrintWriter w = new PrintWriter(sourceFile.openWriter())) {
- ClassG g = new ClassG(p, className, targetClassName.toString());
- FieldRef transactionManager = g.addField(PlatformTransactionManager.class, "transactionManager");
+ String p = elements.getPackageOf(element).getQualifiedName().toString();
- for (ExecutableElement constructor : constructorsIn(elements.getAllMembers(element))) {
- if (!constructor.getModifiers().contains(Modifier.PUBLIC)) {
- continue;
- }
+ ClassG g = new ClassG(p, className, targetClassName.toString());
+ FieldRef transactionManager = g.addField(PlatformTransactionManager.class, "transactionManager");
- constructor(g, constructor, transactionManager);
+ for (ExecutableElement constructor : constructorsIn(elements.getAllMembers(element))) {
+ if (!constructor.getModifiers().contains(Modifier.PUBLIC)) {
+ continue;
}
- Name javaLangObjectName = elements.getTypeElement("java.lang.Object").getQualifiedName();
+ constructor(g, constructor, transactionManager);
+ }
+
+ Name javaLangObjectName = elements.getTypeElement("java.lang.Object").getQualifiedName();
- for (Element e : elements.getAllMembers(element)) {
- if (!(e instanceof ExecutableElement)) {
- continue;
- }
+ for (Element e : elements.getAllMembers(element)) {
+ if (!(e instanceof ExecutableElement)) {
+ continue;
+ }
- ExecutableElement ee = (ExecutableElement) e;
+ ExecutableElement ee = (ExecutableElement) e;
- TypeElement enclosingElement = (TypeElement) ee.getEnclosingElement();
+ TypeElement enclosingElement = (TypeElement) ee.getEnclosingElement();
- if (enclosingElement.getQualifiedName().equals(javaLangObjectName)) {
- continue;
- }
+ if (enclosingElement.getQualifiedName().equals(javaLangObjectName)) {
+ continue;
+ }
- if (ee.getSimpleName().toString().equals("<init>")) {
- continue;
- }
+ if (ee.getSimpleName().toString().equals("<init>")) {
+ continue;
+ }
- TypeMirror returnTypeMirror = ee.getReturnType();
+ TypeMirror returnTypeMirror = ee.getReturnType();
- TypeKind kind = returnTypeMirror.getKind();
+ TypeKind kind = returnTypeMirror.getKind();
- boolean isVoid = kind == TypeKind.VOID;
- TypeRef returnType = isVoid ? TypeRef.VOID : g.addImport(returnTypeMirror);
+ boolean isVoid = kind == TypeKind.VOID;
+ TypeRef returnType = isVoid ? TypeRef.VOID : g.addImport(returnTypeMirror);
- List<ParameterRef> parameters = new ArrayList<>();
- List<String> arguments = new ArrayList<>();
- for (VariableElement ve : ee.getParameters()) {
+ List<ParameterRef> parameters = new ArrayList<>();
+ 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()));
- arguments.add(ve.getSimpleName().toString());
- }
-
- List<String> body = new ArrayList<>();
- body.add((isVoid ? "" : "return ") + "transactionManager.doInTransaction(");
- body.add(" PlatformTransactionManager.TransactionIsolation.ISOLATION_" + transactional.isolation() + ",");
- body.add(" PlatformTransactionManager.TransactionPropagation.PROPAGATION_" + transactional.propagation() + ",");
- body.add(" new PlatformTransactionManager.TransactionTemplate<" + (isVoid ? "Object" : returnTypeMirror) + ">() {");
- body.add(" @Override");
- body.add(" public " + (isVoid ? "Object" : returnTypeMirror) + " doInTransaction() {");
- String targetInvocation = className + ".super." + ee.getSimpleName() + "(" + collectionToDelimitedString(arguments, ", ") + ");";
-
- if (isVoid) {
- body.add(" " + targetInvocation);
- body.add(" return null;");
- } else {
- body.add(" return " + targetInvocation);
- }
-
- body.add(" }");
- body.add(" });");
-
- g.addMethod(body, returnType, ee.getSimpleName().toString(), parameters.toArray(new ParameterRef[arguments.size()]));
+ TypeRef k = g.addImport(ve.asType());
+ parameters.add(new ParameterRef(k, ve.getSimpleName().toString()));
+ arguments.add(ve.getSimpleName().toString());
}
+
+ List<String> body = new ArrayList<>();
+ body.add((isVoid ? "" : "return ") + "transactionManager.doInTransaction(");
+ body.add(" PlatformTransactionManager.TransactionIsolation.ISOLATION_" + transactional.isolation() + ",");
+ body.add(" PlatformTransactionManager.TransactionPropagation.PROPAGATION_" + transactional.propagation() + ",");
+ body.add(" new PlatformTransactionManager.TransactionTemplate<" + (isVoid ? "Object" : returnTypeMirror) + ">() {");
+ body.add(" @Override");
+ body.add(" public " + (isVoid ? "Object" : returnTypeMirror) + " doInTransaction() {");
+ String targetInvocation = className + ".super." + ee.getSimpleName() + "(" + collectionToDelimitedString(arguments, ", ") + ");";
+
+ if (isVoid) {
+ body.add(" " + targetInvocation);
+ body.add(" return null;");
+ } else {
+ body.add(" return " + targetInvocation);
+ }
+
+ body.add(" }");
+ body.add(" });");
+
+ g.addMethod(body, returnType, ee.getSimpleName().toString(), parameters.toArray(new ParameterRef[arguments.size()]));
+ }
+
+ JavaFileObject sourceFile = processingEnv.getFiler().createSourceFile((p.length() == 0 ? "" : p + ".") + className, element);
+ try (PrintWriter w = new PrintWriter(sourceFile.openWriter())) {
g.write(w);
}
}
diff --git a/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/entity/EntityMirror.java b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/entity/EntityMirror.java
new file mode 100644
index 0000000..ae7077c
--- /dev/null
+++ b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/entity/EntityMirror.java
@@ -0,0 +1,38 @@
+package io.trygvis.container.compiler.entity;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class EntityMirror {
+ public final List<FieldMirror> fields = new ArrayList<>();
+ public final String tableName;
+
+ public EntityMirror(String tableName) {
+ this.tableName = tableName;
+ }
+
+ public void add(FieldMirror field) {
+ fields.add(field);
+ }
+
+ public static class FieldMirror {
+ private final String javaName;
+ public final String sqlName;
+ private final boolean notNull;
+
+ public FieldMirror(String javaName, String sqlName, boolean notNull) {
+ this.javaName = javaName;
+ this.sqlName = sqlName;
+ this.notNull = notNull;
+ }
+
+ @Override
+ public String toString() {
+ return "FieldMirror{" +
+ "javaName='" + javaName + '\'' +
+ ", sqlName='" + sqlName + '\'' +
+ ", notNull=" + notNull +
+ '}';
+ }
+ }
+}
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 13e1b03..cf68cba 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
@@ -2,6 +2,7 @@ package io.trygvis.container.compiler.model;
import javax.lang.model.type.TypeMirror;
import java.io.PrintWriter;
+import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@@ -18,10 +19,6 @@ 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;
@@ -74,7 +71,14 @@ public class ClassG {
public FieldRef addField(Class<?> klass, String name) {
TypeRef type = addImport(klass);
- FieldRef ref = new FieldRef(type, name);
+ FieldRef ref = new FieldRef(Modifier.PRIVATE | Modifier.FINAL, type, name);
+ fields.add(ref);
+ return ref;
+ }
+
+ public FieldRef addPublicFinalField(Class<?> klass, String name) {
+ TypeRef type = addImport(klass);
+ FieldRef ref = new FieldRef(Modifier.PUBLIC | Modifier.FINAL, type, name);
fields.add(ref);
return ref;
}
@@ -92,8 +96,10 @@ public class ClassG {
}
public void write(PrintWriter writer) {
- writer.println("package " + packageName + ";");
- writer.println();
+ if(packageName.length() > 0) {
+ writer.println("package " + packageName + ";");
+ writer.println();
+ }
for (TypeRef i : imports) {
if (i.isPrimitive()) {
continue;
@@ -101,10 +107,13 @@ public class ClassG {
writer.println("import " + i.canonicalName() + ";");
}
writer.println();
- writer.println("public class " + className + " extends " + extendsClass + " {");
+
+ String extendsString = extendsClass == null ? "" : " extends " + extendsClass;
+
+ writer.println("public class " + className + extendsString + " {");
for (FieldRef field : fields) {
writer.println();
- writer.println(" private final " + field.klass.name + " " + field.name + ";");
+ writer.println(" " + field.toJava() + ";");
}
for (Constructor constructor : constructors) {
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 29a2c51..c6b81a0 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
@@ -1,14 +1,22 @@
package io.trygvis.container.compiler.model;
+import java.lang.reflect.Modifier;
+
public class FieldRef implements Comparable<FieldRef> {
+ public final int modifiers;
public final TypeRef klass;
public final String name;
- public FieldRef(TypeRef klass, String name) {
+ public FieldRef(int modifiers, TypeRef klass, String name) {
+ this.modifiers = modifiers;
this.klass = klass;
this.name = name;
}
+ public String toJava() {
+ return Modifier.toString(modifiers) + " " + klass.name + " " + name;
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) return true;
diff --git a/container-compiler-plugin/src/test/java/io/trygvis/container/compiler/EntityHandlerTest.java b/container-compiler-plugin/src/test/java/io/trygvis/container/compiler/EntityHandlerTest.java
new file mode 100644
index 0000000..98fcaea
--- /dev/null
+++ b/container-compiler-plugin/src/test/java/io/trygvis/container/compiler/EntityHandlerTest.java
@@ -0,0 +1,27 @@
+package io.trygvis.container.compiler;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static io.trygvis.container.compiler.EntityHandler.sqlName;
+import static org.fest.assertions.Assertions.assertThat;
+
+@Test(singleThreaded = false)
+public class EntityHandlerTest {
+
+ @DataProvider(name = "sqlName", parallel = true)
+ public static Object[][] SqlNameDataProvider() {
+ return new Object[][] {
+ new Object[]{"MyClass", "my_class"},
+ new Object[]{"myField", "my_field"},
+ new Object[]{"name", "name"},
+ new Object[]{"first_name", "first_name"},
+ new Object[]{"first_name_", "first_name_"},
+ };
+ }
+
+ @Test(dataProvider = "sqlName")
+ public void testSqlName(String input, String output) throws Exception {
+ assertThat(sqlName(input)).isEqualTo(output);
+ }
+}
diff --git a/container-compiler-plugin/src/test/java/io/trygvis/container/compiler/InMemoryJavaFileManager.java b/container-compiler-plugin/src/test/java/io/trygvis/container/compiler/InMemoryJavaFileManager.java
new file mode 100644
index 0000000..e476d3e
--- /dev/null
+++ b/container-compiler-plugin/src/test/java/io/trygvis/container/compiler/InMemoryJavaFileManager.java
@@ -0,0 +1,74 @@
+package io.trygvis.container.compiler;
+
+import org.apache.commons.io.output.ByteArrayOutputStream;
+
+import javax.tools.FileObject;
+import javax.tools.ForwardingJavaFileManager;
+import javax.tools.JavaFileObject;
+import javax.tools.SimpleJavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import java.io.CharArrayWriter;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.Writer;
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+
+public class InMemoryJavaFileManager extends ForwardingJavaFileManager<StandardJavaFileManager> {
+ public final Map<String, String> codes = new HashMap<>();
+
+ public InMemoryJavaFileManager(StandardJavaFileManager standardFileManager) {
+ super(standardFileManager);
+ }
+
+ @Override
+ public FileObject getFileForOutput(Location location, String packageName, String relativeName, FileObject sibling) throws IOException {
+ System.out.println("io.trygvis.container.compiler.InMemoryJavaFileManager.getFileForOutput");
+ throw new RuntimeException("");
+ }
+
+ @Override
+ public JavaFileObject getJavaFileForOutput(Location location, final String className, JavaFileObject.Kind kind, FileObject sibling) throws IOException {
+ System.out.println("io.trygvis.container.compiler.InMemoryJavaFileManager.getJavaFileForOutput");
+ return new SimpleJavaFileObject(URI.create("wat://woot/" + className.replace('.', '/') + ".java"), kind) {
+ String code;
+
+ @Override
+ public Writer openWriter() throws IOException {
+ return new CharArrayWriter() {
+ @Override
+ public void close() {
+ super.close();
+ System.out.println("Closing writer to: className = " + className);
+ code = super.toString();
+ codes.put(className, code);
+ }
+ };
+ }
+
+ @Override
+ public OutputStream openOutputStream() throws IOException {
+ return new ByteArrayOutputStream() {
+ @Override
+ public void close() throws IOException {
+ super.close();
+ // ignored for now
+// System.out.println("Closing output stream to: className = " + className);
+// System.out.println(new String(super.toByteArray()));
+ }
+ };
+ }
+
+ @Override
+ public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
+ if(code == null) {
+ throw new FileNotFoundException(className);
+ }
+
+ return code;
+ }
+ };
+ }
+}
diff --git a/container-compiler-plugin/src/test/java/io/trygvis/container/compiler/ProcessorTest.java b/container-compiler-plugin/src/test/java/io/trygvis/container/compiler/ProcessorTest.java
new file mode 100644
index 0000000..e070f3c
--- /dev/null
+++ b/container-compiler-plugin/src/test/java/io/trygvis/container/compiler/ProcessorTest.java
@@ -0,0 +1,83 @@
+package io.trygvis.container.compiler;
+
+import org.apache.commons.io.IOUtils;
+import org.testng.annotations.Test;
+
+import javax.tools.Diagnostic;
+import javax.tools.DiagnosticCollector;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.SimpleJavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.ToolProvider;
+import java.net.URI;
+import java.nio.charset.Charset;
+import java.util.Arrays;
+import java.util.Locale;
+
+import static java.util.Collections.singletonList;
+import static org.fest.assertions.Assertions.assertThat;
+
+public class ProcessorTest {
+ Charset UTF_8 = Charset.forName("utf-8");
+
+ /**
+ * A file object used to represent source coming from a string.
+ */
+ public class JavaSourceFromString extends SimpleJavaFileObject {
+ /**
+ * The source code of this "file".
+ */
+ final String code;
+
+ /**
+ * Constructs a new JavaSourceFromString.
+ *
+ * @param name the name of the compilation unit represented by this file object
+ * @param code the source code for the compilation unit represented by this file object
+ */
+ JavaSourceFromString(String name, String code) {
+ super(URI.create("string:///" + name.replace('.', '/') + JavaFileObject.Kind.SOURCE.extension),
+ JavaFileObject.Kind.SOURCE);
+ this.code = code;
+ }
+
+ @Override
+ public CharSequence getCharContent(boolean ignoreEncodingErrors) {
+ return code;
+ }
+ }
+
+ @Test
+ public void testBasic() throws Exception {
+ JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+
+ DiagnosticCollector<JavaFileObject> collector = new DiagnosticCollector<>();
+ StandardJavaFileManager standardFileManager = compiler.getStandardFileManager(collector, Locale.ENGLISH, UTF_8);
+
+ InMemoryJavaFileManager fileManager = new InMemoryJavaFileManager(standardFileManager);
+
+ JavaSourceFromString myEntity = new JavaSourceFromString("Person", IOUtils.toString(getClass().getResource("/Person.java"), UTF_8));
+
+ JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, collector, null,
+ null, singletonList(myEntity));
+
+ task.setProcessors(Arrays.asList(new MyProcessor()));
+
+ Boolean result = task.call();
+
+ for (Diagnostic<? extends JavaFileObject> diagnostic : collector.getDiagnostics()) {
+// System.out.println("diagnostic = " + diagnostic);
+ System.out.println("diagnostic.source = ->" + diagnostic.getSource().getName() + "<-");
+ System.out.println("diagnostic.message = " + diagnostic.getMessage(Locale.ENGLISH));
+ }
+
+ assertThat(collector.getDiagnostics()).isEmpty();
+ assertThat(result).isTrue();
+
+ fileManager.close();
+
+ assertThat(fileManager.codes.keySet()).containsOnly("Person_Sql");
+ System.out.println(fileManager.codes.get("Person_Sql"));
+ }
+}
diff --git a/container-compiler-plugin/src/test/resources/Car.java b/container-compiler-plugin/src/test/resources/Car.java
new file mode 100644
index 0000000..5661bc2
--- /dev/null
+++ b/container-compiler-plugin/src/test/resources/Car.java
@@ -0,0 +1,6 @@
+import javax.persistence.Entity;
+
+@Entity
+public class Car {
+ private int year;
+}
diff --git a/container-compiler-plugin/src/test/resources/Person.java b/container-compiler-plugin/src/test/resources/Person.java
new file mode 100644
index 0000000..740b42d
--- /dev/null
+++ b/container-compiler-plugin/src/test/resources/Person.java
@@ -0,0 +1,26 @@
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.OrderBy;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+@Entity
+public class Person {
+ @Id
+ private Long id;
+
+ private Date birthDate;
+
+ @ManyToOne
+ private Person mother;
+
+ @ManyToOne
+ private Person father;
+
+ @OneToMany(mappedBy = "id")
+ @OrderBy("birthDate asc")
+ private List<Person> children = new ArrayList<>();
+}
diff --git a/container-core/pom.xml b/container-core/pom.xml
index e16c761..d17a86a 100644
--- a/container-core/pom.xml
+++ b/container-core/pom.xml
@@ -19,6 +19,11 @@
<version>${version.spring}</version>
</dependency>
<dependency>
+ <groupId>org.hibernate.javax.persistence</groupId>
+ <artifactId>hibernate-jpa-2.0-api</artifactId>
+ <version>1.0.1.Final</version>
+ </dependency>
+ <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${version.spring}</version>
diff --git a/myapp/src/main/java/io/trygvis/container/myapp/MyEntity.java b/myapp/src/main/java/io/trygvis/container/myapp/MyEntity.java
new file mode 100644
index 0000000..5eeface
--- /dev/null
+++ b/myapp/src/main/java/io/trygvis/container/myapp/MyEntity.java
@@ -0,0 +1,10 @@
+package io.trygvis.container.myapp;
+
+import javax.persistence.Entity;
+
+@Entity
+public class MyEntity {
+ public Long id;
+
+ public String name;
+}