From e78c0a1e4a4ebc71502dceccc9ae640862b7ce9e Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Sun, 11 Aug 2013 22:35:02 +0200 Subject: o Overhauling inheritance, adding a decent start of support for @MappedSuperclass. --- .../container/compiler/ElementComparator.java | 11 ++ .../trygvis/container/compiler/EntityHandler.java | 129 +++++++++++++++------ .../io/trygvis/container/compiler/MyProcessor.java | 24 ++-- .../trygvis/container/compiler/SqlUnitModel.java | 13 ++- .../container/compiler/TypeMirrorComparator.java | 11 ++ .../java/io/trygvis/container/compiler/Utils.java | 16 +++ 6 files changed, 152 insertions(+), 52 deletions(-) create mode 100644 container-compiler-plugin/src/main/java/io/trygvis/container/compiler/ElementComparator.java create mode 100644 container-compiler-plugin/src/main/java/io/trygvis/container/compiler/TypeMirrorComparator.java (limited to 'container-compiler-plugin/src/main/java/io/trygvis/container') diff --git a/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/ElementComparator.java b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/ElementComparator.java new file mode 100644 index 0000000..d1ed776 --- /dev/null +++ b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/ElementComparator.java @@ -0,0 +1,11 @@ +package io.trygvis.container.compiler; + +import javax.lang.model.element.Element; +import java.util.Comparator; + +class ElementComparator implements Comparator { + @Override + public int compare(Element o1, Element o2) { + return o1.asType().toString().compareTo(o2.asType().toString()); + } +} 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 9cb85e9..ba9f100 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 @@ -25,11 +25,13 @@ import javax.lang.model.type.TypeMirror; import javax.persistence.Id; import javax.persistence.SequenceGenerator; import java.util.ArrayList; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; +import java.util.TreeSet; import static io.trygvis.container.compiler.Utils.toFieldName; import static io.trygvis.container.compiler.Utils.writeFile; @@ -95,22 +97,60 @@ public class EntityHandler extends AbstractHandler { sqlUnit.setName(name); } - public void recordEntity(TypeElement element) throws Exception { + Set mappedSuperclasses = new HashSet<>(); + Set entities = new HashSet<>(); + + public void record(TypeElement element, boolean superclass) throws Exception { + (superclass ? mappedSuperclasses : entities).add(element); + } + + private EntityMirror getEntity(TypeElement element, boolean superclass) throws Exception { + EntityMirror entity = sqlUnit.entity(element); + if (entity != null) { + return entity; + } + + entity = buildMirror(element, superclass); + sqlUnit.add(entity, element); + return entity; + } + + public EntityMirror buildMirror(TypeElement element, boolean concrete) throws Exception { + EntityMirror superEntity = null; + + Set ancestry = new TreeSet<>(new TypeMirrorComparator()); + ancestry.add(element.asType()); + TypeMirror superType = element.getSuperclass(); + while (!superType.toString().equals("java.lang.Object")) { + TypeElement superTypeMirror = elements.getTypeElement(superType.toString()); + if (superTypeMirror == null) { + throw new CompilerException(element, "Couldn't find element for super class: " + element.getSuperclass()); + } + + if (mappedSuperclasses.contains(superTypeMirror)) { + superEntity = getEntity(superTypeMirror, false); + break; + } + ancestry.add(superType); + superType = superTypeMirror.getSuperclass(); + } + EntityMirror entity = new EntityMirror( generatorConfiguration, new TypeRef(types.getDeclaredType(element)), - sqlName(element.getSimpleName().toString())); + concrete, + superEntity, + concrete ? Utils.sqlName(element.getSimpleName().toString()) : null); Map getters = new TreeMap<>(); Map setters = new TreeMap<>(); for (ExecutableElement m : methodsIn(elements.getAllMembers(element))) { - String name = m.getSimpleName().toString(); - if (name.length() < 4 || !isUpperCase(name.charAt(3))) { + if (!ancestry.contains(m.getEnclosingElement().asType())) { continue; } - String declaringType = ((TypeElement) m.getEnclosingElement()).getQualifiedName().toString(); - if (declaringType.equals("java.lang.Object")) { + String name = m.getSimpleName().toString(); + if (name.length() < 4 || !isUpperCase(name.charAt(3))) { continue; } @@ -126,6 +166,11 @@ public class EntityHandler extends AbstractHandler { } for (VariableElement f : fieldsIn(elements.getAllMembers(element))) { + System.out.println("f.getEnclosingElement() = " + f.getEnclosingElement()); + if (!ancestry.contains(f.getEnclosingElement().asType())) { + continue; + } + String name = f.getSimpleName().toString(); ExecutableElement getter = getters.remove(name); ExecutableElement setter = setters.remove(name); @@ -141,6 +186,11 @@ public class EntityHandler extends AbstractHandler { String name = e.getKey(); ExecutableElement getter = e.getValue(); ExecutableElement setter = setters.remove(name); + + if (!ancestry.contains(getter.getEnclosingElement().asType())) { + continue; + } + FieldMirror field = fromElement(generatorConfiguration, null, getter, setter); if (field == null) { continue; @@ -167,12 +217,16 @@ public class EntityHandler extends AbstractHandler { processSequenceGenerators(element); - // ----------------------------------------------------------------------- - // Validation - // ----------------------------------------------------------------------- + return entity; + } + + public void validate(Element element, EntityMirror entity) { + if (!entity.concrete) { + return; + } List idFields = new ArrayList<>(); - for (FieldMirror field : entity.fields) { + for (FieldMirror field : entity.getFields()) { if (field.id) { idFields.add(field); } @@ -184,9 +238,8 @@ public class EntityHandler extends AbstractHandler { if (idFields.size() != 1) { throw new CompilerException(element, "This implementation only support a single @Id annotated field."); } - entity.setIdType(idFields.get(0).type); - sqlUnit.add(entity, element); + entity.setIdType(idFields.get(0).type); } private void processSequenceGenerators(Element element) { @@ -219,7 +272,7 @@ public class EntityHandler extends AbstractHandler { } } if (name != null) { - sequenceName = sequenceName == null ? sqlName(name) : sequenceName; + sequenceName = sequenceName == null ? Utils.sqlName(name) : sequenceName; sqlUnit.add(new SequenceMirror(name, sequenceName, initialValue, allocationSize), element); } } @@ -247,7 +300,7 @@ public class EntityHandler extends AbstractHandler { } else { setterType = setter != null ? SetterType.METHOD : SetterType.FIELD; } - getterType = GetterType.FIELD; + getterType = getter != null ? GetterType.METHOD : GetterType.FIELD; type = new TypeRef(var.asType()); element = types.asElement(var.asType()); javaName = var.getSimpleName().toString(); @@ -274,7 +327,7 @@ public class EntityHandler extends AbstractHandler { } javaName = toFieldName(getter.getSimpleName().toString()); } - sqlName = sqlName(javaName); + sqlName = Utils.sqlName(javaName); // Register type handler if this is an enum if (element != null && element.getKind() == ElementKind.ENUM) { @@ -292,10 +345,7 @@ public class EntityHandler extends AbstractHandler { FieldMirror field; if (primitive) { - System.out.println("type = " + type); TypeHandler typeHandler = generatorConfiguration.typeHandler(type); - System.out.println("typeHandler = " + typeHandler); - System.out.println("typeHandler.typeName() = " + typeHandler.typeName()); // TODO: check for configuration conflict notNull = !typeHandler.nullable; field = new FieldMirror(PRIMITIVE, setterType, getterType, type, javaName, sqlName, id, notNull, unique); @@ -312,31 +362,34 @@ public class EntityHandler extends AbstractHandler { } public void phase3(boolean errorRaised) throws Exception { - try { - for (EntityMirror entity : sqlUnit.getEntities().values()) { + for (TypeElement mappedSuperclass : mappedSuperclasses) { + getEntity(mappedSuperclass, false); + } + + for (TypeElement entity : entities) { + getEntity(entity, true); + } + + for (EntityMirror entity : sqlUnit.getEntities().values()) { + try { + validate(sqlUnit.element(entity), entity); + + if (!entity.concrete) { + continue; + } + + System.out.println("entity.type = " + entity.type); DaoGenerator daoGenerator = new DaoGenerator(generatorConfiguration, sqlUnit, entity); writeFile(processingEnv, daoGenerator.generate(), sqlUnit.element(entity)); writeFile(processingEnv, daoGenerator.generateRow(), sqlUnit.element(entity)); + } catch (CompilerException | InternalErrorException e) { + // Ignore any exceptions if we had an error from before + if (errorRaised) { + continue; + } + throw e; } - } catch (CompilerException | InternalErrorException e) { - // Ignore any exceptions if we had an error from before - if (errorRaised) { - return; - } - throw e; - } - } - - 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(); } private AnnotationMirror findAnnotation(Class c, Element type) { 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 24cacf4..80b7283 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 @@ -1,10 +1,8 @@ package io.trygvis.container.compiler; import io.trygvis.container.log.Log; -import io.trygvis.persistence.EntityMirror; import io.trygvis.persistence.SqlEntity; import io.trygvis.persistence.SqlEntitySet; -import io.trygvis.persistence.generators.DaoGenerator; import org.springframework.transaction.annotation.Transactional; import javax.annotation.processing.Completion; @@ -23,14 +21,15 @@ import javax.lang.model.util.ElementFilter; import javax.lang.model.util.Elements; import javax.lang.model.util.Types; import javax.persistence.Entity; +import javax.persistence.MappedSuperclass; import javax.tools.Diagnostic; import java.util.HashSet; import java.util.Set; import static io.trygvis.container.compiler.Utils.writeFile; import static io.trygvis.persistence.generators.SequencesGenerator.generateSequences; -import static io.trygvis.persistence.generators.SqlSessionGenerator.generateSqlSession; import static io.trygvis.persistence.generators.SqlSessionFactoryGenerator.generateSqlSessionFactory; +import static io.trygvis.persistence.generators.SqlSessionGenerator.generateSqlSession; import static java.util.Arrays.asList; import static java.util.Collections.emptyList; import static java.util.Collections.emptySet; @@ -100,6 +99,7 @@ public class MyProcessor implements Processor { } boolean first = true; + public boolean work(RoundEnvironment roundEnv) throws Exception { if (!first) { return false; @@ -109,6 +109,7 @@ public class MyProcessor implements Processor { TypeElement tx = elements.getTypeElement(Transactional.class.getCanonicalName()); TypeElement log = elements.getTypeElement(Log.class.getCanonicalName()); TypeElement entity = elements.getTypeElement(Entity.class.getCanonicalName()); + TypeElement mappedSuperclass = elements.getTypeElement(MappedSuperclass.class.getCanonicalName()); SqlUnitModel unit = new SqlUnitModel(); EntityHandler entityHandler = new EntityHandler(processingEnv, unit); @@ -129,15 +130,16 @@ public class MyProcessor implements Processor { if (types.isSameType(log.asType(), annotationType)) { new LogHandler(processingEnv).processLog((TypeElement) element); } - if (types.isSameType(entity.asType(), annotationType)) { - try { - entityHandler.recordEntity((TypeElement) element); - } catch (CompilerException e) { -// e.printStackTrace(System.out); - Messager messager = processingEnv.getMessager(); - messager.printMessage(Diagnostic.Kind.ERROR, e.getMessage(), e.element); - hadErrors = true; + try { + if (types.isSameType(entity.asType(), annotationType)) { + entityHandler.record((TypeElement) element, false); + } else if (types.isSameType(mappedSuperclass.asType(), annotationType)) { + entityHandler.record((TypeElement) element, true); } + } catch (CompilerException e) { + Messager messager = processingEnv.getMessager(); + messager.printMessage(Diagnostic.Kind.ERROR, e.getMessage(), e.element); + hadErrors = true; } } } diff --git a/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/SqlUnitModel.java b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/SqlUnitModel.java index 717715e..1c0f538 100644 --- a/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/SqlUnitModel.java +++ b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/SqlUnitModel.java @@ -10,7 +10,8 @@ import java.util.TreeMap; public class SqlUnitModel { private Map entities = new TreeMap<>(); - private Map entityElements = new TreeMap<>(); + private Map elementToEntity = new TreeMap<>(new ElementComparator()); + private Map entityToElement = new TreeMap<>(); private Map sequences = new TreeMap<>(); private Map sequenceElements = new TreeMap<>(); private String packageName; @@ -44,7 +45,8 @@ public class SqlUnitModel { public SqlUnitModel add(EntityMirror entity, Element element) { entities.put(entity.type, entity); - entityElements.put(entity, element); + entityToElement.put(entity, element); + elementToEntity.put(element, entity); return this; } @@ -70,7 +72,11 @@ public class SqlUnitModel { } public Element element(EntityMirror entity) { - return entityElements.get(entity); + return entityToElement.get(entity); + } + + public EntityMirror entity(Element element) { + return elementToEntity.get(element); } // ----------------------------------------------------------------------- @@ -120,4 +126,5 @@ public class SqlUnitModel { public Element element(SequenceMirror sequence) { return sequenceElements.get(sequence); } + } diff --git a/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/TypeMirrorComparator.java b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/TypeMirrorComparator.java new file mode 100644 index 0000000..325eeaf --- /dev/null +++ b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/TypeMirrorComparator.java @@ -0,0 +1,11 @@ +package io.trygvis.container.compiler; + +import javax.lang.model.type.TypeMirror; +import java.util.Comparator; + +class TypeMirrorComparator implements Comparator { + @Override + public int compare(TypeMirror o1, TypeMirror o2) { + return o1.toString().compareTo(o2.toString()); + } +} diff --git a/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/Utils.java b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/Utils.java index 3478581..0cac828 100644 --- a/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/Utils.java +++ b/container-compiler-plugin/src/main/java/io/trygvis/container/compiler/Utils.java @@ -17,6 +17,7 @@ import java.util.ArrayList; import java.util.List; import static io.trygvis.container.compiler.model.ClassG.addAll; +import static java.lang.Character.isUpperCase; import static java.lang.Character.toLowerCase; import static java.lang.Character.toUpperCase; import static org.apache.commons.lang.StringUtils.stripEnd; @@ -116,4 +117,19 @@ public class Utils { newBody.add("}"); return newBody; } + + public static String sqlName(String javaName) { + StringBuilder builder = new StringBuilder(); + for (char c : javaName.toCharArray()) { + if (isUpperCase(c) && builder.length() > 0) { + builder.append("_"); + } + if (Character.isLetterOrDigit(c)) { + builder.append(toLowerCase(c)); + } else { + builder.append('_'); + } + } + return builder.toString(); + } } -- cgit v1.2.3