HHH-18162 index creation in HibernateProcessor
This stores an index of entities and enum values in the entity.index directory. This approach has some downsides but works around some limitations of the processor API. Signed-off-by: Gavin King <gavin@hibernate.org>
This commit is contained in:
parent
ed2fdce0a6
commit
ebd8619f73
|
@ -13,6 +13,7 @@ import jakarta.persistence.metamodel.EntityType;
|
||||||
import jakarta.persistence.metamodel.ManagedType;
|
import jakarta.persistence.metamodel.ManagedType;
|
||||||
|
|
||||||
import jakarta.persistence.metamodel.Metamodel;
|
import jakarta.persistence.metamodel.Metamodel;
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
import org.hibernate.Incubating;
|
import org.hibernate.Incubating;
|
||||||
import org.hibernate.graph.spi.RootGraphImplementor;
|
import org.hibernate.graph.spi.RootGraphImplementor;
|
||||||
import org.hibernate.jpa.spi.JpaCompliance;
|
import org.hibernate.jpa.spi.JpaCompliance;
|
||||||
|
@ -89,7 +90,8 @@ public interface JpaMetamodel extends Metamodel {
|
||||||
|
|
||||||
String qualifyImportableName(String queryName);
|
String qualifyImportableName(String queryName);
|
||||||
|
|
||||||
Set<String> getAllowedEnumLiteralTexts(String enumValue);
|
@Nullable
|
||||||
|
Set<String> getEnumTypesForValue(String enumValue);
|
||||||
|
|
||||||
EnumJavaType<?> getEnumType(String prefix);
|
EnumJavaType<?> getEnumType(String prefix);
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ import java.util.TreeMap;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
import org.hibernate.boot.model.NamedEntityGraphDefinition;
|
import org.hibernate.boot.model.NamedEntityGraphDefinition;
|
||||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||||
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
|
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
|
||||||
|
@ -281,8 +282,8 @@ public class JpaMetamodelImpl implements JpaMetamodelImplementor, Serializable {
|
||||||
.collect( Collectors.toSet() );
|
.collect( Collectors.toSet() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override @Nullable
|
||||||
public Set<String> getAllowedEnumLiteralTexts(String enumValue) {
|
public Set<String> getEnumTypesForValue(String enumValue) {
|
||||||
return allowedEnumLiteralTexts.get(enumValue);
|
return allowedEnumLiteralTexts.get(enumValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -530,8 +530,8 @@ public class MappingMetamodelImpl extends QueryParameterBindingTypeResolverImpl
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<String> getAllowedEnumLiteralTexts(String enumValue) {
|
public Set<String> getEnumTypesForValue(String enumValue) {
|
||||||
return jpaMetamodel.getAllowedEnumLiteralTexts(enumValue);
|
return jpaMetamodel.getEnumTypesForValue(enumValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -2603,7 +2603,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
||||||
ctx = ctx.getChild( 0 );
|
ctx = ctx.getChild( 0 );
|
||||||
|
|
||||||
if ( ctx instanceof HqlParser.SimplePathContext ) {
|
if ( ctx instanceof HqlParser.SimplePathContext ) {
|
||||||
return creationContext.getJpaMetamodel().getAllowedEnumLiteralTexts( ctx.getText() );
|
return creationContext.getJpaMetamodel().getEnumTypesForValue( ctx.getText() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,6 +106,9 @@ public final class Context {
|
||||||
private String[] includes = {"*"};
|
private String[] includes = {"*"};
|
||||||
private String[] excludes = {};
|
private String[] excludes = {};
|
||||||
|
|
||||||
|
private final Map<String, String> entityNameMappings = new HashMap<>();
|
||||||
|
private final Map<String, Set<String>> enumTypesByValue = new HashMap<>();
|
||||||
|
|
||||||
public Context(ProcessingEnvironment processingEnvironment) {
|
public Context(ProcessingEnvironment processingEnvironment) {
|
||||||
this.processingEnvironment = processingEnvironment;
|
this.processingEnvironment = processingEnvironment;
|
||||||
|
|
||||||
|
@ -483,4 +486,24 @@ public final class Context {
|
||||||
|| elements.stream().noneMatch(member -> member instanceof ExecutableElement
|
|| elements.stream().noneMatch(member -> member instanceof ExecutableElement
|
||||||
&& getElementUtils().overrides((ExecutableElement) member, (ExecutableElement) inherited, type));
|
&& getElementUtils().overrides((ExecutableElement) member, (ExecutableElement) inherited, type));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getEntityNameMappings() {
|
||||||
|
return entityNameMappings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addEntityNameMapping(String entityName, String qualifiedName) {
|
||||||
|
entityNameMappings.put( entityName, qualifiedName );
|
||||||
|
}
|
||||||
|
|
||||||
|
public @Nullable String qualifiedNameForEntityName(String entityName) {
|
||||||
|
return entityNameMappings.get(entityName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String,Set<String>> getEnumTypesByValue() {
|
||||||
|
return enumTypesByValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addEnumValue(String type, String value) {
|
||||||
|
enumTypesByValue.computeIfAbsent( value, s -> new HashSet<>() ).add( type );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,13 +22,19 @@ import javax.lang.model.SourceVersion;
|
||||||
import javax.lang.model.element.AnnotationMirror;
|
import javax.lang.model.element.AnnotationMirror;
|
||||||
import javax.lang.model.element.AnnotationValue;
|
import javax.lang.model.element.AnnotationValue;
|
||||||
import javax.lang.model.element.Element;
|
import javax.lang.model.element.Element;
|
||||||
|
import javax.lang.model.element.ElementKind;
|
||||||
|
import javax.lang.model.element.ExecutableElement;
|
||||||
import javax.lang.model.element.PackageElement;
|
import javax.lang.model.element.PackageElement;
|
||||||
import javax.lang.model.element.TypeElement;
|
import javax.lang.model.element.TypeElement;
|
||||||
|
import javax.lang.model.type.DeclaredType;
|
||||||
import javax.lang.model.type.TypeKind;
|
import javax.lang.model.type.TypeKind;
|
||||||
import javax.lang.model.type.TypeMirror;
|
import javax.lang.model.type.TypeMirror;
|
||||||
import javax.tools.Diagnostic;
|
import javax.tools.Diagnostic;
|
||||||
|
import javax.tools.StandardLocation;
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
|
import java.io.Writer;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -42,12 +48,36 @@ import static org.hibernate.processor.HibernateProcessor.ADD_GENERATED_ANNOTATIO
|
||||||
import static org.hibernate.processor.HibernateProcessor.ADD_GENERATION_DATE;
|
import static org.hibernate.processor.HibernateProcessor.ADD_GENERATION_DATE;
|
||||||
import static org.hibernate.processor.HibernateProcessor.ADD_SUPPRESS_WARNINGS_ANNOTATION;
|
import static org.hibernate.processor.HibernateProcessor.ADD_SUPPRESS_WARNINGS_ANNOTATION;
|
||||||
import static org.hibernate.processor.HibernateProcessor.DEBUG_OPTION;
|
import static org.hibernate.processor.HibernateProcessor.DEBUG_OPTION;
|
||||||
|
import static org.hibernate.processor.HibernateProcessor.EXCLUDE;
|
||||||
import static org.hibernate.processor.HibernateProcessor.FULLY_ANNOTATION_CONFIGURED_OPTION;
|
import static org.hibernate.processor.HibernateProcessor.FULLY_ANNOTATION_CONFIGURED_OPTION;
|
||||||
|
import static org.hibernate.processor.HibernateProcessor.INCLUDE;
|
||||||
import static org.hibernate.processor.HibernateProcessor.LAZY_XML_PARSING;
|
import static org.hibernate.processor.HibernateProcessor.LAZY_XML_PARSING;
|
||||||
import static org.hibernate.processor.HibernateProcessor.ORM_XML_OPTION;
|
import static org.hibernate.processor.HibernateProcessor.ORM_XML_OPTION;
|
||||||
import static org.hibernate.processor.HibernateProcessor.PERSISTENCE_XML_OPTION;
|
import static org.hibernate.processor.HibernateProcessor.PERSISTENCE_XML_OPTION;
|
||||||
import static org.hibernate.processor.HibernateProcessor.SUPPRESS_JAKARTA_DATA_METAMODEL;
|
import static org.hibernate.processor.HibernateProcessor.SUPPRESS_JAKARTA_DATA_METAMODEL;
|
||||||
import static org.hibernate.processor.util.Constants.*;
|
import static org.hibernate.processor.util.Constants.EMBEDDABLE;
|
||||||
|
import static org.hibernate.processor.util.Constants.ENTITY;
|
||||||
|
import static org.hibernate.processor.util.Constants.FIND;
|
||||||
|
import static org.hibernate.processor.util.Constants.HIB_FETCH_PROFILE;
|
||||||
|
import static org.hibernate.processor.util.Constants.HIB_FETCH_PROFILES;
|
||||||
|
import static org.hibernate.processor.util.Constants.HIB_FILTER_DEF;
|
||||||
|
import static org.hibernate.processor.util.Constants.HIB_FILTER_DEFS;
|
||||||
|
import static org.hibernate.processor.util.Constants.HIB_NAMED_NATIVE_QUERIES;
|
||||||
|
import static org.hibernate.processor.util.Constants.HIB_NAMED_NATIVE_QUERY;
|
||||||
|
import static org.hibernate.processor.util.Constants.HIB_NAMED_QUERIES;
|
||||||
|
import static org.hibernate.processor.util.Constants.HIB_NAMED_QUERY;
|
||||||
|
import static org.hibernate.processor.util.Constants.HQL;
|
||||||
|
import static org.hibernate.processor.util.Constants.JD_REPOSITORY;
|
||||||
|
import static org.hibernate.processor.util.Constants.MAPPED_SUPERCLASS;
|
||||||
|
import static org.hibernate.processor.util.Constants.NAMED_ENTITY_GRAPH;
|
||||||
|
import static org.hibernate.processor.util.Constants.NAMED_ENTITY_GRAPHS;
|
||||||
|
import static org.hibernate.processor.util.Constants.NAMED_NATIVE_QUERIES;
|
||||||
|
import static org.hibernate.processor.util.Constants.NAMED_NATIVE_QUERY;
|
||||||
|
import static org.hibernate.processor.util.Constants.NAMED_QUERIES;
|
||||||
|
import static org.hibernate.processor.util.Constants.NAMED_QUERY;
|
||||||
|
import static org.hibernate.processor.util.Constants.SQL;
|
||||||
|
import static org.hibernate.processor.util.Constants.SQL_RESULT_SET_MAPPING;
|
||||||
|
import static org.hibernate.processor.util.Constants.SQL_RESULT_SET_MAPPINGS;
|
||||||
import static org.hibernate.processor.util.TypeUtils.containsAnnotation;
|
import static org.hibernate.processor.util.TypeUtils.containsAnnotation;
|
||||||
import static org.hibernate.processor.util.TypeUtils.getAnnotationMirror;
|
import static org.hibernate.processor.util.TypeUtils.getAnnotationMirror;
|
||||||
import static org.hibernate.processor.util.TypeUtils.getAnnotationValue;
|
import static org.hibernate.processor.util.TypeUtils.getAnnotationValue;
|
||||||
|
@ -85,7 +115,8 @@ import static org.hibernate.processor.util.TypeUtils.isClassOrRecordType;
|
||||||
ADD_GENERATION_DATE,
|
ADD_GENERATION_DATE,
|
||||||
ADD_GENERATED_ANNOTATION,
|
ADD_GENERATED_ANNOTATION,
|
||||||
ADD_SUPPRESS_WARNINGS_ANNOTATION,
|
ADD_SUPPRESS_WARNINGS_ANNOTATION,
|
||||||
SUPPRESS_JAKARTA_DATA_METAMODEL
|
SUPPRESS_JAKARTA_DATA_METAMODEL,
|
||||||
|
INCLUDE, EXCLUDE
|
||||||
})
|
})
|
||||||
public class HibernateProcessor extends AbstractProcessor {
|
public class HibernateProcessor extends AbstractProcessor {
|
||||||
|
|
||||||
|
@ -157,6 +188,8 @@ public class HibernateProcessor extends AbstractProcessor {
|
||||||
|
|
||||||
private static final boolean ALLOW_OTHER_PROCESSORS_TO_CLAIM_ANNOTATIONS = false;
|
private static final boolean ALLOW_OTHER_PROCESSORS_TO_CLAIM_ANNOTATIONS = false;
|
||||||
|
|
||||||
|
public static final String ENTITY_INDEX = "entity.index";
|
||||||
|
|
||||||
private Context context;
|
private Context context;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -168,7 +201,7 @@ public class HibernateProcessor extends AbstractProcessor {
|
||||||
"Hibernate compile-time tooling " + Version.getVersionString()
|
"Hibernate compile-time tooling " + Version.getVersionString()
|
||||||
);
|
);
|
||||||
|
|
||||||
boolean fullyAnnotationConfigured = handleSettings( processingEnvironment );
|
final boolean fullyAnnotationConfigured = handleSettings( processingEnvironment );
|
||||||
if ( !fullyAnnotationConfigured ) {
|
if ( !fullyAnnotationConfigured ) {
|
||||||
new JpaDescriptorParser( context ).parseXml();
|
new JpaDescriptorParser( context ).parseXml();
|
||||||
if ( context.isFullyXmlConfigured() ) {
|
if ( context.isFullyXmlConfigured() ) {
|
||||||
|
@ -275,6 +308,7 @@ public class HibernateProcessor extends AbstractProcessor {
|
||||||
if ( !elementsToRedo.isEmpty() ) {
|
if ( !elementsToRedo.isEmpty() ) {
|
||||||
context.logMessage( Diagnostic.Kind.ERROR, "Failed to generate code for " + elementsToRedo );
|
context.logMessage( Diagnostic.Kind.ERROR, "Failed to generate code for " + elementsToRedo );
|
||||||
}
|
}
|
||||||
|
writeIndex();
|
||||||
}
|
}
|
||||||
else if ( context.isFullyXmlConfigured() ) {
|
else if ( context.isFullyXmlConfigured() ) {
|
||||||
context.logMessage(
|
context.logMessage(
|
||||||
|
@ -518,6 +552,9 @@ public class HibernateProcessor extends AbstractProcessor {
|
||||||
if ( isClassOrRecordType( element ) ) {
|
if ( isClassOrRecordType( element ) ) {
|
||||||
if ( hasAnnotation( element, ENTITY, MAPPED_SUPERCLASS, EMBEDDABLE ) ) {
|
if ( hasAnnotation( element, ENTITY, MAPPED_SUPERCLASS, EMBEDDABLE ) ) {
|
||||||
final TypeElement typeElement = (TypeElement) element;
|
final TypeElement typeElement = (TypeElement) element;
|
||||||
|
indexEntityName( typeElement );
|
||||||
|
indexEnumFields( typeElement );
|
||||||
|
|
||||||
final String qualifiedName = typeElement.getQualifiedName().toString();
|
final String qualifiedName = typeElement.getQualifiedName().toString();
|
||||||
final Metamodel alreadyExistingMetaEntity =
|
final Metamodel alreadyExistingMetaEntity =
|
||||||
tryGettingExistingEntityFromContext( typeElement, qualifiedName );
|
tryGettingExistingEntityFromContext( typeElement, qualifiedName );
|
||||||
|
@ -565,6 +602,54 @@ public class HibernateProcessor extends AbstractProcessor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void indexEntityName(TypeElement typeElement) {
|
||||||
|
final AnnotationMirror mirror = getAnnotationMirror( typeElement, ENTITY );
|
||||||
|
if ( mirror != null ) {
|
||||||
|
context.addEntityNameMapping( entityName( typeElement, mirror ),
|
||||||
|
typeElement.getQualifiedName().toString() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String entityName(TypeElement entityType, AnnotationMirror mirror) {
|
||||||
|
final String className = entityType.getSimpleName().toString();
|
||||||
|
final AnnotationValue name = getAnnotationValue(mirror, "name" );
|
||||||
|
if (name != null) {
|
||||||
|
final String explicitName = name.getValue().toString();
|
||||||
|
if ( !explicitName.isEmpty() ) {
|
||||||
|
return explicitName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return className;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void indexEnumFields(TypeElement typeElement) {
|
||||||
|
for ( Element member : context.getAllMembers(typeElement) ) {
|
||||||
|
switch ( member.getKind() ) {
|
||||||
|
case FIELD:
|
||||||
|
indexEnumValues( member.asType() );
|
||||||
|
break;
|
||||||
|
case METHOD:
|
||||||
|
indexEnumValues( ((ExecutableElement) member).getReturnType() );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void indexEnumValues(TypeMirror type) {
|
||||||
|
if ( type.getKind() == TypeKind.DECLARED ) {
|
||||||
|
final DeclaredType declaredType = (DeclaredType) type;
|
||||||
|
final TypeElement fieldType = (TypeElement) declaredType.asElement();
|
||||||
|
if ( fieldType.getKind() == ElementKind.ENUM ) {
|
||||||
|
for (Element enumMember : fieldType.getEnclosedElements() ) {
|
||||||
|
if ( enumMember.getKind() == ElementKind.ENUM_CONSTANT) {
|
||||||
|
context.addEnumValue( fieldType.getQualifiedName().toString(),
|
||||||
|
enumMember.getSimpleName().toString() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void handleRootElementAuxiliaryAnnotationMirrors(final Element element) {
|
private void handleRootElementAuxiliaryAnnotationMirrors(final Element element) {
|
||||||
if ( element instanceof TypeElement ) {
|
if ( element instanceof TypeElement ) {
|
||||||
final AnnotationMetaEntity metaEntity =
|
final AnnotationMetaEntity metaEntity =
|
||||||
|
@ -615,4 +700,33 @@ public class HibernateProcessor extends AbstractProcessor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void writeIndex() {
|
||||||
|
final ProcessingEnvironment processingEnvironment = context.getProcessingEnvironment();
|
||||||
|
context.getEntityNameMappings().forEach((entityName, className) -> {
|
||||||
|
try (Writer writer = processingEnvironment.getFiler()
|
||||||
|
.createResource(StandardLocation.SOURCE_OUTPUT, ENTITY_INDEX, entityName)
|
||||||
|
.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)
|
||||||
|
.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());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,7 +84,8 @@ public abstract class AnnotationMeta implements Metamodel {
|
||||||
final AnnotationValue nameValue = getAnnotationValue( mirror, "name" );
|
final AnnotationValue nameValue = getAnnotationValue( mirror, "name" );
|
||||||
if ( nameValue != null ) {
|
if ( nameValue != null ) {
|
||||||
final String name = nameValue.getValue().toString();
|
final String name = nameValue.getValue().toString();
|
||||||
final boolean reportErrors = getContext().checkNamedQuery( name );
|
final Context context = getContext();
|
||||||
|
final boolean reportErrors = context.checkNamedQuery( name );
|
||||||
final AnnotationValue value = getAnnotationValue( mirror, "query" );
|
final AnnotationValue value = getAnnotationValue( mirror, "query" );
|
||||||
if ( value != null ) {
|
if ( value != null ) {
|
||||||
final Object query = value.getValue();
|
final Object query = value.getValue();
|
||||||
|
@ -98,9 +99,10 @@ public abstract class AnnotationMeta implements Metamodel {
|
||||||
// If we are in the scope of @CheckHQL, semantic errors in the
|
// If we are in the scope of @CheckHQL, semantic errors in the
|
||||||
// query result in compilation errors. Otherwise, they only
|
// query result in compilation errors. Otherwise, they only
|
||||||
// result in warnings, so we don't break working code.
|
// result in warnings, so we don't break working code.
|
||||||
new WarningErrorHandler( getContext(), getElement(), mirror, value, hql,
|
new WarningErrorHandler( context, getElement(), mirror, value, hql,
|
||||||
reportErrors, checkHql ),
|
reportErrors, checkHql ),
|
||||||
ProcessorSessionFactory.create( getContext().getProcessingEnvironment() )
|
ProcessorSessionFactory.create( context.getProcessingEnvironment(),
|
||||||
|
context.getEntityNameMappings(), context.getEnumTypesByValue() )
|
||||||
);
|
);
|
||||||
if ( statement instanceof SqmSelectStatement
|
if ( statement instanceof SqmSelectStatement
|
||||||
&& isQueryMethodName( name ) ) {
|
&& isQueryMethodName( name ) ) {
|
||||||
|
@ -112,7 +114,7 @@ public abstract class AnnotationMeta implements Metamodel {
|
||||||
isRepository(),
|
isRepository(),
|
||||||
getSessionType(),
|
getSessionType(),
|
||||||
getSessionVariableName(),
|
getSessionVariableName(),
|
||||||
getContext().addNonnullAnnotation()
|
context.addNonnullAnnotation()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2469,7 +2469,8 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
||||||
returnType,
|
returnType,
|
||||||
true,
|
true,
|
||||||
new ErrorHandler( context, isLocal(method) ? method : element, mirror, value, hql ),
|
new ErrorHandler( context, isLocal(method) ? method : element, mirror, value, hql ),
|
||||||
ProcessorSessionFactory.create( context.getProcessingEnvironment() )
|
ProcessorSessionFactory.create( context.getProcessingEnvironment(),
|
||||||
|
context.getEntityNameMappings(), context.getEnumTypesByValue() )
|
||||||
);
|
);
|
||||||
if ( statement != null ) {
|
if ( statement != null ) {
|
||||||
if ( statement instanceof SqmSelectStatement ) {
|
if ( statement instanceof SqmSelectStatement ) {
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
package org.hibernate.processor.annotation;
|
package org.hibernate.processor.annotation;
|
||||||
|
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
import org.hibernate.processor.Context;
|
||||||
import org.hibernate.processor.model.MetaAttribute;
|
import org.hibernate.processor.model.MetaAttribute;
|
||||||
import org.hibernate.processor.model.Metamodel;
|
import org.hibernate.processor.model.Metamodel;
|
||||||
import org.hibernate.processor.util.Constants;
|
import org.hibernate.processor.util.Constants;
|
||||||
|
@ -18,6 +19,7 @@ import org.hibernate.type.descriptor.java.JavaType;
|
||||||
|
|
||||||
import javax.lang.model.element.ModuleElement;
|
import javax.lang.model.element.ModuleElement;
|
||||||
import javax.lang.model.element.TypeElement;
|
import javax.lang.model.element.TypeElement;
|
||||||
|
import javax.lang.model.util.Elements;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
|
||||||
|
@ -194,13 +196,19 @@ class NamedQueryMethod implements MetaAttribute {
|
||||||
}
|
}
|
||||||
|
|
||||||
private @Nullable TypeElement entityType(String entityName) {
|
private @Nullable TypeElement entityType(String entityName) {
|
||||||
|
final Context context = annotationMeta.getContext();
|
||||||
|
final Elements elementUtils = context.getElementUtils();
|
||||||
|
final String qualifiedName = context.qualifiedNameForEntityName(entityName);
|
||||||
|
if ( qualifiedName != null ) {
|
||||||
|
return elementUtils.getTypeElement(qualifiedName);
|
||||||
|
}
|
||||||
TypeElement symbol =
|
TypeElement symbol =
|
||||||
findEntityByUnqualifiedName( entityName,
|
findEntityByUnqualifiedName( entityName,
|
||||||
annotationMeta.getContext().getElementUtils().getModuleElement("") );
|
elementUtils.getModuleElement("") );
|
||||||
if ( symbol != null ) {
|
if ( symbol != null ) {
|
||||||
return symbol;
|
return symbol;
|
||||||
}
|
}
|
||||||
for ( ModuleElement module : annotationMeta.getContext().getElementUtils().getAllModuleElements() ) {
|
for ( ModuleElement module : elementUtils.getAllModuleElements() ) {
|
||||||
symbol = findEntityByUnqualifiedName( entityName, module );
|
symbol = findEntityByUnqualifiedName( entityName, module );
|
||||||
if ( symbol != null ) {
|
if ( symbol != null ) {
|
||||||
return symbol;
|
return symbol;
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.processor.validation;
|
package org.hibernate.processor.validation;
|
||||||
|
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
import org.hibernate.CustomEntityDirtinessStrategy;
|
import org.hibernate.CustomEntityDirtinessStrategy;
|
||||||
import org.hibernate.EntityNameResolver;
|
import org.hibernate.EntityNameResolver;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
|
@ -58,7 +59,6 @@ import org.hibernate.metamodel.internal.MetadataContext;
|
||||||
import org.hibernate.metamodel.internal.RuntimeMetamodelsImpl;
|
import org.hibernate.metamodel.internal.RuntimeMetamodelsImpl;
|
||||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||||
import org.hibernate.metamodel.model.domain.DomainType;
|
import org.hibernate.metamodel.model.domain.DomainType;
|
||||||
import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
|
|
||||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.ManagedDomainType;
|
import org.hibernate.metamodel.model.domain.ManagedDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.PersistentAttribute;
|
import org.hibernate.metamodel.model.domain.PersistentAttribute;
|
||||||
|
@ -729,6 +729,11 @@ public abstract class MockSessionFactory
|
||||||
public EntityPersister findEntityDescriptor(String entityName) {
|
public EntityPersister findEntityDescriptor(String entityName) {
|
||||||
return createEntityPersister(entityName);
|
return createEntityPersister(entityName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getEnumTypesForValue(String enumValue) {
|
||||||
|
return MockSessionFactory.this.getEnumTypesForValue(enumValue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -868,9 +873,9 @@ public abstract class MockSessionFactory
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override @Nullable
|
||||||
public Set<String> getAllowedEnumLiteralTexts(String enumValue) {
|
public Set<String> getEnumTypesForValue(String enumValue) {
|
||||||
return MockSessionFactory.this.getAllowedEnumLiteralTexts().get(enumValue);
|
return MockSessionFactory.this.getEnumTypesForValue(enumValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -879,8 +884,9 @@ public abstract class MockSessionFactory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, Set<String>> getAllowedEnumLiteralTexts() {
|
@Nullable
|
||||||
return emptyMap();
|
Set<String> getEnumTypesForValue(String value) {
|
||||||
|
return emptySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
class MockMappedDomainType<X> extends MappedSuperclassTypeImpl<X>{
|
class MockMappedDomainType<X> extends MappedSuperclassTypeImpl<X>{
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
package org.hibernate.processor.validation;
|
package org.hibernate.processor.validation;
|
||||||
|
|
||||||
import jakarta.persistence.AccessType;
|
import jakarta.persistence.AccessType;
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
import org.hibernate.PropertyNotFoundException;
|
import org.hibernate.PropertyNotFoundException;
|
||||||
import org.hibernate.engine.spi.Mapping;
|
import org.hibernate.engine.spi.Mapping;
|
||||||
import org.hibernate.type.BasicType;
|
import org.hibernate.type.BasicType;
|
||||||
|
@ -21,6 +22,7 @@ import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||||
import org.hibernate.type.descriptor.jdbc.VarcharJdbcType;
|
import org.hibernate.type.descriptor.jdbc.VarcharJdbcType;
|
||||||
import org.hibernate.type.internal.BasicTypeImpl;
|
import org.hibernate.type.internal.BasicTypeImpl;
|
||||||
|
|
||||||
|
import javax.annotation.processing.Filer;
|
||||||
import javax.annotation.processing.ProcessingEnvironment;
|
import javax.annotation.processing.ProcessingEnvironment;
|
||||||
import javax.lang.model.element.AnnotationMirror;
|
import javax.lang.model.element.AnnotationMirror;
|
||||||
import javax.lang.model.element.AnnotationValue;
|
import javax.lang.model.element.AnnotationValue;
|
||||||
|
@ -40,10 +42,13 @@ import javax.lang.model.type.TypeMirror;
|
||||||
import javax.lang.model.type.TypeVariable;
|
import javax.lang.model.type.TypeVariable;
|
||||||
import javax.lang.model.util.Elements;
|
import javax.lang.model.util.Elements;
|
||||||
import javax.lang.model.util.Types;
|
import javax.lang.model.util.Types;
|
||||||
|
import javax.tools.StandardLocation;
|
||||||
import java.beans.Introspector;
|
import java.beans.Introspector;
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Reader;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -65,8 +70,11 @@ import static org.hibernate.processor.util.Constants.JAVA_OBJECT;
|
||||||
@SuppressWarnings("nullness")
|
@SuppressWarnings("nullness")
|
||||||
public abstract class ProcessorSessionFactory extends MockSessionFactory {
|
public abstract class ProcessorSessionFactory extends MockSessionFactory {
|
||||||
|
|
||||||
public static MockSessionFactory create(ProcessingEnvironment environment) {
|
public static MockSessionFactory create(
|
||||||
return instance.make(environment);
|
ProcessingEnvironment environment,
|
||||||
|
Map<String,String> entityNameMappings,
|
||||||
|
Map<String, Set<String>> enumTypesByValue) {
|
||||||
|
return instance.make(environment, entityNameMappings, enumTypesByValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
static final Mocker<ProcessorSessionFactory> instance = Mocker.variadic(ProcessorSessionFactory.class);
|
static final Mocker<ProcessorSessionFactory> instance = Mocker.variadic(ProcessorSessionFactory.class);
|
||||||
|
@ -80,10 +88,19 @@ public abstract class ProcessorSessionFactory extends MockSessionFactory {
|
||||||
|
|
||||||
private final Elements elementUtil;
|
private final Elements elementUtil;
|
||||||
private final Types typeUtil;
|
private final Types typeUtil;
|
||||||
|
private final Filer filer;
|
||||||
|
private final Map<String, String> entityNameMappings;
|
||||||
|
private final Map<String, Set<String>> enumTypesByValue;
|
||||||
|
|
||||||
public ProcessorSessionFactory(ProcessingEnvironment processingEnv) {
|
public ProcessorSessionFactory(
|
||||||
elementUtil = processingEnv.getElementUtils();
|
ProcessingEnvironment processingEnvironment,
|
||||||
typeUtil = processingEnv.getTypeUtils();
|
Map<String,String> entityNameMappings,
|
||||||
|
Map<String, Set<String>> enumTypesByValue) {
|
||||||
|
elementUtil = processingEnvironment.getElementUtils();
|
||||||
|
typeUtil = processingEnvironment.getTypeUtils();
|
||||||
|
filer = processingEnvironment.getFiler();
|
||||||
|
this.entityNameMappings = entityNameMappings;
|
||||||
|
this.enumTypesByValue = enumTypesByValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -196,29 +213,28 @@ public abstract class ProcessorSessionFactory extends MockSessionFactory {
|
||||||
: IntegerJdbcType.INSTANCE;
|
: IntegerJdbcType.INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Map<String, Set<String>> result = new HashMap<>();
|
public static final String ENTITY_INDEX = "entity.index";
|
||||||
|
|
||||||
@Override
|
@Override @Nullable
|
||||||
Map<String, Set<String>> getAllowedEnumLiteralTexts() {
|
Set<String> getEnumTypesForValue(String value) {
|
||||||
//TODO: elementUtil.getAllModuleElements();
|
Set<String> result = enumTypesByValue.get(value);
|
||||||
if ( result.isEmpty() ) {
|
if ( result != null ) {
|
||||||
for (Element mod : elementUtil.getModuleElement("").getEnclosedElements()) {
|
|
||||||
for (Element element : mod.getEnclosedElements()) {
|
|
||||||
if (element.getKind() == ElementKind.ENUM) {
|
|
||||||
TypeElement typeElement = (TypeElement) element;
|
|
||||||
for (Element member : element.getEnclosedElements()) {
|
|
||||||
if (member.getKind() == ElementKind.ENUM_CONSTANT) {
|
|
||||||
String name = member.getSimpleName().toString();
|
|
||||||
result.computeIfAbsent( name, s -> new HashSet<>() )
|
|
||||||
.add( typeElement.getQualifiedName().toString() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
try (Reader reader = filer.getResource(StandardLocation.SOURCE_OUTPUT, ENTITY_INDEX, value)
|
||||||
|
.openReader(true); BufferedReader buffered = new BufferedReader(reader) ) {
|
||||||
|
return Set.of(buffered.readLine().split(" "));
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
}
|
||||||
|
try (Reader reader = filer.getResource(StandardLocation.CLASS_PATH, ENTITY_INDEX, '.' + value)
|
||||||
|
.openReader(true); BufferedReader buffered = new BufferedReader(reader) ) {
|
||||||
|
return Set.of(buffered.readLine().split(" "));
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private static Type elementCollectionElementType(TypeElement elementType,
|
private static Type elementCollectionElementType(TypeElement elementType,
|
||||||
String role, String path,
|
String role, String path,
|
||||||
|
@ -430,6 +446,30 @@ public abstract class ProcessorSessionFactory extends MockSessionFactory {
|
||||||
if ( cached != null ) {
|
if ( cached != null ) {
|
||||||
return cached;
|
return cached;
|
||||||
}
|
}
|
||||||
|
String qualifiedName = entityNameMappings.get(entityName);
|
||||||
|
if ( qualifiedName != null ) {
|
||||||
|
TypeElement result = elementUtil.getTypeElement(qualifiedName);
|
||||||
|
entityCache.put(entityName, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
StandardLocation location = StandardLocation.SOURCE_OUTPUT;
|
||||||
|
try (Reader reader = filer.getResource(location, ENTITY_INDEX, entityName)
|
||||||
|
.openReader(true); BufferedReader buffered = new BufferedReader(reader) ) {
|
||||||
|
TypeElement result = elementUtil.getTypeElement(buffered.readLine());
|
||||||
|
entityCache.put(entityName, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
}
|
||||||
|
try (Reader reader = filer.getResource(StandardLocation.CLASS_PATH, ENTITY_INDEX, entityName)
|
||||||
|
.openReader(true); BufferedReader buffered = new BufferedReader(reader) ) {
|
||||||
|
TypeElement result = elementUtil.getTypeElement(buffered.readLine());
|
||||||
|
entityCache.put(entityName, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
}
|
||||||
|
|
||||||
TypeElement symbol =
|
TypeElement symbol =
|
||||||
findEntityByUnqualifiedName(entityName,
|
findEntityByUnqualifiedName(entityName,
|
||||||
elementUtil.getModuleElement(""));
|
elementUtil.getModuleElement(""));
|
||||||
|
|
Loading…
Reference in New Issue