From f13a653d5233dc4c14ddba879fa2a1ec7ce92260 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Westk=C3=A4mper?= Date: Sat, 5 Nov 2011 18:50:12 +0200 Subject: [PATCH] worked on improving Querydsl APT --- .../mysema/query/apt/ExtendedTypeFactory.java | 116 +--- .../java/com/mysema/query/apt/Processor.java | 555 ++++++++---------- ...ntHandler.java => TypeElementHandler.java} | 7 +- .../com/mysema/query/apt/TypeExtractor.java | 106 ++-- .../com/mysema/query/apt/VisitorConfig.java | 16 +- 5 files changed, 334 insertions(+), 466 deletions(-) rename querydsl-apt/src/main/java/com/mysema/query/apt/{ElementHandler.java => TypeElementHandler.java} (97%) diff --git a/querydsl-apt/src/main/java/com/mysema/query/apt/ExtendedTypeFactory.java b/querydsl-apt/src/main/java/com/mysema/query/apt/ExtendedTypeFactory.java index 7e26ed095..bca4fd60a 100644 --- a/querydsl-apt/src/main/java/com/mysema/query/apt/ExtendedTypeFactory.java +++ b/querydsl-apt/src/main/java/com/mysema/query/apt/ExtendedTypeFactory.java @@ -46,7 +46,6 @@ import com.mysema.query.codegen.EntityType; import com.mysema.query.codegen.QueryTypeFactory; import com.mysema.query.codegen.Supertype; import com.mysema.query.codegen.TypeMappings; -import com.mysema.util.ClassPathUtils; /** * ExtendedTypeFactory is a factory for APT inspection based Type creation @@ -66,7 +65,7 @@ public final class ExtendedTypeFactory { private final ProcessingEnvironment env; - private final TypeElement numberType, comparableType; + private final TypeMirror numberType, comparableType, collectionType, setType, listType, mapType; private final TypeMappings typeMappings; @@ -78,17 +77,7 @@ public final class ExtendedTypeFactory { @Override public Type visitPrimitive(PrimitiveType primitiveType, Boolean p) { - switch (primitiveType.getKind()) { - case BOOLEAN: return Types.BOOLEAN; - case BYTE: return Types.BYTE; - case CHAR: return Types.CHARACTER; - case DOUBLE: return Types.DOUBLE; - case FLOAT: return Types.FLOAT; - case INT: return Types.INTEGER; - case LONG: return Types.LONG; - case SHORT: return Types.SHORT; - } - return null; + return visit(env.getTypeUtils().boxedClass(primitiveType).asType(), p); } @Override @@ -179,18 +168,7 @@ public final class ExtendedTypeFactory { @Override public List visitPrimitive(PrimitiveType t, Boolean p) { - // TODO : optimize - switch (t.getKind()) { - case BOOLEAN: return Collections.singletonList("Boolean"); - case BYTE: return Collections.singletonList("Byte"); - case CHAR: return Collections.singletonList("Character"); - case DOUBLE: return Collections.singletonList("Double"); - case FLOAT: return Collections.singletonList("Float"); - case INT: return Collections.singletonList("Integer"); - case LONG: return Collections.singletonList("Long"); - case SHORT: return Collections.singletonList("Short"); - } - return null; + return visit(env.getTypeUtils().boxedClass(t).asType(), p); } @Override @@ -256,10 +234,9 @@ public final class ExtendedTypeFactory { public List visitNoType(NoType t, Boolean p) { return Collections.singletonList("Object"); } - }; - + public ExtendedTypeFactory( ProcessingEnvironment env, Configuration configuration, @@ -269,14 +246,20 @@ public final class ExtendedTypeFactory { this.env = env; this.defaultType = Types.OBJECT; this.entityAnnotations = annotations; - this.numberType = env.getElementUtils().getTypeElement(Number.class.getName()); - this.comparableType = env.getElementUtils().getTypeElement(Comparable.class.getName()); + this.numberType = getErasedType(Number.class); + this.comparableType = getErasedType(Comparable.class); + this.collectionType = getErasedType(Collection.class); + this.listType = getErasedType(List.class); + this.setType = getErasedType(Set.class); + this.mapType = getErasedType(Map.class); this.typeMappings = typeMappings; this.queryTypeFactory = queryTypeFactory; } + private TypeMirror getErasedType(Class clazz) { + return env.getTypeUtils().erasure(env.getElementUtils().getTypeElement(clazz.getName()).asType()); + } - private Type createType(TypeElement typeElement, TypeCategory category, List typeArgs, boolean deep) { String name = typeElement.getQualifiedName().toString(); String simpleName = typeElement.getSimpleName().toString(); @@ -324,10 +307,10 @@ public final class ExtendedTypeFactory { String name = typeElement.getQualifiedName().toString(); TypeCategory typeCategory = TypeCategory.get(name); - if (typeCategory != TypeCategory.NUMERIC && isImplemented(typeElement, comparableType) && isSubType(typeElement, numberType)) { + if (typeCategory != TypeCategory.NUMERIC && isAssignable(typeElement.asType(), comparableType) && isSubType(typeElement.asType(), numberType)) { typeCategory = TypeCategory.NUMERIC; - } else if (!typeCategory.isSubCategoryOf(TypeCategory.COMPARABLE) && isImplemented(typeElement, comparableType)) { + } else if (!typeCategory.isSubCategoryOf(TypeCategory.COMPARABLE) && isAssignable(typeElement.asType(), comparableType)) { typeCategory = TypeCategory.COMPARABLE; } if (typeCategory == TypeCategory.SIMPLE) { @@ -401,18 +384,6 @@ public final class ExtendedTypeFactory { return new SimpleType(Types.MAP, keyType, valueType); } - private Type createCollectionType(String simpleName, Iterator typeMirrors, boolean deep) { - return createCollectionType(Types.COLLECTION, simpleName, typeMirrors, deep); - } - - private Type createListType(String simpleName, Iterator typeMirrors, boolean deep) { - return createCollectionType(Types.LIST, simpleName, typeMirrors, deep); - } - - private Type createSetType(String simpleName, Iterator typeMirrors, boolean deep) { - return createCollectionType(Types.SET, simpleName, typeMirrors, deep); - } - private Type createCollectionType(Type baseType, String simpleName, Iterator typeMirrors, boolean deep) { if (!typeMirrors.hasNext()){ return new SimpleType(baseType, defaultType); @@ -510,28 +481,24 @@ public final class ExtendedTypeFactory { return createType(typeElement, TypeCategory.ENTITY, declaredType.getTypeArguments(), deep); } } - - String name = typeElement.getQualifiedName().toString(); + String simpleName = typeElement.getSimpleName().toString(); Iterator i = declaredType.getTypeArguments().iterator(); - Class cl = ClassPathUtils.safeClassForName(name); - - if (cl == null) { // class not available - return createType(typeElement, TypeCategory.get(name), declaredType.getTypeArguments(), deep); - - } else if (Map.class.isAssignableFrom(cl)) { + + if (isAssignable(declaredType, mapType)) { return createMapType(simpleName, i, deep); - } else if (List.class.isAssignableFrom(cl)) { - return createListType(simpleName, i, deep); + } else if (isAssignable(declaredType, listType)) { + return createCollectionType(Types.LIST, simpleName, i, deep); - } else if (Set.class.isAssignableFrom(cl)) { - return createSetType(simpleName, i, deep); + } else if (isAssignable(declaredType, setType)) { + return createCollectionType(Types.SET, simpleName, i, deep); - } else if (Collection.class.isAssignableFrom(cl)) { - return createCollectionType(simpleName, i, deep); + } else if (isAssignable(declaredType, collectionType)) { + return createCollectionType(Types.COLLECTION, simpleName, i, deep); } else { + String name = typeElement.getQualifiedName().toString(); return createType(typeElement, TypeCategory.get(name), declaredType.getTypeArguments(), deep); } } @@ -578,38 +545,13 @@ public final class ExtendedTypeFactory { doubleIndexEntities = doubleIndex; return superTypes; } - - // TODO : simplify this - private boolean isImplemented(TypeElement type, TypeElement iface) { - for (TypeMirror t : type.getInterfaces()) { - String name = t.toString(); - if (name.contains("<")) { - name = name.substring(0, name.indexOf('<')); - } - // interface is directly implemented - if (name.equals(iface.getQualifiedName().toString())) { - return true; - } - } - if (type.getSuperclass() != null) { - TypeElement superType = (TypeElement) env.getTypeUtils().asElement(type.getSuperclass()); - if (superType != null) { - return isImplemented(superType, iface); - } - superType = env.getElementUtils().getTypeElement(type.getSuperclass().toString()); - if (superType != null) { - return isImplemented(superType, iface); - } else { - return false; - } - } else { - return false; - } + private boolean isAssignable(TypeMirror type, TypeMirror iface) { + return env.getTypeUtils().isAssignable(type, iface); } - private boolean isSubType(TypeElement type1, TypeElement type2) { - return env.getTypeUtils().isSubtype(type1.asType(), type2.asType()); + private boolean isSubType(TypeMirror type1, TypeMirror type2) { + return env.getTypeUtils().isSubtype(type1, type2); } private TypeMirror normalize(TypeMirror type) { diff --git a/querydsl-apt/src/main/java/com/mysema/query/apt/Processor.java b/querydsl-apt/src/main/java/com/mysema/query/apt/Processor.java index 07cdced56..b5b190390 100644 --- a/querydsl-apt/src/main/java/com/mysema/query/apt/Processor.java +++ b/querydsl-apt/src/main/java/com/mysema/query/apt/Processor.java @@ -9,7 +9,16 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.Writer; import java.lang.annotation.Annotation; -import java.util.*; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Deque; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; import javax.annotation.Nullable; import javax.annotation.processing.Filer; @@ -29,10 +38,10 @@ import javax.lang.model.type.NoType; import javax.lang.model.type.TypeMirror; import javax.lang.model.util.ElementFilter; import javax.lang.model.util.Elements; +import javax.tools.Diagnostic.Kind; import javax.tools.FileObject; import javax.tools.JavaFileObject; import javax.tools.StandardLocation; -import javax.tools.Diagnostic.Kind; import com.mysema.codegen.JavaWriter; import com.mysema.codegen.model.Parameter; @@ -41,7 +50,6 @@ import com.mysema.codegen.model.Type; import com.mysema.codegen.model.TypeCategory; import com.mysema.commons.lang.Assert; import com.mysema.query.annotations.QueryDelegate; -import com.mysema.query.annotations.QueryEntities; import com.mysema.query.annotations.QueryExclude; import com.mysema.query.annotations.QueryProjection; import com.mysema.query.annotations.Variables; @@ -53,7 +61,6 @@ import com.mysema.query.codegen.Serializer; import com.mysema.query.codegen.SerializerConfig; import com.mysema.query.codegen.Supertype; import com.mysema.query.codegen.TypeMappings; -import com.mysema.util.BeanUtils; /** * Processor handles the actual work in the Querydsl APT module @@ -84,7 +91,7 @@ public class Processor { private final Map projectionTypes = new HashMap(); - private final ElementHandler elementHandler; + private final TypeElementHandler elementHandler; private final Map embeddables = new HashMap(); @@ -98,6 +105,8 @@ public class Processor { private final ExtendedTypeFactory typeFactory; + private final TypeExtractor typeExtractor = new TypeExtractor(true); + /** * Create a new Processor instance * @@ -121,7 +130,7 @@ public class Processor { TypeMappings typeMappings = configuration.getTypeMappings(); QueryTypeFactory queryTypeFactory = configuration.getQueryTypeFactory(); this.typeFactory = new ExtendedTypeFactory(env, configuration, entityAnnotations, typeMappings, queryTypeFactory); - this.elementHandler = new ElementHandler(configuration, typeFactory, typeMappings, queryTypeFactory); + this.elementHandler = new TypeElementHandler(configuration, typeFactory, typeMappings, queryTypeFactory); } public void process() { @@ -134,6 +143,7 @@ public class Processor { } for (String key : entityTypes.keySet()) { + actualSupertypes.remove(key); extensionTypes.remove(key); embeddables.remove(key); } @@ -153,8 +163,10 @@ public class Processor { processFromProperties(); } + boolean hasEmbeddableAnnotation = configuration.getEmbeddableAnnotation() != null; + if (configuration.getSuperTypeAnnotation() != null) { - processSupertypes(); + process(configuration.getSuperTypeAnnotation(), hasEmbeddableAnnotation, actualSupertypes); } if (configuration.getEmbeddedAnnotation() != null) { @@ -162,76 +174,154 @@ public class Processor { } if (configuration.getEmbeddableAnnotation() != null) { - processEmbeddables(); + process(configuration.getEmbeddableAnnotation(), false, embeddables); } if (configuration.getEntitiesAnnotation() != null) { processEntitiesFromPackage(); } - processEntities(); + process(configuration.getEntityAnnotation(), hasEmbeddableAnnotation, entityTypes); processProjectionTypes(); } + + /** + * Get the elements with the given annotation type + * + * @param a + * @return + */ + private Set getElements(Class a) { + return roundEnv.getElementsAnnotatedWith(a); + } private void processExclusions() { - for (Element element : roundEnv.getElementsAnnotatedWith(QueryExclude.class)) { + for (Element element : getElements(QueryExclude.class)) { if (element instanceof PackageElement) { configuration.addExcludedPackage(((PackageElement)element).getQualifiedName().toString()); - } else { + } else if (element instanceof TypeElement) { configuration.addExcludedClass(((TypeElement)element).getQualifiedName().toString()); + } else { + throw new IllegalArgumentException(element.toString()); } } } + + private void process(Class annotation, boolean skipEmbeddables, Map types) { + process(getElements(annotation), skipEmbeddables, types); + } + + @SuppressWarnings("unchecked") + private void process(Set elements, boolean skipEmbeddables, Map types) { + Deque superTypes = new ArrayDeque(); + List allElements = new ArrayList(); + List typeMirrors = new ArrayList(); + List superTypeMirrors = new ArrayList(); + + for (TypeElement element : (Set)elements) { + if (skipEmbeddables && element.getAnnotation(configuration.getEmbeddableAnnotation()) != null) { + continue; + } + typeFactory.getEntityType(element.asType(), false); + typeMirrors.add(element.asType()); + allElements.add(element); + + addAnnotationlessSupertypes(superTypeMirrors, allElements, element); + } + // super type handling + for (TypeMirror typeMirror : superTypeMirrors) { + typeFactory.getEntityType(typeMirror, true); + } + + for (TypeMirror typeMirror : typeMirrors) { + typeFactory.getEntityType(typeMirror, true); + } + + // get annotated types + for (TypeElement element : allElements) { + EntityType model = elementHandler.handleEntityType(element); + registerTypeElement(model.getFullName(), element); + types.put(model.getFullName(), model); + if (model.getSuperType() != null) { + superTypes.push(model.getSuperType().getType()); + } + } + + mergeTypes(types, superTypes); + } + + private void processEmbedded() { + Set elements = new HashSet(); + + // only creation + for (Element element : getElements(configuration.getEmbeddedAnnotation())) { + TypeMirror type = element.asType(); + if (element.getKind() == ElementKind.METHOD){ + type = ((ExecutableElement)element).getReturnType(); + } + String typeName = type.toString(); + if (typeName.startsWith(Collection.class.getName()) + || typeName.startsWith(List.class.getName()) + || typeName.startsWith(Set.class.getName())) { + type = ((DeclaredType)type).getTypeArguments().get(0); + + } else if (typeName.startsWith(Map.class.getName())){ + type = ((DeclaredType)type).getTypeArguments().get(1); + } + + TypeElement typeElement = typeExtractor.visit(type); + if (typeElement != null && typeElement.getAnnotation(configuration.getEntityAnnotation()) == null) { + elements.add(typeElement); + } + } + + process(elements, false, embeddables); + } + + @SuppressWarnings("unchecked") + private void processEntitiesFromPackage() { + Class annotation = configuration.getEntitiesAnnotation(); + Set elements = new HashSet(); + + // only creation + for (Element element : getElements(annotation)) { + for (AnnotationMirror mirror : element.getAnnotationMirrors()) { + if (mirror.getAnnotationType().asElement().getSimpleName().toString().equals(annotation.getSimpleName())) { + for (Map.Entry entry : mirror.getElementValues().entrySet()) { + if (entry.getKey().getSimpleName().toString().equals("value")) { + List values = (List) entry.getValue().getValue(); + for (AnnotationValue value : values) { + DeclaredType type = (DeclaredType) value.getValue(); + elements.add(type.asElement()); + } + } + } + } + } + } + + process(elements, false, entityTypes); + } + private void processFromProperties() { Set elements = new HashSet(); for (Class annotation : entityAnnotations) { - elements.addAll(roundEnv.getElementsAnnotatedWith(annotation)); + elements.addAll(getElements(annotation)); } - TypeExtractor typeExtractor = new TypeExtractor(true, true); Set types = new HashSet(); // classes for (Element element : elements) { if (element instanceof TypeElement) { - TypeElement type = (TypeElement)element; - List children = type.getEnclosedElements(); - VisitorConfig config = configuration.getConfig(type, children); - - // fields - if (config.visitFieldProperties()) { - for (VariableElement field : ElementFilter.fieldsIn(children)) { - TypeElement typeElement = typeExtractor.handle(field.asType()); - if (typeElement != null) { - types.add(typeElement); - } - } - } - - // getters - if (config.visitMethodProperties()) { - for (ExecutableElement method : ElementFilter.methodsIn(children)) { - String name = method.getSimpleName().toString(); - if (name.startsWith("get") && method.getParameters().isEmpty()) { - name = BeanUtils.uncapitalize(name.substring(3)); - } else if (name.startsWith("is") && method.getParameters().isEmpty()) { - name = BeanUtils.uncapitalize(name.substring(2)); - } else { - continue; - } - TypeElement typeElement = typeExtractor.handle(method.getReturnType()); - if (typeElement != null) { - types.add(typeElement); - } - } - } + processFromProperties((TypeElement)element, types); } } - List typeMirrors = new ArrayList(); + List typeMirrors = new ArrayList(types.size()); for (TypeElement type : types) { // skip internal types @@ -274,53 +364,35 @@ public class Processor { } } } - - - private void serializeTypes() { - if (!actualSupertypes.isEmpty()) { - env.getMessager().printMessage(Kind.NOTE, "Serializing Supertypes"); - serialize(configuration.getSupertypeSerializer(), actualSupertypes.values()); - } - - if (!entityTypes.isEmpty()) { - env.getMessager().printMessage(Kind.NOTE, "Serializing Entity types"); - serialize(configuration.getEntitySerializer(), entityTypes.values()); - } - - if (!extensionTypes.isEmpty()) { - env.getMessager().printMessage(Kind.NOTE, "Serializing Extension types"); - serialize(configuration.getEmbeddableSerializer(), extensionTypes.values()); - } - - if (!embeddables.isEmpty()) { - env.getMessager().printMessage(Kind.NOTE, "Serializing Embeddable types"); - serialize(configuration.getEmbeddableSerializer(), embeddables.values()); - } - - if (!projectionTypes.isEmpty()) { - env.getMessager().printMessage(Kind.NOTE, "Serializing Projection types"); - serialize(configuration.getDTOSerializer(), projectionTypes.values()); - } - - } - - private void serializeVariableClasses() { - for (Element element : roundEnv.getElementsAnnotatedWith(Variables.class)) { - if (element instanceof PackageElement) { - Variables vars = element.getAnnotation(Variables.class); - PackageElement packageElement = (PackageElement)element; - List models = new ArrayList(); - for (EntityType model : entityTypes.values()) { - if (model.getPackageName().equals(packageElement.getQualifiedName().toString())) { - models.add(model); - } + + private void processFromProperties(TypeElement type, Set types) { + List children = type.getEnclosedElements(); + VisitorConfig config = configuration.getConfig(type, children); + + // fields + if (config.visitFieldProperties()) { + for (VariableElement field : ElementFilter.fieldsIn(children)) { + TypeElement typeElement = typeExtractor.visit(field.asType()); + if (typeElement != null) { + types.add(typeElement); } - serializeVariableList(packageElement.getQualifiedName().toString(), vars, models); + } + } + + // getters + if (config.visitMethodProperties()) { + for (ExecutableElement method : ElementFilter.methodsIn(children)) { + String name = method.getSimpleName().toString(); + if ((name.startsWith("get") || name.startsWith("is")) && method.getParameters().isEmpty()) { + TypeElement typeElement = typeExtractor.visit(method.getReturnType()); + if (typeElement != null) { + types.add(typeElement); + } + } } } } - private void addSupertypeFields(EntityType model, Map superTypes, Set handled) { if (handled.add(model)) { for (Supertype supertype : model.getSuperTypes()) { @@ -336,7 +408,7 @@ public class Processor { @SuppressWarnings("unchecked") private Set getElementsAndCache(Class annotationType) { - Set elements = (Set)roundEnv.getElementsAnnotatedWith(annotationType); + Set elements = (Set)getElements(annotationType); if (!elements.isEmpty()) { Set cached = elementCache.get(annotationType); if (cached == null) { @@ -378,28 +450,7 @@ public class Processor { return Collections.emptySet(); } } - - @Nullable - private FileObject getSourceFile(String fullName) throws IOException { - Elements elementUtils = env.getElementUtils(); - TypeElement sourceElement = elementUtils.getTypeElement(fullName); - if (sourceElement == null) { - return null; - } else { - if (sourceElement.getNestingKind().isNested()) { - sourceElement = (TypeElement) sourceElement.getEnclosingElement(); - } - PackageElement packageElement = elementUtils.getPackageOf(sourceElement); - try { - return env.getFiler().getResource(StandardLocation.SOURCE_PATH, - packageElement.getQualifiedName(), - sourceElement.getSimpleName() + ".java"); - } catch(Exception e) { - return null; - } - } - } - + private void mergeTypes(Map types, Deque superTypes) { // get external supertypes while (!superTypes.isEmpty()) { @@ -426,63 +477,19 @@ public class Processor { } } - private void process(Class annotation, Map types) { - Deque superTypes = new ArrayDeque(); - List elements = new ArrayList(); - - // only creation - List typeMirrors = new ArrayList(); - List superTypeMirrors = new ArrayList(); - - for (Element element : roundEnv.getElementsAnnotatedWith(annotation)) { - if (configuration.getEmbeddableAnnotation() == null - || element.getAnnotation(configuration.getEmbeddableAnnotation()) == null) { - typeFactory.getEntityType(element.asType(), false); - typeMirrors.add(element.asType()); - elements.add(element); - - addAnnotationlessSupertypes(superTypeMirrors, elements, element); - } - } - - for (TypeMirror typeMirror : superTypeMirrors) { - typeFactory.getEntityType(typeMirror, true); - } - - // super type handling - for (TypeMirror typeMirror : typeMirrors) { - typeFactory.getEntityType(typeMirror, true); - } - - // get annotated types - for (Element element : elements) { - EntityType model = elementHandler.handleEntityType((TypeElement) element); - registerTypeElement(model.getFullName(), (TypeElement)element); - types.put(model.getFullName(), model); - if (model.getSuperType() != null) { - superTypes.push(model.getSuperType().getType()); - } - } - - mergeTypes(types, superTypes); - } private boolean hasKnownAnnotation(Element element) { if (configuration.getEmbeddableAnnotation() != null && element.getAnnotation(configuration.getEmbeddableAnnotation()) != null) { return true; - } - - if (configuration.getSuperTypeAnnotation() != null && element.getAnnotation(configuration.getSuperTypeAnnotation()) != null) { + } else if (configuration.getSuperTypeAnnotation() != null && element.getAnnotation(configuration.getSuperTypeAnnotation()) != null) { return true; - } - - if (element.getAnnotation(configuration.getEntityAnnotation()) != null) { + } else if (element.getAnnotation(configuration.getEntityAnnotation()) != null) { return true; - } - - return false; + } else { + return false; + } } - + private void processDelegateMethod(Element delegateMethod, boolean cached) { ExecutableElement method = (ExecutableElement)delegateMethod; Element element = delegateMethod.getEnclosingElement(); @@ -517,12 +524,12 @@ public class Processor { } private void processDelegateMethods() { - // 1 : get elements from cache + // get elements from cache for (Element delegateMethod : getElementsFromCache(QueryDelegate.class)) { processDelegateMethod(delegateMethod, true); } - // 2 : get elements from roundEnv + // get elements from roundEnv for (Element delegateMethod : getElementsAndCache(QueryDelegate.class)) { processDelegateMethod(delegateMethod, false); } @@ -530,7 +537,7 @@ public class Processor { private void processProjectionTypes() { Set visitedDTOTypes = new HashSet(); - for (Element element : roundEnv.getElementsAnnotatedWith(QueryProjection.class)) { + for (Element element : getElements(QueryProjection.class)) { Element parent = element.getEnclosingElement(); if (parent.getAnnotation(configuration.getEntityAnnotation()) == null && parent.getAnnotation(configuration.getEmbeddableAnnotation()) == null @@ -542,58 +549,20 @@ public class Processor { } } } - - private void processEmbeddables() { - List typeMirrors = new ArrayList(); - List superTypeMirrors = new ArrayList(); - List elements = new ArrayList(); - - // only creation - for (Element element : roundEnv.getElementsAnnotatedWith(configuration.getEmbeddableAnnotation())) { - // TODO: Why is this needed if there's no assignment? Just for cache? - typeFactory.getEntityType(element.asType(), false); - typeMirrors.add(element.asType()); - elements.add(element); - - addAnnotationlessSupertypes(superTypeMirrors, elements, element); - } - - for (TypeMirror typeMirror : superTypeMirrors) { - typeFactory.getEntityType(typeMirror, true); - } - - // supertype handling - for (TypeMirror typeMirror : typeMirrors) { - typeFactory.getEntityType(typeMirror, true); - } - - for (Element element : elements) { - EntityType model = elementHandler.handleEntityType((TypeElement) element); - registerTypeElement(model.getFullName(), (TypeElement)element); - embeddables.put(model.getFullName(), model); - } - allSupertypes.putAll(embeddables); - - // add super type fields - Set handled = new HashSet(); - for (EntityType embeddable : embeddables.values()) { - addSupertypeFields(embeddable, allSupertypes, handled); - } - } - + private void addAnnotationlessSupertypes(List superTypeMirrors, - List elements, Element element) { + List elements, TypeElement element) { // add annotationless supertype - TypeMirror superTypeMirror = ((TypeElement)element).getSuperclass(); + TypeMirror superTypeMirror = element.getSuperclass(); while (superTypeMirror != null){ - Element superTypeElement = env.getTypeUtils().asElement(superTypeMirror); + TypeElement superTypeElement = (TypeElement) env.getTypeUtils().asElement(superTypeMirror); if (superTypeElement != null && !superTypeElement.toString().startsWith("java.lang.") && !hasKnownAnnotation(superTypeElement)) { typeFactory.getEntityType(superTypeMirror, false); superTypeMirrors.add(superTypeMirror); elements.add(superTypeElement); - superTypeMirror = ((TypeElement)superTypeElement).getSuperclass(); + superTypeMirror = superTypeElement.getSuperclass(); if (superTypeMirror instanceof NoType) { superTypeMirror = null; } @@ -601,112 +570,7 @@ public class Processor { superTypeMirror = null; } } - } - - - private void processEmbedded() { - List typeMirrors = new ArrayList(); - - // only creation - for (Element element : roundEnv.getElementsAnnotatedWith(configuration.getEmbeddedAnnotation())) { - TypeMirror type = element.asType(); - if (element.getKind() == ElementKind.METHOD){ - type = ((ExecutableElement)element).getReturnType(); - } - String typeName = type.toString(); - if (typeName.startsWith(Collection.class.getName()) - || typeName.startsWith(List.class.getName()) - || typeName.startsWith(Set.class.getName())) { - type = ((DeclaredType)type).getTypeArguments().get(0); - - } else if (typeName.startsWith(Map.class.getName())){ - type = ((DeclaredType)type).getTypeArguments().get(1); - } - typeFactory.getEntityType(type, false); - typeMirrors.add(type); - } - - // supertype handling - for (TypeMirror typeMirror : typeMirrors) { - typeFactory.getEntityType(typeMirror, true); - } - - // deep - for (TypeMirror type : typeMirrors) { - // remove generic signature of type for TypeElement lookup - String typeName = type.toString(); - if (typeName.contains("<")) { - typeName = typeName.substring(0, typeName.indexOf('<')); - } - TypeElement typeElement = env.getElementUtils().getTypeElement(typeName); - if (typeElement == null) { - continue; - } else if (typeElement.getAnnotation(configuration.getEntityAnnotation()) != null){ - // skip Entity types here - continue; - } - - EntityType model = elementHandler.handleEntityType(typeElement); - registerTypeElement(model.getFullName(), typeElement); - embeddables.put(model.getFullName(), model); - } - allSupertypes.putAll(embeddables); - - // add super type fields - Set handled = new HashSet(); - for (EntityType embeddable : embeddables.values()) { - addSupertypeFields(embeddable, allSupertypes, handled); - } - } - - private void processEntities() { - process(configuration.getEntityAnnotation(), entityTypes); - } - - @SuppressWarnings("unchecked") - private void processEntitiesFromPackage() { - Class annotation = configuration.getEntitiesAnnotation(); - List typeMirrors = new ArrayList(); - - // only creation - for (Element element : roundEnv.getElementsAnnotatedWith(annotation)) { - for (AnnotationMirror mirror : element.getAnnotationMirrors()) { - if (mirror.getAnnotationType().asElement().getSimpleName().toString().equals(QueryEntities.class.getSimpleName())) { - for (Map.Entry entry : mirror.getElementValues().entrySet()) { - if (entry.getKey().getSimpleName().toString().equals("value")) { - List values = (List) entry.getValue().getValue(); - for (AnnotationValue value : values) { - TypeMirror type = (TypeMirror) value.getValue(); - typeFactory.getEntityType(type, false); - typeMirrors.add(type); - } - } - } - } - } - } - - Map types = entityTypes; - Deque superTypes = new ArrayDeque(); - - // get annotated types - for (TypeMirror mirror : typeMirrors) { - typeFactory.getEntityType(mirror, true); - TypeElement element = (TypeElement) env.getTypeUtils().asElement(mirror); - EntityType model = elementHandler.handleEntityType(element); - registerTypeElement(model.getFullName(), element); - types.put(model.getFullName(), model); - if (model.getSuperType() != null) { - superTypes.push(model.getSuperType().getType()); - } - } - - mergeTypes(types, superTypes); - } - - private void processSupertypes() { - process(configuration.getSuperTypeAnnotation(), actualSupertypes); - } + } private void registerTypeElement(String entityName, TypeElement element) { Set elements = typeElements.get(entityName); @@ -716,6 +580,73 @@ public class Processor { } elements.add(element); } + + // SERIALIZATION + + private void serializeTypes() { + if (!actualSupertypes.isEmpty()) { + env.getMessager().printMessage(Kind.NOTE, "Serializing Supertypes"); + serialize(configuration.getSupertypeSerializer(), actualSupertypes.values()); + } + + if (!entityTypes.isEmpty()) { + env.getMessager().printMessage(Kind.NOTE, "Serializing Entity types"); + serialize(configuration.getEntitySerializer(), entityTypes.values()); + } + + if (!extensionTypes.isEmpty()) { + env.getMessager().printMessage(Kind.NOTE, "Serializing Extension types"); + serialize(configuration.getEmbeddableSerializer(), extensionTypes.values()); + } + + if (!embeddables.isEmpty()) { + env.getMessager().printMessage(Kind.NOTE, "Serializing Embeddable types"); + serialize(configuration.getEmbeddableSerializer(), embeddables.values()); + } + + if (!projectionTypes.isEmpty()) { + env.getMessager().printMessage(Kind.NOTE, "Serializing Projection types"); + serialize(configuration.getDTOSerializer(), projectionTypes.values()); + } + + } + + private void serializeVariableClasses() { + for (Element element : getElements(Variables.class)) { + if (element instanceof PackageElement) { + Variables vars = element.getAnnotation(Variables.class); + PackageElement packageElement = (PackageElement)element; + List models = new ArrayList(); + for (EntityType model : entityTypes.values()) { + if (model.getPackageName().equals(packageElement.getQualifiedName().toString())) { + models.add(model); + } + } + serializeVariableList(packageElement.getQualifiedName().toString(), vars, models); + } + } + } + + @Nullable + private FileObject getSourceFile(String fullName) throws IOException { + Elements elementUtils = env.getElementUtils(); + TypeElement sourceElement = elementUtils.getTypeElement(fullName); + if (sourceElement == null) { + return null; + } else { + if (sourceElement.getNestingKind().isNested()) { + sourceElement = (TypeElement) sourceElement.getEnclosingElement(); + } + PackageElement packageElement = elementUtils.getPackageOf(sourceElement); + try { + return env.getFiler().getResource(StandardLocation.SOURCE_PATH, + packageElement.getQualifiedName(), + sourceElement.getSimpleName() + ".java"); + } catch(Exception e) { + return null; + } + } + } private void serialize(Serializer serializer, Collection models) { Messager msg = env.getMessager(); diff --git a/querydsl-apt/src/main/java/com/mysema/query/apt/ElementHandler.java b/querydsl-apt/src/main/java/com/mysema/query/apt/TypeElementHandler.java similarity index 97% rename from querydsl-apt/src/main/java/com/mysema/query/apt/ElementHandler.java rename to querydsl-apt/src/main/java/com/mysema/query/apt/TypeElementHandler.java index dca4c7d45..d3592a33b 100644 --- a/querydsl-apt/src/main/java/com/mysema/query/apt/ElementHandler.java +++ b/querydsl-apt/src/main/java/com/mysema/query/apt/TypeElementHandler.java @@ -34,14 +34,13 @@ import com.mysema.query.codegen.TypeMappings; import com.mysema.util.BeanUtils; /** - * ElementHandler is a an APT visitor for entity types + * TypeElementHandler is a an APT visitor for entity types * * @author tiwe * */ @Immutable -// TODO : rename -public final class ElementHandler{ +public final class TypeElementHandler { private final TypeMappings typeMappings; @@ -51,7 +50,7 @@ public final class ElementHandler{ private final ExtendedTypeFactory typeFactory; - public ElementHandler(Configuration configuration, ExtendedTypeFactory typeFactory, + public TypeElementHandler(Configuration configuration, ExtendedTypeFactory typeFactory, TypeMappings typeMappings, QueryTypeFactory queryTypeFactory) { this.configuration = configuration; this.typeFactory = typeFactory; diff --git a/querydsl-apt/src/main/java/com/mysema/query/apt/TypeExtractor.java b/querydsl-apt/src/main/java/com/mysema/query/apt/TypeExtractor.java index 25838882d..7c58022b2 100644 --- a/querydsl-apt/src/main/java/com/mysema/query/apt/TypeExtractor.java +++ b/querydsl-apt/src/main/java/com/mysema/query/apt/TypeExtractor.java @@ -1,49 +1,52 @@ package com.mysema.query.apt; -import javax.annotation.Nullable; import javax.lang.model.element.TypeElement; import javax.lang.model.type.ArrayType; import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.ErrorType; +import javax.lang.model.type.ExecutableType; import javax.lang.model.type.NoType; -import javax.lang.model.type.TypeMirror; +import javax.lang.model.type.NullType; +import javax.lang.model.type.PrimitiveType; import javax.lang.model.type.TypeVariable; import javax.lang.model.type.WildcardType; +import javax.lang.model.util.AbstractTypeVisitor6; -public class TypeExtractor { +/** + * @author tiwe + * + */ +public class TypeExtractor extends AbstractTypeVisitor6 { - private final boolean skipPrimitive, skipEnum; + private final boolean skipEnum; - public TypeExtractor(boolean skipPrimitive, boolean skipEnum) { - this.skipPrimitive = skipPrimitive; + public TypeExtractor(boolean skipEnum) { this.skipEnum = skipEnum; } - @Nullable - public TypeElement handle(TypeMirror typeMirror) { - if (typeMirror instanceof DeclaredType) { - return handleDeclaredType((DeclaredType)typeMirror); - } else if (typeMirror instanceof TypeVariable) { - return handleTypeVariable((TypeVariable)typeMirror); - } else if (typeMirror instanceof WildcardType) { - return handleWildcard((WildcardType)typeMirror); - } else if (typeMirror instanceof ArrayType) { - ArrayType t = (ArrayType)typeMirror; - return handle(t.getComponentType()); - } else if (typeMirror instanceof NoType) { - return null; - } else { - return null; - } + @Override + public TypeElement visitPrimitive(PrimitiveType t, Void p) { + return null; } - - @Nullable - private TypeElement handleDeclaredType(DeclaredType typeMirror) { - if (typeMirror.asElement() instanceof TypeElement) { - TypeElement typeElement = (TypeElement)typeMirror.asElement(); + + @Override + public TypeElement visitNull(NullType t, Void p) { + return null; + } + + @Override + public TypeElement visitArray(ArrayType t, Void p) { + return visit(t.getComponentType()); + } + + @Override + public TypeElement visitDeclared(DeclaredType t, Void p) { + if (t.asElement() instanceof TypeElement) { + TypeElement typeElement = (TypeElement)t.asElement(); switch (typeElement.getKind()) { - case ENUM: return handleEnumType(typeMirror, typeElement); - case CLASS: return handleClassType(typeMirror, typeElement); - case INTERFACE: return handleInterfaceType(typeMirror, typeElement); + case ENUM: return skipEnum ? null : typeElement; + case CLASS: return typeElement; + case INTERFACE: return visit(t.getTypeArguments().get(t.getTypeArguments().size()-1)); default: throw new IllegalArgumentException("Illegal type " + typeElement); } } else { @@ -51,41 +54,34 @@ public class TypeExtractor { } } - @Nullable - private TypeElement handleWildcard(WildcardType typeMirror) { - return handle(typeMirror.getExtendsBound()); + @Override + public TypeElement visitError(ErrorType t, Void p) { + return visitDeclared(t, p); } - @Nullable - private TypeElement handleTypeVariable(TypeVariable typeMirror) { - if (typeMirror.getUpperBound() != null) { - return handle(typeMirror.getUpperBound()); + @Override + public TypeElement visitTypeVariable(TypeVariable t, Void p) { + if (t.getUpperBound() != null) { + return visit(t.getUpperBound()); } else { - return handle(typeMirror.getLowerBound()); + return visit(t.getLowerBound()); } } - @Nullable - private TypeElement handleInterfaceType(DeclaredType typeMirror, TypeElement typeElement) { - return handle(typeMirror.getTypeArguments().get(typeMirror.getTypeArguments().size()-1)); + @Override + public TypeElement visitWildcard(WildcardType t, Void p) { + return visit(t.getExtendsBound()); } - @Nullable - private TypeElement handleClassType(DeclaredType typeMirror, TypeElement typeElement) { - if (skipPrimitive && typeMirror.getKind().isPrimitive()) { - return null; - } else { - return typeElement; - } + @Override + public TypeElement visitExecutable(ExecutableType t, Void p) { + return null; } - @Nullable - private TypeElement handleEnumType(DeclaredType typeMirror, TypeElement typeElement) { - if (skipEnum) { - return null; - } else { - return typeElement; - } + @Override + public TypeElement visitNoType(NoType t, Void p) { + return null; } + } diff --git a/querydsl-apt/src/main/java/com/mysema/query/apt/VisitorConfig.java b/querydsl-apt/src/main/java/com/mysema/query/apt/VisitorConfig.java index b133b0f53..1e31ba516 100644 --- a/querydsl-apt/src/main/java/com/mysema/query/apt/VisitorConfig.java +++ b/querydsl-apt/src/main/java/com/mysema/query/apt/VisitorConfig.java @@ -15,33 +15,33 @@ public enum VisitorConfig { /** * visit both fields and getters */ - ALL(true,true), + ALL(true, true, true), /** * visit fields only */ - FIELDS_ONLY(true,false), + FIELDS_ONLY(true, false, true), /** * visit methods only */ - METHODS_ONLY(false,true), + METHODS_ONLY(false, true, true), /** * visit none */ - NONE(false,false); + NONE(false, false, false); - private final boolean visitFieldProperties, visitMethodProperties; + private final boolean visitFieldProperties, visitMethodProperties, visitConstructors; - VisitorConfig(boolean fields, boolean methods) { + VisitorConfig(boolean fields, boolean methods, boolean constructors) { this.visitFieldProperties = fields; this.visitMethodProperties = methods; + this.visitConstructors = constructors; } public boolean visitConstructors() { - // TODO : parametrize! - return true; + return visitConstructors; } public boolean visitFieldProperties() {