Skip to content

Commit a8c6132

Browse files
cigalygavinking
authored andcommitted
HHH-19626 Properly resolving generic parameter type in subclass
1 parent e256006 commit a8c6132

File tree

2 files changed

+52
-1
lines changed

2 files changed

+52
-1
lines changed

tooling/metamodel-generator/src/main/java/org/hibernate/processor/annotation/AnnotationMetaEntity.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
import static java.beans.Introspector.decapitalize;
6868
import static java.lang.Boolean.FALSE;
6969
import static java.util.Collections.emptyList;
70+
import static java.util.Objects.requireNonNullElse;
7071
import static java.util.stream.Collectors.toList;
7172
import static javax.lang.model.util.ElementFilter.fieldsIn;
7273
import static javax.lang.model.util.ElementFilter.methodsIn;
@@ -100,6 +101,7 @@
100101
import static org.hibernate.processor.util.TypeUtils.implementsInterface;
101102
import static org.hibernate.processor.util.TypeUtils.primitiveClassMatchesKind;
102103
import static org.hibernate.processor.util.TypeUtils.propertyName;
104+
import static org.hibernate.processor.util.TypeUtils.resolveTypeMirror;
103105

104106
/**
105107
* Class used to collect meta information about an annotated type (entity, embeddable or mapped superclass).
@@ -2526,7 +2528,15 @@ enum FieldType {
25262528
return null;
25272529
}
25282530

2529-
if ( checkParameterType( entityType, param, memberType( member ) ) ) {
2531+
final var memberType = memberType( member );
2532+
final var attributeType = requireNonNullElse(
2533+
resolveTypeMirror(
2534+
entityType,
2535+
member.getEnclosingElement(),
2536+
memberType.toString()
2537+
), memberType
2538+
);
2539+
if ( checkParameterType( entityType, param, attributeType ) ) {
25302540
return FieldType.MULTIVALUED;
25312541
}
25322542
else if ( containsAnnotation( param, PATTERN ) ) {

tooling/metamodel-generator/src/main/java/org/hibernate/processor/util/TypeUtils.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,17 @@
3030
import javax.lang.model.util.Elements;
3131
import javax.lang.model.util.SimpleTypeVisitor8;
3232
import javax.tools.Diagnostic;
33+
import java.util.Collection;
3334
import java.util.HashMap;
3435
import java.util.HashSet;
3536
import java.util.List;
3637
import java.util.Map;
38+
import java.util.Objects;
3739
import java.util.Set;
40+
import java.util.stream.Stream;
3841

3942
import static java.beans.Introspector.decapitalize;
43+
import static java.util.stream.Stream.concat;
4044
import static org.hibernate.internal.util.StringHelper.split;
4145
import static org.hibernate.processor.util.AccessTypeInformation.DEFAULT_ACCESS_TYPE;
4246
import static org.hibernate.processor.util.Constants.ACCESS;
@@ -779,4 +783,41 @@ public static boolean isPrimitive(String paramType) {
779783

780784
public static final Set<String> PRIMITIVE_TYPES =
781785
Set.of("boolean", "char", "long", "int", "short", "byte", "double", "float");
786+
787+
public static TypeMirror resolveTypeMirror(TypeElement typeElement, Element element, String name) {
788+
final var mirrorMap = resolveTypeParameters( typeElement.asType(), element, Map.of(), new HashSet<>() );
789+
return mirrorMap == null ? null : mirrorMap.get( name );
790+
}
791+
792+
private static Map<String, TypeMirror> resolveTypeParameters(TypeMirror type, Element element, Map<String, TypeMirror> parametersMap, Collection<Element> visited) {
793+
if ( !(type instanceof DeclaredType declaredType
794+
&& declaredType.asElement() instanceof TypeElement typeElement) ) {
795+
return null;
796+
}
797+
if ( !visited.add( typeElement ) ) {
798+
return null;
799+
}
800+
final var generic = typeElement.getTypeParameters();
801+
final var map = new HashMap<String, TypeMirror>();
802+
var typeArguments = declaredType.getTypeArguments();
803+
if ( !(typeArguments.isEmpty() || generic.size() == typeArguments.size()) ) {
804+
return null;
805+
}
806+
for ( var n = 0; n < generic.size(); ++n ) {
807+
final var mirror = typeArguments.isEmpty()
808+
? generic.get( 0 ).getBounds().get( 0 )
809+
: typeArguments.get( n );
810+
final var value = mirror.toString();
811+
map.put( generic.get( n ).toString(), parametersMap.getOrDefault( value, mirror ) );
812+
}
813+
if ( typeElement.equals( element ) ) {
814+
return map;
815+
}
816+
return concat(
817+
Stream.of( typeElement.getSuperclass() ),
818+
typeElement.getInterfaces().stream()
819+
).map( tm -> resolveTypeParameters( tm, element, map, visited ) )
820+
.filter( Objects::nonNull )
821+
.findFirst().orElse( null );
822+
}
782823
}

0 commit comments

Comments
 (0)