From bc00ff369afccb01d5686104bc4e5ec3cf6e3f8c Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Sat, 14 Dec 2024 15:32:50 -0500 Subject: [PATCH 01/10] use avaje prisms --- .gitignore | 2 + ebean-querybean/pom.xml | 7 - querybean-generator/pom.xml | 60 ++- .../ebean/querybean/generator/Constants.java | 2 +- .../ebean/querybean/generator/FindDbName.java | 55 --- .../ebean/querybean/generator/ModuleMeta.java | 21 - .../generator/ProcessingContext.java | 408 +++++++----------- .../ebean/querybean/generator/Processor.java | 110 ++--- .../querybean/generator/ReadModuleInfo.java | 69 --- .../generator/SimpleModuleInfoWriter.java | 56 +-- .../generator/SimpleQueryBeanWriter.java | 52 +-- .../querybean/generator/package-info.java | 23 + .../src/main/java/module-info.java | 11 +- .../javax.annotation.processing.Processor | 1 - .../generator/QueryBeanProcessorTest.java | 68 +++ .../generator/entities/ArticleEntity.java | 127 ++++++ .../generator/entities/ArticleTags.java | 72 ++++ .../generator/entities/CommentEntity.java | 52 +++ .../generator/entities/FavoriteEntity.java | 40 ++ .../generator/entities/TagEntity.java | 27 ++ .../generator/entities/UserEntity.java | 86 ++++ 21 files changed, 835 insertions(+), 514 deletions(-) delete mode 100644 querybean-generator/src/main/java/io/ebean/querybean/generator/FindDbName.java delete mode 100644 querybean-generator/src/main/java/io/ebean/querybean/generator/ModuleMeta.java delete mode 100644 querybean-generator/src/main/java/io/ebean/querybean/generator/ReadModuleInfo.java create mode 100644 querybean-generator/src/main/java/io/ebean/querybean/generator/package-info.java delete mode 100644 querybean-generator/src/main/resources/META-INF/services/javax.annotation.processing.Processor create mode 100644 querybean-generator/src/test/java/io/ebean/querybean/generator/QueryBeanProcessorTest.java create mode 100644 querybean-generator/src/test/java/io/ebean/querybean/generator/entities/ArticleEntity.java create mode 100644 querybean-generator/src/test/java/io/ebean/querybean/generator/entities/ArticleTags.java create mode 100644 querybean-generator/src/test/java/io/ebean/querybean/generator/entities/CommentEntity.java create mode 100644 querybean-generator/src/test/java/io/ebean/querybean/generator/entities/FavoriteEntity.java create mode 100644 querybean-generator/src/test/java/io/ebean/querybean/generator/entities/TagEntity.java create mode 100644 querybean-generator/src/test/java/io/ebean/querybean/generator/entities/UserEntity.java diff --git a/.gitignore b/.gitignore index a95675f955..e786531d24 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,5 @@ profiling/ *.iws .idea/ *uuid.state +querybean-generator/.factorypath +*.class diff --git a/ebean-querybean/pom.xml b/ebean-querybean/pom.xml index 0346f5ca6d..95f5bec71a 100644 --- a/ebean-querybean/pom.xml +++ b/ebean-querybean/pom.xml @@ -77,13 +77,6 @@ test - - io.ebean - querybean-generator - 14.8.0 - provided - - diff --git a/querybean-generator/pom.xml b/querybean-generator/pom.xml index 7879da2561..c24583a02b 100644 --- a/querybean-generator/pom.xml +++ b/querybean-generator/pom.xml @@ -10,17 +10,71 @@ querybean generator Querybean generator querybean-generator + + + 1.36 + + + + io.ebean + ebean-api + ${project.version} + true + provided + + + io.ebean + ebean-querybean + ${project.version} + true + provided + + + io.ebean + jakarta-persistence-api + ${ebean-persistence-api.version} + true + provided + + + + org.jspecify + jspecify + 1.0.0 + true + provided + + + + io.avaje + avaje-prisms + ${avaje.prisms.version} + true + provided + + + + io.avaje + avaje-spi-service + 2.8 + + + + + io.avaje + junit + 1.5 + test + + - org.apache.maven.plugins maven-compiler-plugin 11 11 - - -proc:none diff --git a/querybean-generator/src/main/java/io/ebean/querybean/generator/Constants.java b/querybean-generator/src/main/java/io/ebean/querybean/generator/Constants.java index 76949a8fd9..1927bd7673 100644 --- a/querybean-generator/src/main/java/io/ebean/querybean/generator/Constants.java +++ b/querybean-generator/src/main/java/io/ebean/querybean/generator/Constants.java @@ -25,7 +25,7 @@ interface Constants { String METAINF_MANIFEST = "META-INF/ebean-generated-info.mf"; String METAINF_SERVICES_MODULELOADER = "META-INF/services/io.ebean.config.EntityClassRegister"; - String AVAJE_LANG_NULLABLE = "io.avaje.lang.Nullable"; + String AVAJE_LANG_NULLABLE = "org.jspecify.annotations.Nullable"; String JAVA_COLLECTION = "java.util.Collection"; String EXPRESSIONLIST = "io.ebean.ExpressionList"; String EXPR = "io.ebean.Expr"; diff --git a/querybean-generator/src/main/java/io/ebean/querybean/generator/FindDbName.java b/querybean-generator/src/main/java/io/ebean/querybean/generator/FindDbName.java deleted file mode 100644 index 9fd0133823..0000000000 --- a/querybean-generator/src/main/java/io/ebean/querybean/generator/FindDbName.java +++ /dev/null @@ -1,55 +0,0 @@ -package io.ebean.querybean.generator; - -import javax.lang.model.element.AnnotationMirror; -import javax.lang.model.element.AnnotationValue; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.TypeElement; -import javax.lang.model.type.TypeKind; -import javax.lang.model.type.TypeMirror; -import javax.lang.model.util.Types; -import java.util.List; -import java.util.Map; -import java.util.Set; - -class FindDbName { - - /** - * Return the value of the DbName annotation or null if it isn't found on the element. - */ - static String value(TypeElement element, Types typeUtils) { - - AnnotationMirror mirror = findDbNameMirror(element); - if (mirror != null) { - return readDbNameValue(mirror); - } - final TypeMirror typeMirror = element.getSuperclass(); - if (typeMirror.getKind() == TypeKind.NONE) { - return null; - } - final TypeElement element1 = (TypeElement)typeUtils.asElement(typeMirror); - return value(element1, typeUtils); - } - - private static String readDbNameValue(AnnotationMirror mirror) { - - final Map elementValues = mirror.getElementValues(); - final Set> entries = elementValues.entrySet(); - for (Map.Entry entry : entries) { - if ("value".equals(entry.getKey().getSimpleName().toString())) { - return (String) entry.getValue().getValue(); - } - } - return null; - } - - private static AnnotationMirror findDbNameMirror(TypeElement element) { - final List mirrors = element.getAnnotationMirrors(); - for (AnnotationMirror mirror : mirrors) { - final String name = mirror.getAnnotationType().asElement().toString(); - if (Constants.DBNAME.equals(name)) { - return mirror; - } - } - return null; - } -} diff --git a/querybean-generator/src/main/java/io/ebean/querybean/generator/ModuleMeta.java b/querybean-generator/src/main/java/io/ebean/querybean/generator/ModuleMeta.java deleted file mode 100644 index a1e98f3a19..0000000000 --- a/querybean-generator/src/main/java/io/ebean/querybean/generator/ModuleMeta.java +++ /dev/null @@ -1,21 +0,0 @@ -package io.ebean.querybean.generator; - -import java.util.List; - -class ModuleMeta { - private final List entities; - private final List other; - - ModuleMeta(List entities, List other) { - this.entities = entities; - this.other = other; - } - - List getEntities() { - return entities; - } - - List getOther() { - return other; - } -} diff --git a/querybean-generator/src/main/java/io/ebean/querybean/generator/ProcessingContext.java b/querybean-generator/src/main/java/io/ebean/querybean/generator/ProcessingContext.java index bbc8728039..bb82e6385c 100644 --- a/querybean-generator/src/main/java/io/ebean/querybean/generator/ProcessingContext.java +++ b/querybean-generator/src/main/java/io/ebean/querybean/generator/ProcessingContext.java @@ -1,8 +1,25 @@ package io.ebean.querybean.generator; -import javax.annotation.processing.Filer; +import static io.ebean.querybean.generator.APContext.filer; +import static io.ebean.querybean.generator.APContext.logError; +import static io.ebean.querybean.generator.APContext.logNote; +import static io.ebean.querybean.generator.APContext.typeElement; +import static io.ebean.querybean.generator.ProcessorUtils.trimAnnotations; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.LineNumberReader; +import java.io.Reader; +import java.nio.file.NoSuchFileException; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; + import javax.annotation.processing.FilerException; -import javax.annotation.processing.Messager; import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.AnnotationValue; @@ -16,118 +33,68 @@ import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; import javax.lang.model.util.ElementFilter; -import javax.lang.model.util.Elements; -import javax.lang.model.util.Types; -import javax.tools.Diagnostic; import javax.tools.FileObject; -import javax.tools.JavaFileObject; import javax.tools.StandardLocation; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.LineNumberReader; -import java.io.Reader; -import java.nio.file.NoSuchFileException; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; -import java.util.TreeSet; -/** - * Context for the source generation. - */ +/** Context for the source generation. */ class ProcessingContext implements Constants { - private final ProcessingEnvironment processingEnv; - private final Types typeUtils; - private final Filer filer; - private final Messager messager; - private final Elements elementUtils; - - private final PropertyTypeMap propertyTypeMap = new PropertyTypeMap(); + private static final ThreadLocal CTX = new ThreadLocal<>(); - private final ReadModuleInfo readModuleInfo; - - /** - * All entity packages regardless of DB (for META-INF/ebean-generated-info.mf). - */ - private final Set allEntityPackages = new TreeSet<>(); + private static final class Ctx { + private final Set services = new TreeSet<>(); - private final Set otherClasses = new TreeSet<>(); + private final PropertyTypeMap propertyTypeMap = new PropertyTypeMap(); - /** - * The DB name prefixed entities. - */ - private final Set prefixEntities = new TreeSet<>(); + /** All entity packages regardless of DB (for META-INF/ebean-generated-info.mf). */ + private final Set allEntityPackages = new TreeSet<>(); - /** - * Entity classes for the default database. - */ - private final Set dbEntities = new TreeSet<>(); + private final Set otherClasses = new TreeSet<>(); - /** - * Entity classes for non default databases. - */ - private final Map> otherDbEntities = new TreeMap<>(); + /** The DB name prefixed entities. */ + private final Set prefixEntities = new TreeSet<>(); - /** - * All loaded entities regardless of db (to detect ones we add back from loadedPrefixEntities). - */ - private final Set loaded = new HashSet<>(); + /** Entity classes for the default database. */ + private final Set dbEntities = new TreeSet<>(); - /** - * For partial compile the previous list of prefixed entity classes. - */ - private final List loadedPrefixEntities = new ArrayList<>(); + /** Entity classes for non default databases. */ + private final Map> otherDbEntities = new TreeMap<>(); - /** - * The package for the generated EntityClassRegister. - */ - private String factoryPackage; + /** + * All loaded entities regardless of db (to detect ones we add back from loadedPrefixEntities). + */ + private final Set loaded = new HashSet<>(); - ProcessingContext(ProcessingEnvironment processingEnv) { - this.processingEnv = processingEnv; - this.typeUtils = processingEnv.getTypeUtils(); - this.filer = processingEnv.getFiler(); - this.messager = processingEnv.getMessager(); - this.elementUtils = processingEnv.getElementUtils(); - this.readModuleInfo = new ReadModuleInfo(this); - } + /** For partial compile the previous list of prefixed entity classes. */ + private final List loadedPrefixEntities = new ArrayList<>(); - TypeElement entityAnnotation() { - return elementUtils.getTypeElement(ENTITY); + /** The package for the generated EntityClassRegister. */ + private String factoryPackage; } - TypeElement embeddableAnnotation() { - return elementUtils.getTypeElement(EMBEDDABLE); + static void init(ProcessingEnvironment processingEnv) { + APContext.init(processingEnv); + CTX.set(new Ctx()); } - TypeElement converterAnnotation() { - return elementUtils.getTypeElement(CONVERTER); - } + static void clear() { + APContext.clear(); - TypeElement componentAnnotation() { - return elementUtils.getTypeElement(EBEAN_COMPONENT); + CTX.remove(); } - /** - * Gather all the fields (properties) for the given bean element. - */ - List allFields(Element element) { + /** Gather all the fields (properties) for the given bean element. */ + static List allFields(Element element) { List list = new ArrayList<>(); gatherProperties(list, element); return list; } - /** - * Recursively gather all the fields (properties) for the given bean element. - */ - private void gatherProperties(List fields, Element element) { + /** Recursively gather all the fields (properties) for the given bean element. */ + private static void gatherProperties(List fields, Element element) { TypeElement typeElement = (TypeElement) element; TypeMirror superclass = typeElement.getSuperclass(); - Element mappedSuper = typeUtils.asElement(superclass); + var mappedSuper = APContext.asTypeElement(superclass); if (isMappedSuperOrInheritance(mappedSuper)) { gatherProperties(fields, mappedSuper); } @@ -140,25 +107,21 @@ private void gatherProperties(List fields, Element element) { } } - /** - * Not interested in static, transient or Ebean internal fields. - */ - private boolean ignoreField(VariableElement field) { + /** Not interested in static, transient or Ebean internal fields. */ + private static boolean ignoreField(VariableElement field) { return isStaticOrTransient(field) || ignoreEbeanInternalFields(field); } - private boolean ignoreEbeanInternalFields(VariableElement field) { + private static boolean ignoreEbeanInternalFields(VariableElement field) { String fieldName = field.getSimpleName().toString(); return fieldName.startsWith("_ebean") || fieldName.startsWith("_EBEAN"); } - private boolean isStaticOrTransient(VariableElement field) { + private static boolean isStaticOrTransient(VariableElement field) { Set modifiers = field.getModifiers(); - return ( - modifiers.contains(Modifier.STATIC) || - modifiers.contains(Modifier.TRANSIENT) || - hasAnnotations(field, "jakarta.persistence.Transient") - ); + return (modifiers.contains(Modifier.STATIC) + || modifiers.contains(Modifier.TRANSIENT) + || hasAnnotations(field, "jakarta.persistence.Transient")); } private static boolean hasAnnotations(Element element, String... annotations) { @@ -180,50 +143,35 @@ private static AnnotationMirror getAnnotation(Element element, String... annotat return null; } - private boolean isMappedSuperOrInheritance(Element mappedSuper) { + private static boolean isMappedSuperOrInheritance(Element mappedSuper) { return hasAnnotations(mappedSuper, MAPPED_SUPERCLASS, INHERITANCE, DISCRIMINATOR_VALUE); } - private boolean isEntityOrEmbedded(Element mappedSuper) { - return hasAnnotations(mappedSuper, ENTITY, EMBEDDABLE); - } + private static boolean isEntityOrEmbedded(Element mappedSuper) { - boolean isEntity(Element element) { - return hasAnnotations(element, ENTITY); + return EntityPrism.isPresent(mappedSuper) || EmbeddablePrism.isPresent(mappedSuper); } - boolean isEmbeddable(Element element) { - return hasAnnotations(element, EMBEDDABLE); + static boolean isEmbeddable(Element element) { + return EmbeddablePrism.isPresent(element); } - /** - * Find the DbName annotation and return name if found. - */ - String findDbName(TypeElement element) { - return FindDbName.value(element, typeUtils); - } + /** Find the DbName annotation and return name if found. */ + static String findDbName(TypeElement element) { - /** - * Return true if it is a DbJson field. - */ - private static boolean dbJsonField(Element field) { - return hasAnnotations(field, DBJSON, DBJSONB); + return DbNamePrism.getOptionalOn(element).map(DbNamePrism::value).orElse(null); } - /** - * Return true if it is a DbArray field. - */ - private static boolean dbArrayField(Element field) { - return hasAnnotations(field, DBARRAY); + /** Return true if it is a DbJson field. */ + private static boolean dbJsonField(Element field) { + return DbJsonPrism.isPresent(field) || DbJsonBPrism.isPresent(field); } private static boolean dbToMany(Element field) { - return hasAnnotations(field, ONE_TO_MANY, MANY_TO_MANY); + return OneToManyPrism.isPresent(field) || ManyToManyPrism.isPresent(field); } - /** - * Escape the type (e.g. java.lang.String) from the TypeMirror toString(). - */ + /** Escape the type (e.g. java.lang.String) from the TypeMirror toString(). */ private static String typeDef(TypeMirror typeMirror) { if (typeMirror.getKind() == TypeKind.DECLARED) { DeclaredType declaredType = (DeclaredType) typeMirror; @@ -233,21 +181,12 @@ private static String typeDef(TypeMirror typeMirror) { } } - private String trimAnnotations(String type) { - int pos = type.indexOf("@"); - if (pos == -1) { - return type; - } - String remainder = type.substring(0, pos) + type.substring(type.indexOf(' ') + 1); - return trimAnnotations(remainder); - } - - PropertyType getPropertyType(VariableElement field) { + static PropertyType getPropertyType(VariableElement field) { boolean toMany = dbToMany(field); if (dbJsonField(field)) { - return propertyTypeMap.getDbJsonType(); + return CTX.get().propertyTypeMap.getDbJsonType(); } - if (dbArrayField(field)) { + if (DbArrayPrism.isPresent(field)) { // get generic parameter type DeclaredType declaredType = (DeclaredType) field.asType(); String fullType = typeDef(declaredType.getTypeArguments().get(0)); @@ -256,23 +195,23 @@ PropertyType getPropertyType(VariableElement field) { final TypeMirror typeMirror = field.asType(); TypeMirror currentType = typeMirror; while (currentType != null) { - PropertyType type = propertyTypeMap.getType(typeDef(currentType)); + PropertyType type = CTX.get().propertyTypeMap.getType(typeDef(currentType)); if (type != null) { // simple scalar type return type; } // go up in class hierarchy - TypeElement fieldType = (TypeElement) typeUtils.asElement(currentType); + TypeElement fieldType = APContext.asTypeElement(currentType); currentType = (fieldType == null) ? null : fieldType.getSuperclass(); } - Element fieldType = typeUtils.asElement(typeMirror); + Element fieldType = APContext.asTypeElement(typeMirror); if (fieldType == null) { return null; } // workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=544288 - fieldType = elementUtils.getTypeElement(fieldType.toString()); + fieldType = typeElement(fieldType.toString()); if (fieldType.getKind() == ElementKind.ENUM) { String fullType = typeDef(typeMirror); return new PropertyTypeEnum(fullType, Split.shortName(fullType)); @@ -281,7 +220,7 @@ PropertyType getPropertyType(VariableElement field) { // look for targetEntity annotation attribute final String targetEntity = readTargetEntity(field); if (targetEntity != null) { - final TypeElement element = elementUtils.getTypeElement(targetEntity); + final TypeElement element = typeElement(targetEntity); if (isEntityOrEmbedded(element)) { boolean embeddable = isEmbeddable(element); return createPropertyTypeAssoc(embeddable, toMany, typeDef(element.asType())); @@ -300,45 +239,27 @@ PropertyType getPropertyType(VariableElement field) { } else { result = null; } - if (result != null) { return result; + } else if (APContext.isAssignable(typeMirror.toString(), "java.lang.Comparable")) { + return new PropertyTypeScalarComparable(trimAnnotations(typeMirror.toString())); } else { - if (typeInstanceOf(typeMirror, "java.lang.Comparable")) { - return new PropertyTypeScalarComparable(trimAnnotations(typeMirror.toString())); - } else { - return new PropertyTypeScalar(trimAnnotations(typeMirror.toString())); - } + return new PropertyTypeScalar(trimAnnotations(typeMirror.toString())); } } - private boolean typeInstanceOf(final TypeMirror typeMirror, final CharSequence desiredInterface) { - TypeElement typeElement = (TypeElement) typeUtils.asElement(typeMirror); - if (typeElement == null || typeElement.getQualifiedName().contentEquals("java.lang.Object")) { - return false; - } - if (typeElement.getQualifiedName().contentEquals(desiredInterface)) { - return true; - } - - return typeInstanceOf(typeElement.getSuperclass(), desiredInterface) || - typeElement - .getInterfaces() - .stream() - .anyMatch(t -> typeInstanceOf(t, desiredInterface)); - } - - private PropertyType createManyTypeAssoc(VariableElement field, DeclaredType declaredType) { + private static PropertyType createManyTypeAssoc( + VariableElement field, DeclaredType declaredType) { boolean toMany = dbToMany(field); List typeArguments = declaredType.getTypeArguments(); if (typeArguments.size() == 1) { - Element argElement = typeUtils.asElement(typeArguments.get(0)); + Element argElement = APContext.asTypeElement(typeArguments.get(0)); if (isEntityOrEmbedded(argElement)) { boolean embeddable = isEmbeddable(argElement); return createPropertyTypeAssoc(embeddable, toMany, typeDef(argElement.asType())); } } else if (typeArguments.size() == 2) { - Element argElement = typeUtils.asElement(typeArguments.get(1)); + Element argElement = APContext.asTypeElement(typeArguments.get(1)); if (isEntityOrEmbedded(argElement)) { boolean embeddable = isEmbeddable(argElement); return createPropertyTypeAssoc(embeddable, toMany, typeDef(argElement.asType())); @@ -347,7 +268,7 @@ private PropertyType createManyTypeAssoc(VariableElement field, DeclaredType dec return null; } - private String readTargetEntity(Element declaredType) { + private static String readTargetEntity(Element declaredType) { for (AnnotationMirror annotation : declaredType.getAnnotationMirrors()) { final Object targetEntity = readTargetEntityFromAnnotation(annotation); if (targetEntity != null) { @@ -358,7 +279,8 @@ private String readTargetEntity(Element declaredType) { } private static Object readTargetEntityFromAnnotation(AnnotationMirror mirror) { - for (Map.Entry entry : mirror.getElementValues().entrySet()) { + for (Map.Entry entry : + mirror.getElementValues().entrySet()) { if ("targetEntity".equals(entry.getKey().getSimpleName().toString())) { return entry.getValue().getValue(); } @@ -366,11 +288,10 @@ private static Object readTargetEntityFromAnnotation(AnnotationMirror mirror) { return null; } - /** - * Create the QAssoc PropertyType. - */ - private PropertyType createPropertyTypeAssoc(boolean embeddable, boolean toMany, String fullName) { - TypeElement typeElement = elementUtils.getTypeElement(fullName); + /** Create the QAssoc PropertyType. */ + private static PropertyType createPropertyTypeAssoc( + boolean embeddable, boolean toMany, String fullName) { + TypeElement typeElement = typeElement(fullName); String type; if (typeElement.getNestingKind().isNested()) { type = typeElement.getEnclosingElement().toString() + "$" + typeElement.getSimpleName(); @@ -378,73 +299,48 @@ private PropertyType createPropertyTypeAssoc(boolean embeddable, boolean toMany, type = typeElement.getQualifiedName().toString(); } - String suffix = toMany ? "Many" : embeddable ? "": "One"; + String suffix = toMany ? "Many" : embeddable ? "" : "One"; String[] split = Split.split(type); String propertyName = "Q" + split[1] + ".Assoc" + suffix; String importName = split[0] + ".query.Q" + split[1]; return new PropertyTypeAssoc(propertyName, importName); } - /** - * Create a file writer for the given class name. - */ - JavaFileObject createWriter(String factoryClassName, Element originatingElement) throws IOException { - return filer.createSourceFile(factoryClassName, originatingElement); - } - - /** - * Create a file writer for the given class name without an originating element. - */ - JavaFileObject createWriter(String factoryClassName) throws IOException { - return filer.createSourceFile(factoryClassName); - } - - void logError(Element e, String msg, Object... args) { - messager.printMessage(Diagnostic.Kind.ERROR, String.format(msg, args), e); - } - - void logNote(String msg, Object... args) { - messager.printMessage(Diagnostic.Kind.NOTE, String.format(msg, args)); - } - - void readModuleInfo() { + static void readModuleInfo() { String factory = loadMetaInfServices(); if (factory != null) { - TypeElement factoryType = elementUtils.getTypeElement(factory); + TypeElement factoryType = APContext.typeElement(factory); if (factoryType != null) { + // previous prefixed entities to add back for partial compile - final ModuleMeta read = readModuleInfo.read(factoryType); - loadedPrefixEntities.addAll(read.getEntities()); - otherClasses.addAll(read.getOther()); + var p = ModuleInfoPrism.getInstanceOn(factoryType); + CTX.get().loadedPrefixEntities.addAll(p.entities()); + CTX.get().otherClasses.addAll(p.other()); } } } - /** - * Register an entity with optional dbName. - */ - void addEntity(String beanFullName, String dbName) { - loaded.add(beanFullName); + /** Register an entity with optional dbName. */ + static void addEntity(String beanFullName, String dbName) { + CTX.get().loaded.add(beanFullName); final String pkg = packageOf(beanFullName); if (pkg != null) { - allEntityPackages.add(pkg); + CTX.get().allEntityPackages.add(pkg); updateFactoryPackage(pkg); } if (dbName != null) { - prefixEntities.add(dbName + ":" + beanFullName); - otherDbEntities.computeIfAbsent(dbName, s -> new TreeSet<>()).add(beanFullName); + CTX.get().prefixEntities.add(dbName + ":" + beanFullName); + CTX.get().otherDbEntities.computeIfAbsent(dbName, s -> new TreeSet<>()).add(beanFullName); } else { - prefixEntities.add(beanFullName); - dbEntities.add(beanFullName); + CTX.get().prefixEntities.add(beanFullName); + CTX.get().dbEntities.add(beanFullName); } } - /** - * Add back entity classes for partial compile. - */ - int complete() { + /** Add back entity classes for partial compile. */ + static int complete() { int added = 0; - for (String oldPrefixEntity : loadedPrefixEntities) { + for (String oldPrefixEntity : CTX.get().loadedPrefixEntities) { // maybe split as dbName:entityClass final String[] prefixEntityClass = oldPrefixEntity.split(":"); @@ -456,7 +352,7 @@ int complete() { } else { entityClass = prefixEntityClass[0]; } - if (!loaded.contains(entityClass)) { + if (!CTX.get().loaded.contains(entityClass)) { addEntity(entityClass, dbName); added++; } @@ -464,7 +360,7 @@ int complete() { return added; } - private String packageOf(String beanFullName) { + private static String packageOf(String beanFullName) { final int pos = beanFullName.lastIndexOf('.'); if (pos > -1) { return beanFullName.substring(0, pos); @@ -472,69 +368,70 @@ private String packageOf(String beanFullName) { return null; } - private void updateFactoryPackage(String pkg) { - if (pkg != null && (factoryPackage == null || factoryPackage.length() > pkg.length())) { - factoryPackage = pkg; + private static void updateFactoryPackage(String pkg) { + if (pkg != null + && (CTX.get().factoryPackage == null || CTX.get().factoryPackage.length() > pkg.length())) { + CTX.get().factoryPackage = pkg; } } - FileObject createMetaInfServicesWriter() throws IOException { + static FileObject createMetaInfServicesWriter() throws IOException { return createMetaInfWriter(METAINF_SERVICES_MODULELOADER); } - FileObject createManifestWriter() throws IOException { + static FileObject createManifestWriter() throws IOException { return createMetaInfWriter(METAINF_MANIFEST); } - FileObject createNativeImageWriter(String name) throws IOException { + static FileObject createNativeImageWriter(String name) throws IOException { String nm = "META-INF/native-image/" + name + "/reflect-config.json"; return createMetaInfWriter(nm); } - FileObject createMetaInfWriter(String target) throws IOException { - return filer.createResource(StandardLocation.CLASS_OUTPUT, "", target); + static FileObject createMetaInfWriter(String target) throws IOException { + return filer().createResource(StandardLocation.CLASS_OUTPUT, "", target); } - public boolean hasOtherClasses() { - return !otherClasses.isEmpty(); + static boolean hasOtherClasses() { + return !CTX.get().otherClasses.isEmpty(); } - public Set getOtherClasses() { - return otherClasses; + static Set getOtherClasses() { + return CTX.get().otherClasses; } - void addOther(Element element) { - otherClasses.add(element.toString()); + static void addOther(Element element) { + CTX.get().otherClasses.add(element.toString()); } - Set getPrefixEntities() { - return prefixEntities; + static Set getPrefixEntities() { + return CTX.get().prefixEntities; } - Set getDbEntities() { - return dbEntities; + static Set getDbEntities() { + return CTX.get().dbEntities; } - Map> getOtherDbEntities() { - return otherDbEntities; + static Map> getOtherDbEntities() { + return CTX.get().otherDbEntities; } - - Set getAllEntityPackages() { - return allEntityPackages; + static Set getAllEntityPackages() { + return CTX.get().allEntityPackages; } - String getFactoryPackage() { - return factoryPackage != null ? factoryPackage : "unknown"; + static String getFactoryPackage() { + return CTX.get().factoryPackage != null ? CTX.get().factoryPackage : "unknown"; } /** - * Return the class name of the generated EntityClassRegister - * (such that we can read the current metadata for partial compile). + * Return the class name of the generated EntityClassRegister (such that we can read the current + * metadata for partial compile). */ - String loadMetaInfServices() { + static String loadMetaInfServices() { try { - FileObject fileObject = processingEnv.getFiler().getResource(StandardLocation.CLASS_OUTPUT, "", METAINF_SERVICES_MODULELOADER); + FileObject fileObject = + filer().getResource(StandardLocation.CLASS_OUTPUT, "", METAINF_SERVICES_MODULELOADER); if (fileObject != null) { Reader reader = fileObject.openReader(true); LineNumberReader lineReader = new LineNumberReader(reader); @@ -547,19 +444,24 @@ String loadMetaInfServices() { } catch (FileNotFoundException | NoSuchFileException e) { // ignore - no services file yet } catch (FilerException e) { - logNote(null, "FilerException reading services file: " + e.getMessage()); + logNote("FilerException reading services file: " + e.getMessage()); } catch (Exception e) { e.printStackTrace(); - logError(null, "Error reading services file: " + e.getMessage()); + logError("Error reading services file: " + e.getMessage()); } return null; } - Element asElement(TypeMirror mirror) { - return typeUtils.asElement(mirror); + static boolean isNameClash(String shortName) { + return CTX.get().propertyTypeMap.isNameClash(shortName); + } + + static void validateModule() { + APContext.moduleInfoReader() + .ifPresent(r -> r.validateServices(AT_GENERATED, CTX.get().services)); } - boolean isNameClash(String shortName) { - return propertyTypeMap.isNameClash(shortName); + public static void addService(String factoryFullName) { + CTX.get().services.add(factoryFullName); } } diff --git a/querybean-generator/src/main/java/io/ebean/querybean/generator/Processor.java b/querybean-generator/src/main/java/io/ebean/querybean/generator/Processor.java index 9579042a30..eaa5af1fbe 100644 --- a/querybean-generator/src/main/java/io/ebean/querybean/generator/Processor.java +++ b/querybean-generator/src/main/java/io/ebean/querybean/generator/Processor.java @@ -1,41 +1,44 @@ package io.ebean.querybean.generator; +import static io.ebean.querybean.generator.APContext.logError; +import static io.ebean.querybean.generator.APContext.logNote; +import static io.ebean.querybean.generator.APContext.typeElement; + +import java.util.Arrays; +import java.util.Optional; +import java.util.Set; + import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.ProcessingEnvironment; import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedAnnotationTypes; import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; -import java.util.Arrays; -import java.util.LinkedHashSet; -import java.util.Set; -/** - * Process compiled entity beans and generates 'query beans' for them. - */ +import io.avaje.prism.GenerateAPContext; +import io.avaje.prism.GenerateModuleInfoReader; +import io.avaje.prism.GenerateUtils; + +/** Process compiled entity beans and generates 'query beans' for them. */ +@GenerateUtils +@GenerateAPContext +@GenerateModuleInfoReader +@SupportedAnnotationTypes({ + ConverterPrism.PRISM_TYPE, + EbeanComponentPrism.PRISM_TYPE, + EntityPrism.PRISM_TYPE, + EmbeddablePrism.PRISM_TYPE, + ModuleInfoPrism.PRISM_TYPE +}) public class Processor extends AbstractProcessor implements Constants { - private ProcessingContext processingContext; private SimpleModuleInfoWriter moduleWriter; - public Processor() { - } - @Override public synchronized void init(ProcessingEnvironment processingEnv) { super.init(processingEnv); - this.processingContext = new ProcessingContext(processingEnv); - } - - @Override - public Set getSupportedAnnotationTypes() { - Set annotations = new LinkedHashSet<>(); - annotations.add(ENTITY); - annotations.add(EMBEDDABLE); - annotations.add(CONVERTER); - annotations.add(EBEAN_COMPONENT); - annotations.add(MODULEINFO); - return annotations; + ProcessingContext.init(processingEnv); } @Override @@ -45,28 +48,33 @@ public SourceVersion getSupportedSourceVersion() { @Override public boolean process(Set annotations, RoundEnvironment roundEnv) { - processingContext.readModuleInfo(); + APContext.setProjectModuleElement(annotations, roundEnv); + ProcessingContext.readModuleInfo(); int count = processEntities(roundEnv); processOthers(roundEnv); - final int loaded = processingContext.complete(); + final int loaded = ProcessingContext.complete(); initModuleInfoBean(); + if (count > 0) { + String msg = + "Ebean APT generated %s query beans, loaded %s others - META-INF/ebean-generated-info.mf entity-packages: %s"; + logNote(msg, count, loaded, ProcessingContext.getAllEntityPackages()); + } if (roundEnv.processingOver()) { writeModuleInfoBean(); - } - if (count > 0) { - String msg = "Ebean APT generated %s query beans, loaded %s others - META-INF/ebean-generated-info.mf entity-packages: %s"; - processingContext.logNote(msg, count, loaded, processingContext.getAllEntityPackages()); + ProcessingContext.validateModule(); + ProcessingContext.clear(); } return true; } private int processEntities(RoundEnvironment roundEnv) { int count = 0; - for (Element element : roundEnv.getElementsAnnotatedWith(processingContext.embeddableAnnotation())) { + + for (Element element : getElements(roundEnv, EmbeddablePrism.PRISM_TYPE)) { generateQueryBeans(element); count++; } - for (Element element : roundEnv.getElementsAnnotatedWith(processingContext.entityAnnotation())) { + for (Element element : getElements(roundEnv, EntityPrism.PRISM_TYPE)) { generateQueryBeans(element); count++; } @@ -74,50 +82,56 @@ private int processEntities(RoundEnvironment roundEnv) { } private void processOthers(RoundEnvironment round) { - processOthers(round, processingContext.converterAnnotation()); - processOthers(round, processingContext.componentAnnotation()); + getElements(round, ConverterPrism.PRISM_TYPE).forEach(ProcessingContext::addOther); + getElements(round, EbeanComponentPrism.PRISM_TYPE).forEach(ProcessingContext::addOther); } - private void processOthers(RoundEnvironment roundEnv, TypeElement otherType) { - if (otherType != null) { - for (Element element : roundEnv.getElementsAnnotatedWith(otherType)) { - processingContext.addOther(element); - } - } + private Set getElements(RoundEnvironment round, String name) { + return Optional.ofNullable(typeElement(name)) + .map(round::getElementsAnnotatedWith) + .orElse(Set.of()); } private void initModuleInfoBean() { try { if (moduleWriter == null) { - moduleWriter = new SimpleModuleInfoWriter(processingContext); + moduleWriter = new SimpleModuleInfoWriter(); } - } catch (Throwable e) { + } catch (Exception e) { e.printStackTrace(); - processingContext.logError(null, "Failed to initialise EntityClassRegister error:" + e + " stack:" + Arrays.toString(e.getStackTrace())); + logError( + "Failed to initialise EntityClassRegister error:" + + e + + " stack:" + + Arrays.toString(e.getStackTrace())); } } private void writeModuleInfoBean() { try { if (moduleWriter == null) { - processingContext.logError(null, "EntityClassRegister was not initialised and not written"); + logError("EntityClassRegister was not initialised and not written"); } else { moduleWriter.write(); } - } catch (Throwable e) { + } catch (Exception e) { e.printStackTrace(); - processingContext.logError(null, "Failed to write EntityClassRegister error:" + e + " stack:" + Arrays.toString(e.getStackTrace())); + logError( + "Failed to write EntityClassRegister error:" + + e + + " stack:" + + Arrays.toString(e.getStackTrace())); } } private void generateQueryBeans(Element element) { try { - SimpleQueryBeanWriter beanWriter = new SimpleQueryBeanWriter((TypeElement) element, processingContext); + SimpleQueryBeanWriter beanWriter = + new SimpleQueryBeanWriter((TypeElement) element); beanWriter.writeRootBean(); - } catch (Throwable e) { + } catch (Exception e) { e.printStackTrace(); - processingContext.logError(element, "Error generating query beans: " + e); + logError(element, "Error generating query beans: " + e); } } - } diff --git a/querybean-generator/src/main/java/io/ebean/querybean/generator/ReadModuleInfo.java b/querybean-generator/src/main/java/io/ebean/querybean/generator/ReadModuleInfo.java deleted file mode 100644 index 01f19a3044..0000000000 --- a/querybean-generator/src/main/java/io/ebean/querybean/generator/ReadModuleInfo.java +++ /dev/null @@ -1,69 +0,0 @@ -package io.ebean.querybean.generator; - -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 java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Helper to read the current/existing prefixed entity classes. - *

- * These are added back on partial compile. - */ -class ReadModuleInfo { - - private final ProcessingContext ctx; - - public ReadModuleInfo(ProcessingContext ctx) { - this.ctx = ctx; - } - - ModuleMeta read(Element element) { - final List mirrors = element.getAnnotationMirrors(); - for (AnnotationMirror mirror : mirrors) { - final String name = mirror.getAnnotationType().asElement().toString(); - if (Constants.MODULEINFO.equals(name)) { - List entities = readEntities("entities", mirror); - List other = readEntities("other", mirror); - return new ModuleMeta(entities, other); - } - } - return null; - } - - @SuppressWarnings("unchecked") - private List readEntities(String key, AnnotationMirror mirror) { - final Map elementValues = mirror.getElementValues(); - final Set> entries = elementValues.entrySet(); - - for (Map.Entry entry : entries) { - if (key.equals(entry.getKey().getSimpleName().toString())) { - return readAttributes(entry.getValue()); - } - } - return Collections.emptyList(); - } - - @SuppressWarnings("unchecked") - private List readAttributes(AnnotationValue value) { - final Object entitiesValue = value.getValue(); - if (entitiesValue != null) { - try { - List vals = new ArrayList<>(); - List coll = (List) entitiesValue; - for (AnnotationValue annotationValue : coll) { - vals.add((String) annotationValue.getValue()); - } - return vals; - } catch (Exception e) { - ctx.logError(null, "Error reading ModuleInfo annotation, err " + e); - } - } - return Collections.emptyList(); - } -} diff --git a/querybean-generator/src/main/java/io/ebean/querybean/generator/SimpleModuleInfoWriter.java b/querybean-generator/src/main/java/io/ebean/querybean/generator/SimpleModuleInfoWriter.java index 917e34b029..022e0b2a3c 100644 --- a/querybean-generator/src/main/java/io/ebean/querybean/generator/SimpleModuleInfoWriter.java +++ b/querybean-generator/src/main/java/io/ebean/querybean/generator/SimpleModuleInfoWriter.java @@ -1,7 +1,7 @@ package io.ebean.querybean.generator; -import javax.tools.FileObject; -import javax.tools.JavaFileObject; +import static io.ebean.querybean.generator.APContext.logError; + import java.io.IOException; import java.io.Writer; import java.util.LinkedHashSet; @@ -9,26 +9,25 @@ import java.util.Set; import java.util.StringJoiner; +import javax.tools.FileObject; +import javax.tools.JavaFileObject; + /** * Write the source code for the factory. */ class SimpleModuleInfoWriter { - private final ProcessingContext processingContext; - private final String factoryPackage; - private final String factoryShortName; + private final String factoryShortName= "EbeanEntityRegister"; private final String factoryFullName; private final JavaFileObject javaFileObject; private Append writer; - SimpleModuleInfoWriter(ProcessingContext processingContext) throws IOException { - this.processingContext = processingContext; - this.factoryPackage = processingContext.getFactoryPackage(); - this.factoryShortName = "EbeanEntityRegister"; + SimpleModuleInfoWriter() throws IOException { + this.factoryPackage = ProcessingContext.getFactoryPackage(); this.factoryFullName = factoryPackage + "." + factoryShortName; - this.javaFileObject = processingContext.createWriter(factoryFullName); + this.javaFileObject = APContext.createSourceFile(factoryFullName); } void write() throws IOException { @@ -44,22 +43,23 @@ void write() throws IOException { private void writeServicesFile() { try { - FileObject jfo = processingContext.createMetaInfServicesWriter(); + FileObject jfo = ProcessingContext.createMetaInfServicesWriter(); if (jfo != null) { Writer writer = jfo.openWriter(); + ProcessingContext.addService(factoryFullName); writer.write(factoryFullName); writer.close(); } } catch (IOException e) { - processingContext.logError(null, "Failed to write services file " + e.getMessage()); + logError("Failed to write services file " + e.getMessage()); } } private void writeManifestFile() { try { - final Set allEntityPackages = processingContext.getAllEntityPackages(); + final Set allEntityPackages = ProcessingContext.getAllEntityPackages(); if (!allEntityPackages.isEmpty()) { - FileObject jfo = processingContext.createManifestWriter(); + FileObject jfo = ProcessingContext.createManifestWriter(); if (jfo != null) { Writer writer = jfo.openWriter(); writer.write("generated-by: Ebean query bean generator\n"); @@ -69,7 +69,7 @@ private void writeManifestFile() { } } } catch (IOException e) { - processingContext.logError(null, "Failed to write services file " + e.getMessage()); + logError("Failed to write services file " + e.getMessage()); } } @@ -84,13 +84,13 @@ private String manifestEntityPackages(Set allEntityPackages) { private void writeNativeImageFile() { try { - Set allEntities = new LinkedHashSet<>(processingContext.getDbEntities()); - for (Set value : processingContext.getOtherDbEntities().values()) { + Set allEntities = new LinkedHashSet<>(ProcessingContext.getDbEntities()); + for (Set value : ProcessingContext.getOtherDbEntities().values()) { allEntities.addAll(value); } if (!allEntities.isEmpty()) { - FileObject jfo = processingContext.createNativeImageWriter(factoryPackage + ".ebean-entity"); + FileObject jfo = ProcessingContext.createNativeImageWriter(factoryPackage + ".ebean-entity"); if (jfo != null) { boolean first = true; Writer writer = jfo.openWriter(); @@ -111,7 +111,7 @@ private void writeNativeImageFile() { } } } catch (IOException e) { - processingContext.logError(null, "Failed to write services file " + e.getMessage()); + logError("Failed to write services file " + e.getMessage()); } } @@ -130,7 +130,7 @@ private void writePackage() { void buildAtContextModule(Append writer) { writer.append(Constants.AT_GENERATED).eol(); writer.append("@ModuleInfo("); - if (processingContext.hasOtherClasses()) { + if (ProcessingContext.hasOtherClasses()) { writer.append("other={%s}, ", otherClasses()); } writer.append("entities={%s}", prefixEntities()); @@ -138,11 +138,11 @@ void buildAtContextModule(Append writer) { } private String otherClasses() { - return quoteTypes(processingContext.getOtherClasses()); + return quoteTypes(ProcessingContext.getOtherClasses()); } private String prefixEntities() { - return quoteTypes(processingContext.getPrefixEntities()); + return quoteTypes(ProcessingContext.getPrefixEntities()); } private String quoteTypes(Set otherClasses) { @@ -158,9 +158,9 @@ private void writeStartClass() { writer.append("public class %s implements EntityClassRegister {", factoryShortName).eol().eol(); writeMethodOtherClasses(); - writeMethodEntityClasses(processingContext.getDbEntities(), null); + writeMethodEntityClasses(ProcessingContext.getDbEntities(), null); - final Map> otherDbEntities = processingContext.getOtherDbEntities(); + final Map> otherDbEntities = ProcessingContext.getOtherDbEntities(); for (Map.Entry> otherDb : otherDbEntities.entrySet()) { writeMethodEntityClasses(otherDb.getValue(), otherDb.getKey()); } @@ -171,11 +171,11 @@ private void writeStartClass() { private void writeMethodOtherClasses() { writeMethodComment("Register AttributeConverter etc", ""); writer.append(" private List> otherClasses() {").eol(); - if (!processingContext.hasOtherClasses()) { + if (!ProcessingContext.hasOtherClasses()) { writer.append(" return Collections.emptyList();").eol(); } else { writer.append(" List> others = new ArrayList<>();").eol(); - for (String otherType : processingContext.getOtherClasses()) { + for (String otherType : ProcessingContext.getOtherClasses()) { writer.append(" others.add(%s.class);", otherType).eol(); } writer.append(" return others;").eol(); @@ -192,14 +192,14 @@ private void writeMethodEntityClasses(Set dbEntities, String dbName) { writeMethodComment("Entities with no @DbName", dbName); } writer.append(" private List> %s() {", method).eol(); - if (dbEntities.isEmpty() && !processingContext.hasOtherClasses()) { + if (dbEntities.isEmpty() && !ProcessingContext.hasOtherClasses()) { writer.append(" return Collections.emptyList();").eol(); } else { writer.append(" List> entities = new ArrayList<>();").eol(); for (String dbEntity : dbEntities) { writer.append(" entities.add(%s.class);", dbEntity).eol(); } - if (processingContext.hasOtherClasses()) { + if (ProcessingContext.hasOtherClasses()) { writer.append(" entities.addAll(otherClasses());").eol(); } writer.append(" return entities;").eol(); diff --git a/querybean-generator/src/main/java/io/ebean/querybean/generator/SimpleQueryBeanWriter.java b/querybean-generator/src/main/java/io/ebean/querybean/generator/SimpleQueryBeanWriter.java index c642146835..4f8887ac0e 100644 --- a/querybean-generator/src/main/java/io/ebean/querybean/generator/SimpleQueryBeanWriter.java +++ b/querybean-generator/src/main/java/io/ebean/querybean/generator/SimpleQueryBeanWriter.java @@ -1,10 +1,9 @@ package io.ebean.querybean.generator; -import javax.lang.model.element.TypeElement; -import javax.lang.model.element.VariableElement; -import javax.lang.model.type.TypeMirror; -import javax.tools.JavaFileObject; +import static io.ebean.querybean.generator.APContext.asTypeElement; +import static io.ebean.querybean.generator.APContext.createSourceFile; + import java.io.IOException; import java.io.Writer; import java.util.ArrayList; @@ -12,6 +11,11 @@ import java.util.Set; import java.util.TreeSet; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.TypeMirror; +import javax.tools.JavaFileObject; + /** * A simple implementation that generates and writes query beans. */ @@ -22,7 +26,6 @@ class SimpleQueryBeanWriter { private final TypeElement element; private final TypeElement implementsInterface; private String implementsInterfaceShortName; - private final ProcessingContext processingContext; private final String dbName; private final String beanFullName; private final boolean isEntity; @@ -34,25 +37,24 @@ class SimpleQueryBeanWriter { private final boolean fullyQualify; private Append writer; - SimpleQueryBeanWriter(TypeElement element, ProcessingContext processingContext) { + SimpleQueryBeanWriter(TypeElement element) { this.element = element; - this.processingContext = processingContext; this.beanFullName = element.getQualifiedName().toString(); boolean nested = element.getNestingKind().isNested(); this.destPackage = Util.packageOf(nested, beanFullName) + ".query"; String sn = Util.shortName(nested, beanFullName); this.shortInnerName = Util.shortName(false, sn); this.shortName = sn.replace('.', '$'); - this.isEntity = processingContext.isEntity(element); - this.embeddable = processingContext.isEmbeddable(element); + this.isEntity = EntityPrism.isPresent(element); + this.embeddable = ProcessingContext.isEmbeddable(element); this.dbName = findDbName(); this.implementsInterface = initInterface(element); - this.fullyQualify = processingContext.isNameClash(shortName); + this.fullyQualify = ProcessingContext.isNameClash(shortName); } private TypeElement initInterface(TypeElement element) { for (TypeMirror anInterface : element.getInterfaces()) { - TypeElement e = (TypeElement)processingContext.asElement(anInterface); + TypeElement e = asTypeElement(anInterface); String name = e.getQualifiedName().toString(); if (!name.startsWith("java") && !name.startsWith("io.ebean")) { return e; @@ -62,7 +64,7 @@ private TypeElement initInterface(TypeElement element) { } private String findDbName() { - return processingContext.findDbName(element); + return ProcessingContext.findDbName(element); } private boolean isEntity() { @@ -88,8 +90,8 @@ private void gatherPropertyDetails() { * Includes properties from mapped super classes and usual inheritance. */ private void addClassProperties() { - for (VariableElement field : processingContext.allFields(element)) { - PropertyType type = processingContext.getPropertyType(field); + for (VariableElement field : ProcessingContext.allFields(element)) { + PropertyType type = ProcessingContext.getPropertyType(field); if (type != null) { type.addImports(importTypes, fullyQualify); properties.add(new PropertyMeta(field.getSimpleName().toString(), type)); @@ -102,7 +104,7 @@ private void addClassProperties() { */ void writeRootBean() throws IOException { gatherPropertyDetails(); - processingContext.addEntity(beanFullName, dbName); + ProcessingContext.addEntity(beanFullName, dbName); writer = new Append(createFileWriter()); writePackage(); writeImports(); @@ -339,15 +341,13 @@ private void writeAssocBeanConstructor(String prefix) { } private void writeAssocBeanFetch() { - if (isEntity()) { - // inherit the fetch methods - if (implementsInterface != null) { - writeAssocBeanExpression(false, "eq", "Is equal to by ID property."); - writeAssocBeanExpression(true, "eqIfPresent", "Is equal to by ID property if the value is not null, if null no expression is added."); - writeAssocBeanExpression(false, "in", "IN the given values.", implementsInterfaceShortName + "...", "in"); - writeAssocBeanExpression(false, "inBy", "IN the given interface values.", "Collection", "in"); - writeAssocBeanExpression(true, "inOrEmptyBy", "IN the given interface values if the collection is not empty. No expression is added if the collection is empty..", "Collection", "inOrEmpty"); - } + // inherit the fetch methods + if (isEntity() && (implementsInterface != null)) { + writeAssocBeanExpression(false, "eq", "Is equal to by ID property."); + writeAssocBeanExpression(true, "eqIfPresent", "Is equal to by ID property if the value is not null, if null no expression is added."); + writeAssocBeanExpression(false, "in", "IN the given values.", implementsInterfaceShortName + "...", "in"); + writeAssocBeanExpression(false, "inBy", "IN the given interface values.", "Collection", "in"); + writeAssocBeanExpression(true, "inOrEmptyBy", "IN the given interface values if the collection is not empty. No expression is added if the collection is empty..", "Collection", "inOrEmpty"); } } @@ -358,7 +358,7 @@ private void writeAssocBeanExpression(boolean nullable,String expression, String private void writeAssocBeanExpression(boolean nullable, String expression, String comment, String param, String actualExpression) { final String nullableAnnotation = nullable ? "@Nullable " : ""; String values = expression.startsWith("in") ? "values" : "value"; - String castVarargs = expression.equals("in") ? "(Object[])" : ""; + String castVarargs = "in".equals(expression) ? "(Object[])" : ""; writer.append(" /**").eol(); writer.append(" * ").append(comment).eol(); writer.append(" */").eol(); @@ -388,7 +388,7 @@ private void writePackage() { } private Writer createFileWriter() throws IOException { - JavaFileObject jfo = processingContext.createWriter(destPackage + "." + "Q" + shortName, element); + JavaFileObject jfo = createSourceFile(destPackage + "." + "Q" + shortName, element); return jfo.openWriter(); } diff --git a/querybean-generator/src/main/java/io/ebean/querybean/generator/package-info.java b/querybean-generator/src/main/java/io/ebean/querybean/generator/package-info.java new file mode 100644 index 0000000000..4ae287c355 --- /dev/null +++ b/querybean-generator/src/main/java/io/ebean/querybean/generator/package-info.java @@ -0,0 +1,23 @@ +@GeneratePrism(io.ebean.annotation.DbArray.class) +@GeneratePrism(io.ebean.annotation.DbJson.class) +@GeneratePrism(io.ebean.annotation.DbJsonB.class) +@GeneratePrism(io.ebean.annotation.DbName.class) +@GeneratePrism(io.ebean.annotation.DbName.class) +@GeneratePrism(io.ebean.annotation.EbeanComponent.class) +@GeneratePrism(io.ebean.config.ModuleInfo.class) +@GeneratePrism(io.ebean.config.ModuleInfo.class) +@GeneratePrism(io.ebean.typequery.Generated.class) + +@GeneratePrism(jakarta.persistence.Converter.class) +@GeneratePrism(jakarta.persistence.DiscriminatorValue.class) +@GeneratePrism(jakarta.persistence.Embeddable.class) +@GeneratePrism(jakarta.persistence.Embeddable.class) +@GeneratePrism(jakarta.persistence.Entity.class) +@GeneratePrism(jakarta.persistence.Entity.class) +@GeneratePrism(jakarta.persistence.Inheritance.class) +@GeneratePrism(jakarta.persistence.ManyToMany.class) +@GeneratePrism(jakarta.persistence.MappedSuperclass.class) +@GeneratePrism(jakarta.persistence.OneToMany.class) +package io.ebean.querybean.generator; + +import io.avaje.prism.GeneratePrism; diff --git a/querybean-generator/src/main/java/module-info.java b/querybean-generator/src/main/java/module-info.java index f864e9528e..2c57458f45 100644 --- a/querybean-generator/src/main/java/module-info.java +++ b/querybean-generator/src/main/java/module-info.java @@ -1,7 +1,14 @@ module io.ebean.querybean.generator { - provides javax.annotation.processing.Processor with io.ebean.querybean.generator.Processor; - requires java.compiler; requires java.sql; + + requires static io.avaje.prism; + requires static io.ebean.api; + requires static io.ebean.annotation; + requires static io.ebean.querybean; + requires static jakarta.persistence.api; + + provides javax.annotation.processing.Processor with io.ebean.querybean.generator.Processor; + } diff --git a/querybean-generator/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/querybean-generator/src/main/resources/META-INF/services/javax.annotation.processing.Processor deleted file mode 100644 index 0ca63ab195..0000000000 --- a/querybean-generator/src/main/resources/META-INF/services/javax.annotation.processing.Processor +++ /dev/null @@ -1 +0,0 @@ -io.ebean.querybean.generator.Processor \ No newline at end of file diff --git a/querybean-generator/src/test/java/io/ebean/querybean/generator/QueryBeanProcessorTest.java b/querybean-generator/src/test/java/io/ebean/querybean/generator/QueryBeanProcessorTest.java new file mode 100644 index 0000000000..3ee00563e8 --- /dev/null +++ b/querybean-generator/src/test/java/io/ebean/querybean/generator/QueryBeanProcessorTest.java @@ -0,0 +1,68 @@ +package io.ebean.querybean.generator; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.File; +import java.io.PrintWriter; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Comparator; +import java.util.List; +import java.util.Set; + +import javax.tools.JavaCompiler; +import javax.tools.JavaCompiler.CompilationTask; +import javax.tools.JavaFileObject; +import javax.tools.JavaFileObject.Kind; +import javax.tools.StandardJavaFileManager; +import javax.tools.StandardLocation; +import javax.tools.ToolProvider; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +class QueryBeanProcessorTest { + + @AfterEach + void deleteGeneratedFiles() throws Exception { + + Paths.get("ebean-generated-info.mf").toAbsolutePath().toFile().delete(); + Paths.get("io.ebean.config.EntityClassRegister").toAbsolutePath().toFile().delete(); + Paths.get("reflect-config.json").toAbsolutePath().toFile().delete(); + Files.walk(Paths.get("io").toAbsolutePath()) + .sorted(Comparator.reverseOrder()) + .map(Path::toFile) + .forEach(File::delete); + } + + @Test + void testGeneration() throws Exception { + final String source = + Paths.get("src/test/java/io/ebean/querybean/generator/entities") + .toAbsolutePath() + .toString(); + + final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + final StandardJavaFileManager manager = compiler.getStandardFileManager(null, null, null); + + manager.setLocation(StandardLocation.SOURCE_PATH, List.of(new File(source))); + + final Set fileKinds = Set.of(Kind.SOURCE); + + final Iterable files = + manager.list(StandardLocation.SOURCE_PATH, "", fileKinds, true); + + final CompilationTask task = + compiler.getTask( + new PrintWriter(System.out), + null, + null, + List.of("--release=" + Integer.getInteger("java.specification.version")), + null, + files); + task.setProcessors(List.of(new Processor())); + + assertThat(task.call()).isTrue(); + } +} diff --git a/querybean-generator/src/test/java/io/ebean/querybean/generator/entities/ArticleEntity.java b/querybean-generator/src/test/java/io/ebean/querybean/generator/entities/ArticleEntity.java new file mode 100644 index 0000000000..7b95f3f46f --- /dev/null +++ b/querybean-generator/src/test/java/io/ebean/querybean/generator/entities/ArticleEntity.java @@ -0,0 +1,127 @@ +package io.ebean.querybean.generator.entities; + +import io.ebean.Model; +import io.ebean.annotation.WhenCreated; +import io.ebean.annotation.WhenModified; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +@Entity +@Table(name = "realworld.article") +public class ArticleEntity extends Model { + + @Id @GeneratedValue private UUID id; + + @WhenCreated + @Column(nullable = false, updatable = false) + private LocalDateTime createdAt; + + @WhenModified + @Column(nullable = false) + private LocalDateTime updatedAt; + + @ManyToOne(fetch = FetchType.EAGER) + @JoinColumn(name = "user_id", nullable = false) + private UserEntity author; + + @Column(nullable = false) + private String slug; + + @Column(nullable = false) + private String title; + + @Column(nullable = false) + private String description; + + @Column(nullable = false) + private String body; + + @OneToMany(mappedBy = "article", cascade = CascadeType.ALL, fetch = FetchType.EAGER) + private final List tags = new ArrayList<>(); + + public UUID id() { + return id; + } + + public ArticleEntity id(UUID id) { + this.id = id; + return this; + } + + public UserEntity author() { + return author; + } + + public ArticleEntity author(UserEntity user) { + this.author = user; + return this; + } + + public String slug() { + return slug; + } + + public ArticleEntity slug(String slug) { + this.slug = slug; + return this; + } + + public String title() { + return title; + } + + public ArticleEntity title(String title) { + this.title = title; + return this; + } + + public String description() { + return description; + } + + public ArticleEntity description(String description) { + this.description = description; + return this; + } + + public String body() { + return body; + } + + public ArticleEntity body(String body) { + this.body = body; + return this; + } + + public List tags() { + return tags; + } + + public LocalDateTime createdAt() { + return createdAt; + } + + public void createdAt(LocalDateTime createdAt) { + this.createdAt = createdAt; + } + + public LocalDateTime updatedAt() { + return updatedAt; + } + + public void updatedAt(LocalDateTime updatedAt) { + this.updatedAt = updatedAt; + } +} diff --git a/querybean-generator/src/test/java/io/ebean/querybean/generator/entities/ArticleTags.java b/querybean-generator/src/test/java/io/ebean/querybean/generator/entities/ArticleTags.java new file mode 100644 index 0000000000..058fe04cdf --- /dev/null +++ b/querybean-generator/src/test/java/io/ebean/querybean/generator/entities/ArticleTags.java @@ -0,0 +1,72 @@ +package io.ebean.querybean.generator.entities; + +import java.util.UUID; + +import io.ebean.Model; +import jakarta.persistence.Embeddable; +import jakarta.persistence.EmbeddedId; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; + +@Entity +@Table(name = "realworld.article_tag") +public class ArticleTags extends Model { + + @EmbeddedId private ArticleTagId id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "article_id", nullable = false, insertable = false, updatable = false) + private final ArticleEntity article; + + @ManyToOne(fetch = FetchType.EAGER) + @JoinColumn(name = "tag_id", nullable = false, insertable = false, updatable = false) + private final TagEntity tag; + + public ArticleTags(ArticleEntity article, TagEntity tag) { + this.article = article; + this.tag = tag; + } + + public ArticleEntity article() { + return article; + } + + public TagEntity tag() { + return tag; + } + + public ArticleTagId id() { + return id; + } + + public void id(ArticleTagId id) { + this.id = id; + } + + @Embeddable + public static class ArticleTagId { + UUID articleId; + UUID tagId; + + public ArticleTagId(UUID articleId, UUID tagId) {} + + public UUID getArticleId() { + return articleId; + } + + public void setArticleId(UUID articleId) { + this.articleId = articleId; + } + + public UUID getTagId() { + return tagId; + } + + public void setTagId(UUID tagId) { + this.tagId = tagId; + } + } +} diff --git a/querybean-generator/src/test/java/io/ebean/querybean/generator/entities/CommentEntity.java b/querybean-generator/src/test/java/io/ebean/querybean/generator/entities/CommentEntity.java new file mode 100644 index 0000000000..a3c1a785d0 --- /dev/null +++ b/querybean-generator/src/test/java/io/ebean/querybean/generator/entities/CommentEntity.java @@ -0,0 +1,52 @@ +package io.ebean.querybean.generator.entities; + +import io.ebean.Model; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.NamedAttributeNode; +import jakarta.persistence.NamedEntityGraph; +import jakarta.persistence.Table; + +@Entity +@Table(name = "comments") +@NamedEntityGraph(name = "fetch-author", attributeNodes = @NamedAttributeNode("author")) +public class CommentEntity extends Model { + + @Column(nullable = false) + private String body; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "author_id", nullable = false) + private UserEntity author; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "article_id", nullable = false) + private ArticleEntity article; + + public String getBody() { + return body; + } + + public void setBody(String body) { + this.body = body; + } + + public UserEntity getAuthor() { + return author; + } + + public void setAuthor(UserEntity author) { + this.author = author; + } + + public ArticleEntity getArticle() { + return article; + } + + public void setArticle(ArticleEntity article) { + this.article = article; + } +} diff --git a/querybean-generator/src/test/java/io/ebean/querybean/generator/entities/FavoriteEntity.java b/querybean-generator/src/test/java/io/ebean/querybean/generator/entities/FavoriteEntity.java new file mode 100644 index 0000000000..c49283e91c --- /dev/null +++ b/querybean-generator/src/test/java/io/ebean/querybean/generator/entities/FavoriteEntity.java @@ -0,0 +1,40 @@ +package io.ebean.querybean.generator.entities; + +import io.ebean.Model; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import java.util.UUID; + +@Entity +@Table(name = "favorites") +public class FavoriteEntity extends Model { + + @Id UUID id; + + @ManyToOne(fetch = FetchType.LAZY) + private ArticleEntity article; + + @ManyToOne(fetch = FetchType.LAZY) + private UserEntity user; + + public ArticleEntity article() { + return article; + } + + public FavoriteEntity article(ArticleEntity article) { + this.article = article; + return this; + } + + public UserEntity user() { + return user; + } + + public FavoriteEntity user(UserEntity user) { + this.user = user; + return this; + } +} diff --git a/querybean-generator/src/test/java/io/ebean/querybean/generator/entities/TagEntity.java b/querybean-generator/src/test/java/io/ebean/querybean/generator/entities/TagEntity.java new file mode 100644 index 0000000000..dc06b59a23 --- /dev/null +++ b/querybean-generator/src/test/java/io/ebean/querybean/generator/entities/TagEntity.java @@ -0,0 +1,27 @@ +package io.ebean.querybean.generator.entities; + +import io.ebean.Model; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import java.util.UUID; + +@Entity +@Table(name = "realworld.tag") +public class TagEntity extends Model { + @Id private final UUID id; + private final String name; + + public TagEntity(UUID id, String name) { + this.id = id; + this.name = name; + } + + public UUID id() { + return id; + } + + public String name() { + return name; + } +} diff --git a/querybean-generator/src/test/java/io/ebean/querybean/generator/entities/UserEntity.java b/querybean-generator/src/test/java/io/ebean/querybean/generator/entities/UserEntity.java new file mode 100644 index 0000000000..daa1cca30f --- /dev/null +++ b/querybean-generator/src/test/java/io/ebean/querybean/generator/entities/UserEntity.java @@ -0,0 +1,86 @@ +package io.ebean.querybean.generator.entities; + +import io.ebean.Model; +import io.ebean.annotation.Encrypted; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import java.util.UUID; + +@Entity +@Table(name = "realworld.user") +public class UserEntity extends Model { + + @Id @GeneratedValue private UUID id; + + @Column(nullable = false, unique = true) + private String username; + + @Encrypted + @Column(nullable = false) + private String passwordHash; + + @Column(nullable = false, unique = true) + private String email; + + @Column(nullable = false) + private String bio; + + private String image; + + public UUID id() { + return id; + } + + public UserEntity id(UUID id) { + this.id = id; + return this; + } + + public String username() { + return username; + } + + public UserEntity username(String username) { + this.username = username; + return this; + } + + public String passwordHash() { + return passwordHash; + } + + public UserEntity passwordHash(String passwordHash) { + this.passwordHash = passwordHash; + return this; + } + + public String email() { + return email; + } + + public UserEntity email(String email) { + this.email = email; + return this; + } + + public String bio() { + return bio; + } + + public UserEntity bio(String bio) { + this.bio = bio; + return this; + } + + public String image() { + return image; + } + + public UserEntity image(String image) { + this.image = image; + return this; + } +} From 15d7f4719ab32b04478643009dc43fafbb44a869 Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Sat, 14 Dec 2024 16:00:43 -0500 Subject: [PATCH 02/10] remove unneeded prisms --- ebean-querybean/pom.xml | 7 +++++++ querybean-generator/pom.xml | 7 ------- .../java/io/ebean/querybean/generator/package-info.java | 8 -------- querybean-generator/src/main/java/module-info.java | 1 - 4 files changed, 7 insertions(+), 16 deletions(-) diff --git a/ebean-querybean/pom.xml b/ebean-querybean/pom.xml index 95f5bec71a..0346f5ca6d 100644 --- a/ebean-querybean/pom.xml +++ b/ebean-querybean/pom.xml @@ -77,6 +77,13 @@ test + + io.ebean + querybean-generator + 14.8.0 + provided + + diff --git a/querybean-generator/pom.xml b/querybean-generator/pom.xml index c24583a02b..a97aa8ecd2 100644 --- a/querybean-generator/pom.xml +++ b/querybean-generator/pom.xml @@ -23,13 +23,6 @@ true provided - - io.ebean - ebean-querybean - ${project.version} - true - provided - io.ebean jakarta-persistence-api diff --git a/querybean-generator/src/main/java/io/ebean/querybean/generator/package-info.java b/querybean-generator/src/main/java/io/ebean/querybean/generator/package-info.java index 4ae287c355..95cc2e7594 100644 --- a/querybean-generator/src/main/java/io/ebean/querybean/generator/package-info.java +++ b/querybean-generator/src/main/java/io/ebean/querybean/generator/package-info.java @@ -2,21 +2,13 @@ @GeneratePrism(io.ebean.annotation.DbJson.class) @GeneratePrism(io.ebean.annotation.DbJsonB.class) @GeneratePrism(io.ebean.annotation.DbName.class) -@GeneratePrism(io.ebean.annotation.DbName.class) @GeneratePrism(io.ebean.annotation.EbeanComponent.class) @GeneratePrism(io.ebean.config.ModuleInfo.class) -@GeneratePrism(io.ebean.config.ModuleInfo.class) -@GeneratePrism(io.ebean.typequery.Generated.class) @GeneratePrism(jakarta.persistence.Converter.class) -@GeneratePrism(jakarta.persistence.DiscriminatorValue.class) @GeneratePrism(jakarta.persistence.Embeddable.class) -@GeneratePrism(jakarta.persistence.Embeddable.class) -@GeneratePrism(jakarta.persistence.Entity.class) @GeneratePrism(jakarta.persistence.Entity.class) -@GeneratePrism(jakarta.persistence.Inheritance.class) @GeneratePrism(jakarta.persistence.ManyToMany.class) -@GeneratePrism(jakarta.persistence.MappedSuperclass.class) @GeneratePrism(jakarta.persistence.OneToMany.class) package io.ebean.querybean.generator; diff --git a/querybean-generator/src/main/java/module-info.java b/querybean-generator/src/main/java/module-info.java index 2c57458f45..3bce8926e4 100644 --- a/querybean-generator/src/main/java/module-info.java +++ b/querybean-generator/src/main/java/module-info.java @@ -6,7 +6,6 @@ requires static io.avaje.prism; requires static io.ebean.api; requires static io.ebean.annotation; - requires static io.ebean.querybean; requires static jakarta.persistence.api; provides javax.annotation.processing.Processor with io.ebean.querybean.generator.Processor; From 27ba6513afdeb39854ba7feeb5818cfe0b1f2c05 Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Sat, 14 Dec 2024 16:05:19 -0500 Subject: [PATCH 03/10] Update QueryBeanProcessorTest.java --- .../io/ebean/querybean/generator/QueryBeanProcessorTest.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/querybean-generator/src/test/java/io/ebean/querybean/generator/QueryBeanProcessorTest.java b/querybean-generator/src/test/java/io/ebean/querybean/generator/QueryBeanProcessorTest.java index 3ee00563e8..3c2ccbbf65 100644 --- a/querybean-generator/src/test/java/io/ebean/querybean/generator/QueryBeanProcessorTest.java +++ b/querybean-generator/src/test/java/io/ebean/querybean/generator/QueryBeanProcessorTest.java @@ -20,6 +20,7 @@ import javax.tools.ToolProvider; import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; class QueryBeanProcessorTest { @@ -36,7 +37,8 @@ void deleteGeneratedFiles() throws Exception { .forEach(File::delete); } - @Test + // uncomment this to debug the processor for diagnosing issues + // @Test void testGeneration() throws Exception { final String source = Paths.get("src/test/java/io/ebean/querybean/generator/entities") From e39a548f022a475dff0821a59c723db453559e8d Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Mon, 16 Dec 2024 22:56:53 -0500 Subject: [PATCH 04/10] auto add maven plugin Revert "auto add maven plugin" This reverts commit 6566e9fa0f8efb28b847553d9ac5b7879530db3c. Reapply "auto add maven plugin" This reverts commit 6cd723ba936b389e8291dc879ffd58977d5dc69e. Update pom.xml --- pom.xml | 13 ++++ querybean-generator/pom.xml | 2 +- .../querybean/generator/PomPluginWriter.java | 59 +++++++++++++++++++ .../ebean/querybean/generator/Processor.java | 27 +++++++++ 4 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 querybean-generator/src/main/java/io/ebean/querybean/generator/PomPluginWriter.java diff --git a/pom.xml b/pom.xml index 0ea3b58003..201b3278fd 100644 --- a/pom.xml +++ b/pom.xml @@ -124,5 +124,18 @@ + + + + org.apache.maven.plugins + maven-compiler-plugin + + + -AbuildPlugin=false + + + + + diff --git a/querybean-generator/pom.xml b/querybean-generator/pom.xml index a97aa8ecd2..25dfb4f2f6 100644 --- a/querybean-generator/pom.xml +++ b/querybean-generator/pom.xml @@ -12,7 +12,7 @@ querybean-generator - 1.36 + 1.37 diff --git a/querybean-generator/src/main/java/io/ebean/querybean/generator/PomPluginWriter.java b/querybean-generator/src/main/java/io/ebean/querybean/generator/PomPluginWriter.java new file mode 100644 index 0000000000..275e1ad8e0 --- /dev/null +++ b/querybean-generator/src/main/java/io/ebean/querybean/generator/PomPluginWriter.java @@ -0,0 +1,59 @@ +package io.ebean.querybean.generator; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.StandardOpenOption; + +final class PomPluginWriter { + + private static final String PLUGIN = + " \n" + + " \n" + + " io.ebean\n" + + " ebean-maven-plugin\n" + + " %s\n" + + " \n" + + " \n" + + " " + + " \n" + + " enhance\n" + + " testEnhance\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " "; + + static void addPlugin2Pom() throws IOException { + + if (disabled()) { + return; + } + + var pomPath = APContext.getBuildResource("").getParent().resolve("pom.xml"); + if (!pomPath.toFile().exists()) { + return; + } + + var pomContent = Files.readString(pomPath); + // if not already present in pom.xml + if (pomContent.contains("ebean-maven-plugin")) { + return; + } + APContext.logNote("Adding ebean-maven-plugin to pom"); + var pluginsIndex = pomContent.indexOf(""); + var builder = new StringBuilder(pomContent); + if (pluginsIndex != -1) { + builder.insert( + pluginsIndex, + String.format(PLUGIN, PomPluginWriter.class.getPackage().getImplementationVersion())); + + Files.writeString( + pomPath, builder.toString(), StandardOpenOption.CREATE, StandardOpenOption.WRITE); + } + } + + private static boolean disabled() { + return !APContext.getOption("buildPlugin").map(Boolean::valueOf).orElse(true); + } +} diff --git a/querybean-generator/src/main/java/io/ebean/querybean/generator/Processor.java b/querybean-generator/src/main/java/io/ebean/querybean/generator/Processor.java index eaa5af1fbe..9476c31351 100644 --- a/querybean-generator/src/main/java/io/ebean/querybean/generator/Processor.java +++ b/querybean-generator/src/main/java/io/ebean/querybean/generator/Processor.java @@ -3,15 +3,21 @@ import static io.ebean.querybean.generator.APContext.logError; import static io.ebean.querybean.generator.APContext.logNote; import static io.ebean.querybean.generator.APContext.typeElement; +import static java.util.stream.Collectors.joining; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.StandardOpenOption; import java.util.Arrays; import java.util.Optional; import java.util.Set; +import java.util.stream.Stream; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.ProcessingEnvironment; import javax.annotation.processing.RoundEnvironment; import javax.annotation.processing.SupportedAnnotationTypes; +import javax.annotation.processing.SupportedOptions; import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; @@ -24,6 +30,7 @@ @GenerateUtils @GenerateAPContext @GenerateModuleInfoReader +@SupportedOptions("buildPlugin") @SupportedAnnotationTypes({ ConverterPrism.PRISM_TYPE, EbeanComponentPrism.PRISM_TYPE, @@ -39,6 +46,26 @@ public class Processor extends AbstractProcessor implements Constants { public synchronized void init(ProcessingEnvironment processingEnv) { super.init(processingEnv); ProcessingContext.init(processingEnv); + try { + + // write a note in target so that other apts can know spi is running + var file = APContext.getBuildResource("avaje-processors.txt"); + var addition = new StringBuilder(); + //if file exists, dedup and append current processor + if (file.toFile().exists()) { + var result = + Stream.concat(Files.lines(file), Stream.of("ebean-querybean-generator")) + .distinct() + .collect(joining("\n")); + addition.append(result); + } else { + addition.append("ebean-querybean-generator"); + } + Files.writeString(file, addition.toString(), StandardOpenOption.CREATE, StandardOpenOption.WRITE); + PomPluginWriter.addPlugin2Pom(); + } catch (IOException e) { + // not an issue worth failing over + } } @Override From eaa19e823ea5efce5b6edda530ffb6c9b411f9d5 Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Thu, 19 Dec 2024 12:08:03 -0500 Subject: [PATCH 05/10] rename processor --- .../generator/{Processor.java => QueryBeanProcessor.java} | 2 +- querybean-generator/src/main/java/module-info.java | 2 +- .../resources/META-INF/gradle/incremental.annotation.processors | 2 +- .../io/ebean/querybean/generator/QueryBeanProcessorTest.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename querybean-generator/src/main/java/io/ebean/querybean/generator/{Processor.java => QueryBeanProcessor.java} (98%) diff --git a/querybean-generator/src/main/java/io/ebean/querybean/generator/Processor.java b/querybean-generator/src/main/java/io/ebean/querybean/generator/QueryBeanProcessor.java similarity index 98% rename from querybean-generator/src/main/java/io/ebean/querybean/generator/Processor.java rename to querybean-generator/src/main/java/io/ebean/querybean/generator/QueryBeanProcessor.java index 9476c31351..8815cd0e46 100644 --- a/querybean-generator/src/main/java/io/ebean/querybean/generator/Processor.java +++ b/querybean-generator/src/main/java/io/ebean/querybean/generator/QueryBeanProcessor.java @@ -38,7 +38,7 @@ EmbeddablePrism.PRISM_TYPE, ModuleInfoPrism.PRISM_TYPE }) -public class Processor extends AbstractProcessor implements Constants { +public class QueryBeanProcessor extends AbstractProcessor implements Constants { private SimpleModuleInfoWriter moduleWriter; diff --git a/querybean-generator/src/main/java/module-info.java b/querybean-generator/src/main/java/module-info.java index 3bce8926e4..07c27fd083 100644 --- a/querybean-generator/src/main/java/module-info.java +++ b/querybean-generator/src/main/java/module-info.java @@ -8,6 +8,6 @@ requires static io.ebean.annotation; requires static jakarta.persistence.api; - provides javax.annotation.processing.Processor with io.ebean.querybean.generator.Processor; + provides javax.annotation.processing.Processor with io.ebean.querybean.generator.QueryBeanProcessor; } diff --git a/querybean-generator/src/main/resources/META-INF/gradle/incremental.annotation.processors b/querybean-generator/src/main/resources/META-INF/gradle/incremental.annotation.processors index 2403f535ee..2e4cb49195 100644 --- a/querybean-generator/src/main/resources/META-INF/gradle/incremental.annotation.processors +++ b/querybean-generator/src/main/resources/META-INF/gradle/incremental.annotation.processors @@ -1 +1 @@ -io.ebean.querybean.generator.Processor,aggregating +io.ebean.querybean.generator.QueryBeanProcessor,aggregating diff --git a/querybean-generator/src/test/java/io/ebean/querybean/generator/QueryBeanProcessorTest.java b/querybean-generator/src/test/java/io/ebean/querybean/generator/QueryBeanProcessorTest.java index 3c2ccbbf65..215181ee50 100644 --- a/querybean-generator/src/test/java/io/ebean/querybean/generator/QueryBeanProcessorTest.java +++ b/querybean-generator/src/test/java/io/ebean/querybean/generator/QueryBeanProcessorTest.java @@ -63,7 +63,7 @@ void testGeneration() throws Exception { List.of("--release=" + Integer.getInteger("java.specification.version")), null, files); - task.setProcessors(List.of(new Processor())); + task.setProcessors(List.of(new QueryBeanProcessor())); assertThat(task.call()).isTrue(); } From ded8121b349aa4613b8e0ab40d944753c32d2e32 Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Thu, 19 Dec 2024 14:56:22 -0500 Subject: [PATCH 06/10] Revert "rename processor" This reverts commit eaa19e823ea5efce5b6edda530ffb6c9b411f9d5. --- .../generator/{QueryBeanProcessor.java => Processor.java} | 2 +- querybean-generator/src/main/java/module-info.java | 2 +- .../resources/META-INF/gradle/incremental.annotation.processors | 2 +- .../io/ebean/querybean/generator/QueryBeanProcessorTest.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename querybean-generator/src/main/java/io/ebean/querybean/generator/{QueryBeanProcessor.java => Processor.java} (98%) diff --git a/querybean-generator/src/main/java/io/ebean/querybean/generator/QueryBeanProcessor.java b/querybean-generator/src/main/java/io/ebean/querybean/generator/Processor.java similarity index 98% rename from querybean-generator/src/main/java/io/ebean/querybean/generator/QueryBeanProcessor.java rename to querybean-generator/src/main/java/io/ebean/querybean/generator/Processor.java index 8815cd0e46..9476c31351 100644 --- a/querybean-generator/src/main/java/io/ebean/querybean/generator/QueryBeanProcessor.java +++ b/querybean-generator/src/main/java/io/ebean/querybean/generator/Processor.java @@ -38,7 +38,7 @@ EmbeddablePrism.PRISM_TYPE, ModuleInfoPrism.PRISM_TYPE }) -public class QueryBeanProcessor extends AbstractProcessor implements Constants { +public class Processor extends AbstractProcessor implements Constants { private SimpleModuleInfoWriter moduleWriter; diff --git a/querybean-generator/src/main/java/module-info.java b/querybean-generator/src/main/java/module-info.java index 07c27fd083..3bce8926e4 100644 --- a/querybean-generator/src/main/java/module-info.java +++ b/querybean-generator/src/main/java/module-info.java @@ -8,6 +8,6 @@ requires static io.ebean.annotation; requires static jakarta.persistence.api; - provides javax.annotation.processing.Processor with io.ebean.querybean.generator.QueryBeanProcessor; + provides javax.annotation.processing.Processor with io.ebean.querybean.generator.Processor; } diff --git a/querybean-generator/src/main/resources/META-INF/gradle/incremental.annotation.processors b/querybean-generator/src/main/resources/META-INF/gradle/incremental.annotation.processors index 2e4cb49195..2403f535ee 100644 --- a/querybean-generator/src/main/resources/META-INF/gradle/incremental.annotation.processors +++ b/querybean-generator/src/main/resources/META-INF/gradle/incremental.annotation.processors @@ -1 +1 @@ -io.ebean.querybean.generator.QueryBeanProcessor,aggregating +io.ebean.querybean.generator.Processor,aggregating diff --git a/querybean-generator/src/test/java/io/ebean/querybean/generator/QueryBeanProcessorTest.java b/querybean-generator/src/test/java/io/ebean/querybean/generator/QueryBeanProcessorTest.java index 215181ee50..3c2ccbbf65 100644 --- a/querybean-generator/src/test/java/io/ebean/querybean/generator/QueryBeanProcessorTest.java +++ b/querybean-generator/src/test/java/io/ebean/querybean/generator/QueryBeanProcessorTest.java @@ -63,7 +63,7 @@ void testGeneration() throws Exception { List.of("--release=" + Integer.getInteger("java.specification.version")), null, files); - task.setProcessors(List.of(new QueryBeanProcessor())); + task.setProcessors(List.of(new Processor())); assertThat(task.call()).isTrue(); } From 401f193127937c43bcd129bfa77a5308f602e922 Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Thu, 19 Dec 2024 14:56:29 -0500 Subject: [PATCH 07/10] Revert "auto add maven plugin" This reverts commit e39a548f022a475dff0821a59c723db453559e8d. --- pom.xml | 13 ---- querybean-generator/pom.xml | 2 +- .../querybean/generator/PomPluginWriter.java | 59 ------------------- .../ebean/querybean/generator/Processor.java | 27 --------- 4 files changed, 1 insertion(+), 100 deletions(-) delete mode 100644 querybean-generator/src/main/java/io/ebean/querybean/generator/PomPluginWriter.java diff --git a/pom.xml b/pom.xml index 201b3278fd..0ea3b58003 100644 --- a/pom.xml +++ b/pom.xml @@ -124,18 +124,5 @@ - - - - org.apache.maven.plugins - maven-compiler-plugin - - - -AbuildPlugin=false - - - - - diff --git a/querybean-generator/pom.xml b/querybean-generator/pom.xml index 25dfb4f2f6..a97aa8ecd2 100644 --- a/querybean-generator/pom.xml +++ b/querybean-generator/pom.xml @@ -12,7 +12,7 @@ querybean-generator - 1.37 + 1.36 diff --git a/querybean-generator/src/main/java/io/ebean/querybean/generator/PomPluginWriter.java b/querybean-generator/src/main/java/io/ebean/querybean/generator/PomPluginWriter.java deleted file mode 100644 index 275e1ad8e0..0000000000 --- a/querybean-generator/src/main/java/io/ebean/querybean/generator/PomPluginWriter.java +++ /dev/null @@ -1,59 +0,0 @@ -package io.ebean.querybean.generator; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.StandardOpenOption; - -final class PomPluginWriter { - - private static final String PLUGIN = - " \n" - + " \n" - + " io.ebean\n" - + " ebean-maven-plugin\n" - + " %s\n" - + " \n" - + " \n" - + " " - + " \n" - + " enhance\n" - + " testEnhance\n" - + " \n" - + " \n" - + " \n" - + " \n" - + " "; - - static void addPlugin2Pom() throws IOException { - - if (disabled()) { - return; - } - - var pomPath = APContext.getBuildResource("").getParent().resolve("pom.xml"); - if (!pomPath.toFile().exists()) { - return; - } - - var pomContent = Files.readString(pomPath); - // if not already present in pom.xml - if (pomContent.contains("ebean-maven-plugin")) { - return; - } - APContext.logNote("Adding ebean-maven-plugin to pom"); - var pluginsIndex = pomContent.indexOf(""); - var builder = new StringBuilder(pomContent); - if (pluginsIndex != -1) { - builder.insert( - pluginsIndex, - String.format(PLUGIN, PomPluginWriter.class.getPackage().getImplementationVersion())); - - Files.writeString( - pomPath, builder.toString(), StandardOpenOption.CREATE, StandardOpenOption.WRITE); - } - } - - private static boolean disabled() { - return !APContext.getOption("buildPlugin").map(Boolean::valueOf).orElse(true); - } -} diff --git a/querybean-generator/src/main/java/io/ebean/querybean/generator/Processor.java b/querybean-generator/src/main/java/io/ebean/querybean/generator/Processor.java index 9476c31351..eaa5af1fbe 100644 --- a/querybean-generator/src/main/java/io/ebean/querybean/generator/Processor.java +++ b/querybean-generator/src/main/java/io/ebean/querybean/generator/Processor.java @@ -3,21 +3,15 @@ import static io.ebean.querybean.generator.APContext.logError; import static io.ebean.querybean.generator.APContext.logNote; import static io.ebean.querybean.generator.APContext.typeElement; -import static java.util.stream.Collectors.joining; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.StandardOpenOption; import java.util.Arrays; import java.util.Optional; import java.util.Set; -import java.util.stream.Stream; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.ProcessingEnvironment; import javax.annotation.processing.RoundEnvironment; import javax.annotation.processing.SupportedAnnotationTypes; -import javax.annotation.processing.SupportedOptions; import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; @@ -30,7 +24,6 @@ @GenerateUtils @GenerateAPContext @GenerateModuleInfoReader -@SupportedOptions("buildPlugin") @SupportedAnnotationTypes({ ConverterPrism.PRISM_TYPE, EbeanComponentPrism.PRISM_TYPE, @@ -46,26 +39,6 @@ public class Processor extends AbstractProcessor implements Constants { public synchronized void init(ProcessingEnvironment processingEnv) { super.init(processingEnv); ProcessingContext.init(processingEnv); - try { - - // write a note in target so that other apts can know spi is running - var file = APContext.getBuildResource("avaje-processors.txt"); - var addition = new StringBuilder(); - //if file exists, dedup and append current processor - if (file.toFile().exists()) { - var result = - Stream.concat(Files.lines(file), Stream.of("ebean-querybean-generator")) - .distinct() - .collect(joining("\n")); - addition.append(result); - } else { - addition.append("ebean-querybean-generator"); - } - Files.writeString(file, addition.toString(), StandardOpenOption.CREATE, StandardOpenOption.WRITE); - PomPluginWriter.addPlugin2Pom(); - } catch (IOException e) { - // not an issue worth failing over - } } @Override From 9af7603f2a2422cdc52a639992c60376aecfbb01 Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Thu, 19 Dec 2024 16:06:54 -0500 Subject: [PATCH 08/10] Update pom.xml --- querybean-generator/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/querybean-generator/pom.xml b/querybean-generator/pom.xml index a97aa8ecd2..01aff014b0 100644 --- a/querybean-generator/pom.xml +++ b/querybean-generator/pom.xml @@ -50,7 +50,7 @@ io.avaje avaje-spi-service - 2.8 + 2.9 From 2bd5037c2020d46fdf1e635493b047a9037893c2 Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Wed, 15 Jan 2025 22:54:51 -0500 Subject: [PATCH 09/10] Update pom.xml --- querybean-generator/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/querybean-generator/pom.xml b/querybean-generator/pom.xml index 6c5e414ce0..b946930ed9 100644 --- a/querybean-generator/pom.xml +++ b/querybean-generator/pom.xml @@ -20,7 +20,7 @@ io.ebean ebean-api - ${project.version} + 14.8.1 true provided From c476a7d3bc712d278b540d35882a6a3cae922c3b Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Wed, 15 Jan 2025 22:56:54 -0500 Subject: [PATCH 10/10] Update Processor.java --- .../src/main/java/io/ebean/querybean/generator/Processor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/querybean-generator/src/main/java/io/ebean/querybean/generator/Processor.java b/querybean-generator/src/main/java/io/ebean/querybean/generator/Processor.java index 72eed072a4..d90f973d3d 100644 --- a/querybean-generator/src/main/java/io/ebean/querybean/generator/Processor.java +++ b/querybean-generator/src/main/java/io/ebean/querybean/generator/Processor.java @@ -100,7 +100,7 @@ private void initModuleInfoBean() { moduleWriter = new SimpleModuleInfoWriter(); } } catch (FilerException e) { - logWarn(null, "FilerException trying to write EntityClassRegister: " + e); + logWarn("FilerException trying to write EntityClassRegister: " + e); } catch (Throwable e) { logError("Failed to write EntityClassRegister error:" + e + " stack:" + Arrays.toString(e.getStackTrace())); }