diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/processor/Context.java b/tooling/metamodel-generator/src/main/java/org/hibernate/processor/Context.java index 04efd972df6c..04acf1a41473 100644 --- a/tooling/metamodel-generator/src/main/java/org/hibernate/processor/Context.java +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/processor/Context.java @@ -107,6 +107,8 @@ public final class Context { private String[] includes = {"*"}; private String[] excludes = {}; + private boolean indexing = true; + private final Map entityNameMappings = new HashMap<>(); private final Map> enumTypesByValue = new HashMap<>(); @@ -551,4 +553,12 @@ private void addEnumValue(String qualifiedTypeName, String value) { } return null; } + + public void setIndexing(boolean index) { + this.indexing = index; + } + + public boolean isIndexing() { + return indexing; + } } diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/processor/HibernateProcessor.java b/tooling/metamodel-generator/src/main/java/org/hibernate/processor/HibernateProcessor.java index fcd6bd2f1200..1dd4c9cf759c 100644 --- a/tooling/metamodel-generator/src/main/java/org/hibernate/processor/HibernateProcessor.java +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/processor/HibernateProcessor.java @@ -54,6 +54,7 @@ import static org.hibernate.processor.HibernateProcessor.EXCLUDE; import static org.hibernate.processor.HibernateProcessor.FULLY_ANNOTATION_CONFIGURED_OPTION; import static org.hibernate.processor.HibernateProcessor.INCLUDE; +import static org.hibernate.processor.HibernateProcessor.INDEX; import static org.hibernate.processor.HibernateProcessor.LAZY_XML_PARSING; import static org.hibernate.processor.HibernateProcessor.ORM_XML_OPTION; import static org.hibernate.processor.HibernateProcessor.PERSISTENCE_XML_OPTION; @@ -120,7 +121,8 @@ ADD_GENERATED_ANNOTATION, ADD_SUPPRESS_WARNINGS_ANNOTATION, SUPPRESS_JAKARTA_DATA_METAMODEL, - INCLUDE, EXCLUDE + INCLUDE, EXCLUDE, + INDEX }) public class HibernateProcessor extends AbstractProcessor { @@ -190,6 +192,13 @@ public class HibernateProcessor extends AbstractProcessor { */ public static final String EXCLUDE = "exclude"; + /** + * Option to suppress creation of a filesystem-based index of entity + * types and enums for use by the query validator. By default, and + * index is created. + */ + public static final String INDEX = "index"; + private static final boolean ALLOW_OTHER_PROCESSORS_TO_CLAIM_ANNOTATIONS = false; public static final String ENTITY_INDEX = "entity.index"; @@ -282,6 +291,8 @@ && packagePresent(quarkusOrmPanachePackage) ) { context.setInclude( options.getOrDefault( INCLUDE, "*" ) ); context.setExclude( options.getOrDefault( EXCLUDE, "" ) ); + context.setIndexing( parseBoolean( options.getOrDefault( INDEX, "true" ) ) ); + return parseBoolean( options.get( FULLY_ANNOTATION_CONFIGURED_OPTION ) ); } @@ -773,43 +784,45 @@ else if ( hasAnnotation( typeElement, EMBEDDABLE ) ) { } private void writeIndex() { - final ProcessingEnvironment processingEnvironment = context.getProcessingEnvironment(); - final Elements elementUtils = processingEnvironment.getElementUtils(); - context.getEntityNameMappings().forEach((entityName, className) -> { - try (Writer writer = processingEnvironment.getFiler() - .createResource( - StandardLocation.SOURCE_OUTPUT, - ENTITY_INDEX, - entityName, - elementUtils.getTypeElement( className ) - ) - .openWriter()) { - writer.append(className); - } - catch (IOException e) { - processingEnvironment.getMessager() - .printMessage(Diagnostic.Kind.WARNING, - "could not write entity index " + e.getMessage()); - } - }); - context.getEnumTypesByValue().forEach((valueName, enumTypeNames) -> { - try (Writer writer = processingEnvironment.getFiler() - .createResource( - StandardLocation.SOURCE_OUTPUT, - ENTITY_INDEX, - '.' + valueName, - elementUtils.getTypeElement( enumTypeNames.iterator().next() ) - ) - .openWriter()) { - for (String enumTypeName : enumTypeNames) { - writer.append(enumTypeName).append(" "); + if ( context.isIndexing() ) { + final ProcessingEnvironment processingEnvironment = context.getProcessingEnvironment(); + final Elements elementUtils = processingEnvironment.getElementUtils(); + context.getEntityNameMappings().forEach( (entityName, className) -> { + try (Writer writer = processingEnvironment.getFiler() + .createResource( + StandardLocation.SOURCE_OUTPUT, + ENTITY_INDEX, + entityName, + elementUtils.getTypeElement( className ) + ) + .openWriter()) { + writer.append( className ); } - } - catch (IOException e) { - processingEnvironment.getMessager() - .printMessage(Diagnostic.Kind.WARNING, - "could not write entity index " + e.getMessage()); - } - }); + catch (IOException e) { + processingEnvironment.getMessager() + .printMessage( Diagnostic.Kind.WARNING, + "could not write entity index " + e.getMessage() ); + } + } ); + context.getEnumTypesByValue().forEach( (valueName, enumTypeNames) -> { + try (Writer writer = processingEnvironment.getFiler() + .createResource( + StandardLocation.SOURCE_OUTPUT, + ENTITY_INDEX, + '.' + valueName, + elementUtils.getTypeElement( enumTypeNames.iterator().next() ) + ) + .openWriter()) { + for ( String enumTypeName : enumTypeNames ) { + writer.append( enumTypeName ).append( " " ); + } + } + catch (IOException e) { + processingEnvironment.getMessager() + .printMessage( Diagnostic.Kind.WARNING, + "could not write entity index " + e.getMessage() ); + } + } ); + } } } diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/processor/annotation/AnnotationMeta.java b/tooling/metamodel-generator/src/main/java/org/hibernate/processor/annotation/AnnotationMeta.java index 0f77b78509d7..06db3329d229 100644 --- a/tooling/metamodel-generator/src/main/java/org/hibernate/processor/annotation/AnnotationMeta.java +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/processor/annotation/AnnotationMeta.java @@ -104,7 +104,8 @@ private void handleNamedQuery(AnnotationMirror mirror, boolean checkHql) { new WarningErrorHandler( context, getElement(), mirror, value, hql, reportErrors, checkHql ), ProcessorSessionFactory.create( context.getProcessingEnvironment(), - context.getEntityNameMappings(), context.getEnumTypesByValue() ) + context.getEntityNameMappings(), context.getEnumTypesByValue(), + context.isIndexing() ) ); if ( !isJakartaDataStyle() && statement instanceof SqmSelectStatement selectStatement ) { diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/processor/annotation/AnnotationMetaEntity.java b/tooling/metamodel-generator/src/main/java/org/hibernate/processor/annotation/AnnotationMetaEntity.java index 388268119cfe..a3f975e836b7 100644 --- a/tooling/metamodel-generator/src/main/java/org/hibernate/processor/annotation/AnnotationMetaEntity.java +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/processor/annotation/AnnotationMetaEntity.java @@ -2451,7 +2451,7 @@ private void validateHql( true, new ErrorHandler( context, isLocal(method) ? method : element, mirror, value, hql ), ProcessorSessionFactory.create( context.getProcessingEnvironment(), - context.getEntityNameMappings(), context.getEnumTypesByValue() ) + context.getEntityNameMappings(), context.getEnumTypesByValue(), context.isIndexing() ) ); if ( statement != null ) { if ( statement instanceof SqmSelectStatement ) { diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/processor/validation/ProcessorSessionFactory.java b/tooling/metamodel-generator/src/main/java/org/hibernate/processor/validation/ProcessorSessionFactory.java index e0d224c50a31..381b1ba9248b 100644 --- a/tooling/metamodel-generator/src/main/java/org/hibernate/processor/validation/ProcessorSessionFactory.java +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/processor/validation/ProcessorSessionFactory.java @@ -72,8 +72,9 @@ public abstract class ProcessorSessionFactory extends MockSessionFactory { public static MockSessionFactory create( ProcessingEnvironment environment, Map entityNameMappings, - Map> enumTypesByValue) { - return instance.make(environment, entityNameMappings, enumTypesByValue); + Map> enumTypesByValue, + boolean indexing) { + return instance.make(environment, indexing, entityNameMappings, enumTypesByValue); } static final Mocker instance = Mocker.variadic(ProcessorSessionFactory.class); @@ -88,16 +89,19 @@ public static MockSessionFactory create( private final Elements elementUtil; private final Types typeUtil; private final Filer filer; + private final boolean indexing; private final Map entityNameMappings; private final Map> enumTypesByValue; public ProcessorSessionFactory( ProcessingEnvironment processingEnvironment, + boolean indexing, Map entityNameMappings, Map> enumTypesByValue) { elementUtil = processingEnvironment.getElementUtils(); typeUtil = processingEnvironment.getTypeUtils(); filer = processingEnvironment.getFiler(); + this.indexing = indexing; this.entityNameMappings = entityNameMappings; this.enumTypesByValue = enumTypesByValue; } @@ -130,7 +134,6 @@ else if (isElementCollectionProperty(property)) { } } - @Override Type propertyType(String typeName, String propertyPath) { final TypeElement type = findClassByQualifiedName(typeName); @@ -220,15 +223,27 @@ Set getEnumTypesForValue(String value) { if ( result != null ) { return result; } - try (Reader reader = filer.getResource(StandardLocation.SOURCE_OUTPUT, ENTITY_INDEX, value) - .openReader(true); BufferedReader buffered = new BufferedReader(reader) ) { - return Set.of(split(" ", buffered.readLine())); + if ( indexing ) { + final Set indexed = getIndexedEnumTypesByValue(value); + if ( indexed != null ) { + enumTypesByValue.put(value, indexed); + return indexed; + } + } + //TODO: else do a full scan like in findEntityByUnqualifiedName() + return null; + } + + private @Nullable Set getIndexedEnumTypesByValue(String value) { + try (Reader reader = filer.getResource( StandardLocation.SOURCE_OUTPUT, ENTITY_INDEX, value ) + .openReader( true ); BufferedReader buffered = new BufferedReader( reader )) { + return Set.of( split( " ", buffered.readLine() ) ); } catch (IOException ignore) { } - try (Reader reader = filer.getResource(StandardLocation.CLASS_PATH, ENTITY_INDEX, '.' + value) - .openReader(true); BufferedReader buffered = new BufferedReader(reader) ) { - return Set.of(split(" ", buffered.readLine())); + try (Reader reader = filer.getResource( StandardLocation.CLASS_PATH, ENTITY_INDEX, '.' + value ) + .openReader( true ); BufferedReader buffered = new BufferedReader( reader )) { + return Set.of( split( " ", buffered.readLine() ) ); } catch (IOException ignore) { } @@ -503,27 +518,13 @@ private TypeElement findEntityByUnqualifiedName(String entityName) { if ( cached != null ) { return cached; } - final String qualifiedName = entityNameMappings.get(entityName); - if ( qualifiedName != null ) { - final TypeElement result = elementUtil.getTypeElement(qualifiedName); - entityCache.put(entityName, result); - return result; - } - try (Reader reader = filer.getResource( StandardLocation.SOURCE_OUTPUT, ENTITY_INDEX, entityName) - .openReader(true); BufferedReader buffered = new BufferedReader(reader) ) { - final TypeElement result = elementUtil.getTypeElement(buffered.readLine()); - entityCache.put(entityName, result); - return result; - } - catch (IOException ignore) { - } - try (Reader reader = filer.getResource(StandardLocation.CLASS_PATH, ENTITY_INDEX, entityName) - .openReader(true); BufferedReader buffered = new BufferedReader(reader) ) { - final TypeElement result = elementUtil.getTypeElement(buffered.readLine()); - entityCache.put(entityName, result); - return result; - } - catch (IOException ignore) { + + if ( indexing ) { + final TypeElement indexedEntity = findIndexedEntityByQualifiedName( entityName ); + if ( indexedEntity != null ) { + entityCache.put(entityName, indexedEntity); + return indexedEntity; + } } TypeElement symbol = @@ -543,6 +544,26 @@ private TypeElement findEntityByUnqualifiedName(String entityName) { return null; } + private @Nullable TypeElement findIndexedEntityByQualifiedName(String entityName) { + final String qualifiedName = entityNameMappings.get(entityName); + if ( qualifiedName != null ) { + return elementUtil.getTypeElement(qualifiedName); + } + try (Reader reader = filer.getResource( StandardLocation.SOURCE_OUTPUT, ENTITY_INDEX, entityName) + .openReader(true); BufferedReader buffered = new BufferedReader(reader) ) { + return elementUtil.getTypeElement(buffered.readLine()); + } + catch (IOException ignore) { + } + try (Reader reader = filer.getResource(StandardLocation.CLASS_PATH, ENTITY_INDEX, entityName) + .openReader(true); BufferedReader buffered = new BufferedReader(reader) ) { + return elementUtil.getTypeElement(buffered.readLine()); + } + catch (IOException ignore) { + } + return null; + } + public static TypeElement findEntityByUnqualifiedName(String entityName, ModuleElement module) { for (Element element: module.getEnclosedElements()) { if (element.getKind() == ElementKind.PACKAGE) {