HHH-16633 support AccessType.PROPERTY in @Find method parameter matching
This commit is contained in:
parent
376a90f9b5
commit
8681d702a4
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
package org.hibernate.jpamodelgen.annotation;
|
||||
|
||||
import java.beans.Introspector;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
|
@ -698,14 +699,17 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
|||
}
|
||||
|
||||
private @Nullable FieldType validateFinderParameter(TypeElement entity, VariableElement param) {
|
||||
final String entityClassName = entity.getQualifiedName().toString();
|
||||
determineAccessTypeForHierarchy( entity, context );
|
||||
final AccessType accessType = castNonNull( context.getAccessTypeInfo( entityClassName ) ).getAccessType();
|
||||
for ( Element member : entity.getEnclosedElements() ) {
|
||||
if ( member.getSimpleName().contentEquals( param.getSimpleName() ) ) {
|
||||
final String memberType = member.asType().toString();
|
||||
if ( fieldMatchesParameter( param, member, accessType ) ) {
|
||||
final String memberType = memberType( member ).toString();
|
||||
final String paramType = param.asType().toString();
|
||||
if ( !memberType.equals(paramType) ) {
|
||||
context.message( param,
|
||||
"matching field has type '" + memberType
|
||||
+ "' in entity class '" + entity.getQualifiedName() + "'",
|
||||
+ "' in entity class '" + entityClassName + "'",
|
||||
Diagnostic.Kind.ERROR );
|
||||
}
|
||||
if ( containsAnnotation( member, Constants.ID, Constants.EMBEDDED_ID ) ) {
|
||||
|
@ -730,11 +734,40 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
|||
}
|
||||
context.message( param,
|
||||
"no matching field named '" + param.getSimpleName()
|
||||
+ "' in entity class '" + entity.getQualifiedName() + "'",
|
||||
+ "' in entity class '" + entityClassName + "'",
|
||||
Diagnostic.Kind.ERROR );
|
||||
return null;
|
||||
}
|
||||
|
||||
private static TypeMirror memberType(Element member) {
|
||||
if (member.getKind() == ElementKind.METHOD) {
|
||||
ExecutableElement method = (ExecutableElement) member;
|
||||
return method.getReturnType();
|
||||
}
|
||||
else {
|
||||
return member.asType();
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean fieldMatchesParameter(VariableElement param, Element member, AccessType accessType) {
|
||||
final Name name = member.getSimpleName();
|
||||
final Name paramName = param.getSimpleName();
|
||||
if ( accessType == AccessType.FIELD ) {
|
||||
return name.contentEquals(paramName);
|
||||
}
|
||||
else {
|
||||
if ( name.length() > 3 && name.subSequence(0,3).toString().equals("get")) {
|
||||
final String propertyName = Introspector.decapitalize(name.subSequence(3, name.length()).toString());
|
||||
return paramName.contentEquals(propertyName);
|
||||
}
|
||||
if ( name.length() > 2 && name.subSequence(0,2).toString().equals("is")) {
|
||||
final String propertyName = Introspector.decapitalize(name.subSequence(2, name.length()).toString());
|
||||
return paramName.contentEquals(propertyName);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void addQueryMethod(
|
||||
ExecutableElement method,
|
||||
@Nullable TypeMirror returnType,
|
||||
|
|
|
@ -16,6 +16,7 @@ import javax.lang.model.element.Element;
|
|||
import javax.lang.model.element.ElementKind;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.lang.model.element.VariableElement;
|
||||
import javax.lang.model.type.ArrayType;
|
||||
import javax.lang.model.type.DeclaredType;
|
||||
import javax.lang.model.type.ExecutableType;
|
||||
|
@ -179,31 +180,31 @@ public final class TypeUtils {
|
|||
* <a href="http://www.retep.org/2009/02/getting-class-values-from-annotations.html">getting-class-values-from-annotations</a>.
|
||||
*
|
||||
* @param annotationMirror The annotation mirror
|
||||
* @param fqcn the fully qualified class name to check against
|
||||
* @param qualifiedName the fully qualified class name to check against
|
||||
*
|
||||
* @return {@code true} if the provided annotation type is of the same type as the provided class, {@code false} otherwise.
|
||||
*/
|
||||
public static boolean isAnnotationMirrorOfType(AnnotationMirror annotationMirror, String fqcn) {
|
||||
public static boolean isAnnotationMirrorOfType(AnnotationMirror annotationMirror, String qualifiedName) {
|
||||
assert annotationMirror != null;
|
||||
assert fqcn != null;
|
||||
assert qualifiedName != null;
|
||||
final Element element = annotationMirror.getAnnotationType().asElement();
|
||||
return ((TypeElement) element).getQualifiedName().contentEquals( fqcn );
|
||||
return ((TypeElement) element).getQualifiedName().contentEquals( qualifiedName );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the {@code Element} hosts the annotation with the given fully qualified class name.
|
||||
*
|
||||
* @param element the element to check for the hosted annotation
|
||||
* @param fqcn the fully qualified class name of the annotation to check for
|
||||
* @param qualifiedName the fully qualified class name of the annotation to check for
|
||||
*
|
||||
* @return the annotation mirror for the specified annotation class from the {@code Element} or {@code null} in case
|
||||
* the {@code TypeElement} does not host the specified annotation.
|
||||
*/
|
||||
public static @Nullable AnnotationMirror getAnnotationMirror(Element element, String fqcn) {
|
||||
public static @Nullable AnnotationMirror getAnnotationMirror(Element element, String qualifiedName) {
|
||||
assert element != null;
|
||||
assert fqcn != null;
|
||||
assert qualifiedName != null;
|
||||
for ( AnnotationMirror mirror : element.getAnnotationMirrors() ) {
|
||||
if ( isAnnotationMirrorOfType( mirror, fqcn ) ) {
|
||||
if ( isAnnotationMirrorOfType( mirror, qualifiedName ) ) {
|
||||
return mirror;
|
||||
}
|
||||
}
|
||||
|
@ -235,9 +236,9 @@ public final class TypeUtils {
|
|||
}
|
||||
|
||||
public static void determineAccessTypeForHierarchy(TypeElement searchedElement, Context context) {
|
||||
final String fqcn = searchedElement.getQualifiedName().toString();
|
||||
context.logMessage( Diagnostic.Kind.OTHER, "Determining access type for " + fqcn );
|
||||
final AccessTypeInformation accessTypeInfo = context.getAccessTypeInfo( fqcn );
|
||||
final String qualifiedName = searchedElement.getQualifiedName().toString();
|
||||
context.logMessage( Diagnostic.Kind.OTHER, "Determining access type for " + qualifiedName );
|
||||
final AccessTypeInformation accessTypeInfo = context.getAccessTypeInfo( qualifiedName );
|
||||
if ( accessTypeInfo != null && accessTypeInfo.isAccessTypeResolved() ) {
|
||||
context.logMessage(
|
||||
Diagnostic.Kind.OTHER,
|
||||
|
@ -253,8 +254,8 @@ public final class TypeUtils {
|
|||
"Explicit access type on " + searchedElement + ":" + forcedAccessType
|
||||
);
|
||||
final AccessTypeInformation newAccessTypeInfo =
|
||||
new AccessTypeInformation( fqcn, forcedAccessType, null );
|
||||
context.addAccessTypeInformation( fqcn, newAccessTypeInfo );
|
||||
new AccessTypeInformation( qualifiedName, forcedAccessType, null );
|
||||
context.addAccessTypeInformation( qualifiedName, newAccessTypeInfo );
|
||||
updateEmbeddableAccessType( searchedElement, context, forcedAccessType );
|
||||
}
|
||||
else {
|
||||
|
@ -264,8 +265,8 @@ public final class TypeUtils {
|
|||
final AccessType defaultAccessType = getAccessTypeInCaseElementIsRoot( searchedElement, context );
|
||||
if ( defaultAccessType != null ) {
|
||||
final AccessTypeInformation newAccessTypeInfo =
|
||||
new AccessTypeInformation(fqcn, null, defaultAccessType);
|
||||
context.addAccessTypeInformation( fqcn, newAccessTypeInfo );
|
||||
new AccessTypeInformation(qualifiedName, null, defaultAccessType);
|
||||
context.addAccessTypeInformation( qualifiedName, newAccessTypeInfo );
|
||||
updateEmbeddableAccessType( searchedElement, context, defaultAccessType );
|
||||
setDefaultAccessTypeForMappedSuperclassesInHierarchy( searchedElement, defaultAccessType, context );
|
||||
}
|
||||
|
@ -277,8 +278,8 @@ public final class TypeUtils {
|
|||
newDefaultAccessType = AccessType.PROPERTY;
|
||||
}
|
||||
final AccessTypeInformation newAccessTypeInfo =
|
||||
new AccessTypeInformation( fqcn, null, newDefaultAccessType );
|
||||
context.addAccessTypeInformation( fqcn, newAccessTypeInfo );
|
||||
new AccessTypeInformation( qualifiedName, null, newDefaultAccessType );
|
||||
context.addAccessTypeInformation( qualifiedName, newAccessTypeInfo );
|
||||
updateEmbeddableAccessType( searchedElement, context, newDefaultAccessType );
|
||||
}
|
||||
}
|
||||
|
@ -335,8 +336,8 @@ public final class TypeUtils {
|
|||
do {
|
||||
superClass = getSuperclassTypeElement( superClass );
|
||||
if ( superClass != null ) {
|
||||
final String fqcn = superClass.getQualifiedName().toString();
|
||||
final AccessTypeInformation accessTypeInfo = context.getAccessTypeInfo( fqcn );
|
||||
final String qualifiedName = superClass.getQualifiedName().toString();
|
||||
final AccessTypeInformation accessTypeInfo = context.getAccessTypeInfo( qualifiedName );
|
||||
if ( accessTypeInfo != null && accessTypeInfo.getDefaultAccessType() != null ) {
|
||||
return accessTypeInfo.getDefaultAccessType();
|
||||
}
|
||||
|
@ -344,8 +345,8 @@ public final class TypeUtils {
|
|||
defaultAccessType = getAccessTypeInCaseElementIsRoot( superClass, context );
|
||||
if ( defaultAccessType != null ) {
|
||||
final AccessTypeInformation newAccessTypeInfo
|
||||
= new AccessTypeInformation( fqcn, null, defaultAccessType );
|
||||
context.addAccessTypeInformation( fqcn, newAccessTypeInfo );
|
||||
= new AccessTypeInformation( qualifiedName, null, defaultAccessType );
|
||||
context.addAccessTypeInformation( qualifiedName, newAccessTypeInfo );
|
||||
|
||||
// we found an id within the class hierarchy and determined a default access type
|
||||
// there cannot be any super entity classes (otherwise it would be a configuration error)
|
||||
|
@ -373,14 +374,14 @@ public final class TypeUtils {
|
|||
do {
|
||||
superClass = getSuperclassTypeElement( superClass );
|
||||
if ( superClass != null ) {
|
||||
final String fqcn = superClass.getQualifiedName().toString();
|
||||
final String qualifiedName = superClass.getQualifiedName().toString();
|
||||
if ( containsAnnotation( superClass, Constants.MAPPED_SUPERCLASS ) ) {
|
||||
final AccessType forcedAccessType = determineAnnotationSpecifiedAccessType( superClass );
|
||||
final AccessTypeInformation accessTypeInfo =
|
||||
forcedAccessType != null
|
||||
? new AccessTypeInformation( fqcn, null, forcedAccessType )
|
||||
: new AccessTypeInformation( fqcn, null, defaultAccessType );
|
||||
context.addAccessTypeInformation( fqcn, accessTypeInfo );
|
||||
? new AccessTypeInformation( qualifiedName, null, forcedAccessType )
|
||||
: new AccessTypeInformation( qualifiedName, null, defaultAccessType );
|
||||
context.addAccessTypeInformation( qualifiedName, accessTypeInfo );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -425,15 +426,15 @@ public final class TypeUtils {
|
|||
}
|
||||
|
||||
public static @Nullable AccessType determineAnnotationSpecifiedAccessType(Element element) {
|
||||
final AnnotationMirror accessAnnotationMirror = TypeUtils.getAnnotationMirror( element, Constants.ACCESS );
|
||||
if ( accessAnnotationMirror != null ) {
|
||||
final Element accessElement = (Element)
|
||||
castNonNull( getAnnotationValue( accessAnnotationMirror, DEFAULT_ANNOTATION_PARAMETER_NAME ) );
|
||||
if ( accessElement.getKind() == ElementKind.ENUM_CONSTANT ) {
|
||||
if ( accessElement.getSimpleName().contentEquals( AccessType.PROPERTY.toString() ) ) {
|
||||
final AnnotationMirror mirror = getAnnotationMirror( element, Constants.ACCESS );
|
||||
if ( mirror != null ) {
|
||||
final Object accessType = getAnnotationValue( mirror, DEFAULT_ANNOTATION_PARAMETER_NAME );
|
||||
if ( accessType instanceof VariableElement) {
|
||||
final VariableElement enumValue = (VariableElement) accessType;
|
||||
if ( enumValue.getSimpleName().contentEquals( AccessType.PROPERTY.toString() ) ) {
|
||||
return AccessType.PROPERTY;
|
||||
}
|
||||
else if ( accessElement.getSimpleName().contentEquals( AccessType.FIELD.toString() ) ) {
|
||||
else if ( enumValue.getSimpleName().contentEquals( AccessType.FIELD.toString() ) ) {
|
||||
return AccessType.FIELD;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue