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 eb95f6b362..a1a84c5c6e 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 @@ -376,8 +376,7 @@ public class HibernateProcessor extends AbstractProcessor { context.logMessage( Diagnostic.Kind.OTHER, "Processing annotated class '" + element + "'" ); handleRootElementAuxiliaryAnnotationMirrors( element ); } - else if ( element instanceof TypeElement ) { - final TypeElement typeElement = (TypeElement) element; + else if ( element instanceof TypeElement typeElement ) { final AnnotationMirror repository = getAnnotationMirror( element, JD_REPOSITORY ); if ( repository != null ) { final AnnotationValue provider = getAnnotationValue( repository, "provider" ); 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 4de91ab5b0..1c454e9bd3 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 @@ -21,6 +21,9 @@ import javax.lang.model.element.AnnotationValue; import javax.lang.model.element.Element; import java.util.List; +import static java.lang.Character.isJavaIdentifierStart; +import static org.hibernate.processor.util.Constants.JAVA_OBJECT; +import static org.hibernate.processor.util.Constants.NAMED_QUERY; import static org.hibernate.processor.util.TypeUtils.containsAnnotation; import static org.hibernate.processor.util.TypeUtils.getAnnotationMirror; import static org.hibernate.processor.util.TypeUtils.getAnnotationValue; @@ -28,7 +31,7 @@ import static org.hibernate.processor.util.TypeUtils.getAnnotationValue; public abstract class AnnotationMeta implements Metamodel { void addAuxiliaryMembers() { - addAuxiliaryMembersForAnnotation( Constants.NAMED_QUERY, "QUERY_" ); + addAuxiliaryMembersForAnnotation( NAMED_QUERY, "QUERY_" ); addAuxiliaryMembersForRepeatableAnnotation( Constants.NAMED_QUERIES, "QUERY_" ); addAuxiliaryMembersForAnnotation( Constants.NAMED_NATIVE_QUERY, "QUERY_" ); addAuxiliaryMembersForRepeatableAnnotation( Constants.NAMED_NATIVE_QUERIES, "QUERY_" ); @@ -50,7 +53,7 @@ public abstract class AnnotationMeta implements Metamodel { void checkNamedQueries() { boolean checkHql = containsAnnotation( getElement(), Constants.CHECK_HQL ) || containsAnnotation( getElement().getEnclosingElement(), Constants.CHECK_HQL ); - handleNamedQueryAnnotation( Constants.NAMED_QUERY, checkHql ); + handleNamedQueryAnnotation( NAMED_QUERY, checkHql ); handleNamedQueryRepeatableAnnotation( Constants.NAMED_QUERIES, checkHql ); handleNamedQueryAnnotation( Constants.HIB_NAMED_QUERY, checkHql ); handleNamedQueryRepeatableAnnotation( Constants.HIB_NAMED_QUERIES, checkHql ); @@ -86,9 +89,7 @@ public abstract class AnnotationMeta implements Metamodel { final boolean reportErrors = context.checkNamedQuery( name ); final AnnotationValue value = getAnnotationValue( mirror, "query" ); if ( value != null ) { - final Object query = value.getValue(); - if ( query instanceof String ) { - final String hql = (String) query; + if ( value.getValue() instanceof String hql ) { final SqmStatement statement = Validation.validate( hql, @@ -124,7 +125,7 @@ public abstract class AnnotationMeta implements Metamodel { private static boolean isQueryMethodName(String name) { return name.length() >= 2 && name.charAt(0) == '#' - && Character.isJavaIdentifierStart( name.charAt(1) ) + && isJavaIdentifierStart( name.charAt(1) ) && name.substring(2).chars().allMatch(Character::isJavaIdentifierPart); } @@ -155,13 +156,30 @@ public abstract class AnnotationMeta implements Metamodel { if ( key.getSimpleName().contentEquals("name") ) { final String name = value.getValue().toString(); if ( !name.isEmpty() ) { - putMember( prefix + name, - new NameMetaAttribute( this, name, prefix ) ); + putMember( prefix + name, auxiliaryMember( mirror, prefix, name ) ); } } }); } + private NameMetaAttribute auxiliaryMember(AnnotationMirror mirror, String prefix, String name) { + if ( !isJakartaDataStyle() && "QUERY_".equals(prefix) ) { + final AnnotationValue resultClass = getAnnotationValue( mirror, "resultClass" ); + //TODO: if there is no explicit result class, obtain the result class by + // type-checking the query (this is allowed but not required by JPA) + return new TypedMetaAttribute( this, name, prefix, + resultClass == null ? JAVA_OBJECT : resultClass.getValue().toString(), + "jakarta.persistence.TypedQueryReference" ); + } + else if ( !isJakartaDataStyle() && "GRAPH_".equals(prefix) ) { + return new TypedMetaAttribute( this, name, prefix, getQualifiedName(), + "jakarta.persistence.EntityGraph" ); + } + else { + return new NameMetaAttribute( this, name, prefix); + } + } + protected String getSessionVariableName() { return "entityManager"; } diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/processor/annotation/AnnotationMetaAttribute.java b/tooling/metamodel-generator/src/main/java/org/hibernate/processor/annotation/AnnotationMetaAttribute.java index de1f00c2d8..bb205b8ce3 100644 --- a/tooling/metamodel-generator/src/main/java/org/hibernate/processor/annotation/AnnotationMetaAttribute.java +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/processor/annotation/AnnotationMetaAttribute.java @@ -45,19 +45,20 @@ public abstract class AnnotationMetaAttribute implements MetaAttribute { public String getAttributeDeclarationString() { return new StringBuilder() .append("\n/**\n * @see ") - .append( parent.getQualifiedName() ) - .append( "#") - .append( element.getSimpleName() ) - .append( "\n **/\n" ) - .append( "public static volatile " ) - .append( parent.importType( getMetaType() ) ) - .append( "<" ) - .append( parent.importType( parent.getQualifiedName() ) ) - .append( ", " ) - .append( parent.importType( getTypeDeclaration() ) ) - .append( "> " ) - .append( getPropertyName() ) - .append( ";" ) + .append(parent.getQualifiedName()) + .append('#') + .append(element.getSimpleName()) + .append("\n **/\n") + .append("public static volatile ") + .append(parent.importType(getMetaType())) + .append('<') + .append(parent.importType(parent.getQualifiedName())) + .append(", ") + .append(parent.importType(getTypeDeclaration())) + .append('>') + .append(' ') + .append(getPropertyName()) + .append(';') .toString(); } @@ -66,13 +67,13 @@ public abstract class AnnotationMetaAttribute implements MetaAttribute { return new StringBuilder() .append("public static final ") .append(parent.importType(String.class.getName())) - .append(" ") + .append(' ') .append(getUpperUnderscoreCaseFromLowerCamelCase(getPropertyName())) .append(" = ") - .append("\"") + .append('"') .append(getPropertyName()) - .append("\"") - .append(";") + .append('"') + .append(';') .toString(); } diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/processor/annotation/NameMetaAttribute.java b/tooling/metamodel-generator/src/main/java/org/hibernate/processor/annotation/NameMetaAttribute.java index 9d687e614a..d3fbf60e50 100644 --- a/tooling/metamodel-generator/src/main/java/org/hibernate/processor/annotation/NameMetaAttribute.java +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/processor/annotation/NameMetaAttribute.java @@ -43,14 +43,14 @@ class NameMetaAttribute implements MetaAttribute { return new StringBuilder() .append("public static final ") .append(annotationMetaEntity.importType(String.class.getName())) - .append(" ") + .append(' ') .append(prefix) .append(fieldName()) .append(" = ") - .append("\"") + .append('"') .append(name) - .append("\"") - .append(";") + .append('"') + .append(';') .toString(); } diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/processor/annotation/TypedMetaAttribute.java b/tooling/metamodel-generator/src/main/java/org/hibernate/processor/annotation/TypedMetaAttribute.java new file mode 100644 index 0000000000..79d821bdf3 --- /dev/null +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/processor/annotation/TypedMetaAttribute.java @@ -0,0 +1,52 @@ +/* + * SPDX-License-Identifier: LGPL-2.1-or-later + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.processor.annotation; + +import org.hibernate.processor.model.Metamodel; + +import static org.hibernate.processor.util.StringUtil.nameToMethodName; + +/** + * @author Gavin King + */ +class TypedMetaAttribute extends NameMetaAttribute { + private final String resultType; + private final String referenceType; + + public TypedMetaAttribute( + Metamodel annotationMetaEntity, + String name, + String prefix, + String resultType, + String referenceType) { + super( annotationMetaEntity, name, prefix ); + this.resultType = resultType; + this.referenceType = referenceType; + } + + @Override + public boolean hasTypedAttribute() { + return true; + } + + @Override + public String getAttributeDeclarationString() { + final Metamodel entity = getHostingEntity(); + return new StringBuilder() + .append("\n/**\n * @see ") + .append(entity.getQualifiedName()) + .append("\n **/\n") + .append("public static volatile ") + .append(entity.importType(referenceType)) + .append('<') + .append(entity.importType(resultType)) + .append('>') + .append(' ') + .append('_') + .append(nameToMethodName(getPropertyName())) + .append(';') + .toString(); + } +}