Skip to content

Commit 28dd42c

Browse files
committed
HHH-19326 Properly handling generics parameter types
1 parent e65ce2d commit 28dd42c

File tree

4 files changed

+96
-13
lines changed

4 files changed

+96
-13
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
public abstract class AbstractAnnotatedMethod implements MetaAttribute {
2525

2626
final AnnotationMetaEntity annotationMetaEntity;
27-
private final ExecutableElement method;
27+
final ExecutableElement method;
2828
final String sessionType;
2929
final String sessionName;
3030

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1830,7 +1830,8 @@ else if ( returnArgument
18301830
context.addNonnullAnnotation(),
18311831
lifecycleParameterKind(parameterType),
18321832
returnArgument,
1833-
hasGeneratedId(declaredType)
1833+
hasGeneratedId(declaredType),
1834+
element
18341835
)
18351836
);
18361837
}

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

Lines changed: 87 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,31 @@
44
*/
55
package org.hibernate.processor.annotation;
66

7-
87
import javax.lang.model.element.ExecutableElement;
9-
8+
import javax.lang.model.element.TypeElement;
9+
import javax.lang.model.element.TypeParameterElement;
10+
import javax.lang.model.element.VariableElement;
11+
import javax.lang.model.type.ArrayType;
12+
import javax.lang.model.type.DeclaredType;
13+
import javax.lang.model.type.TypeKind;
14+
import javax.lang.model.type.TypeMirror;
15+
import javax.lang.model.type.TypeVariable;
16+
import javax.lang.model.type.WildcardType;
17+
import java.util.Collection;
1018
import java.util.Set;
1119

1220
import static java.lang.Character.toUpperCase;
21+
import static java.util.stream.Collectors.joining;
22+
import static java.util.stream.Collectors.toSet;
23+
import static javax.lang.model.type.TypeKind.VOID;
1324
import static org.hibernate.processor.util.Constants.EVENT;
1425
import static org.hibernate.processor.util.Constants.INJECT;
1526
import static org.hibernate.processor.util.Constants.JD_LIFECYCLE_EVENT;
1627
import static org.hibernate.processor.util.Constants.LIST;
1728
import static org.hibernate.processor.util.Constants.NONNULL;
1829
import static org.hibernate.processor.util.Constants.TYPE_LITERAL;
1930
import static org.hibernate.processor.util.Constants.UNI;
31+
import static org.hibernate.processor.util.TypeUtils.resolveTypeName;
2032

2133
public class LifecycleMethod extends AbstractAnnotatedMethod {
2234
private final String entity;
@@ -28,6 +40,8 @@ public class LifecycleMethod extends AbstractAnnotatedMethod {
2840
private final ParameterKind parameterKind;
2941
private final boolean returnArgument;
3042
private final boolean hasGeneratedId;
43+
private final Collection<String> methodTypeParameters;
44+
private final TypeElement element;
3145

3246
public enum ParameterKind {
3347
NORMAL,
@@ -48,7 +62,8 @@ public LifecycleMethod(
4862
boolean addNonnullAnnotation,
4963
ParameterKind parameterKind,
5064
boolean returnArgument,
51-
boolean hasGeneratedId) {
65+
boolean hasGeneratedId,
66+
TypeElement element) {
5267
super(annotationMetaEntity, method, sessionName, sessionType);
5368
this.entity = entity;
5469
this.actualEntity = actualEntity;
@@ -59,6 +74,11 @@ public LifecycleMethod(
5974
this.parameterKind = parameterKind;
6075
this.returnArgument = returnArgument;
6176
this.hasGeneratedId = hasGeneratedId;
77+
this.methodTypeParameters = method.getTypeParameters().stream()
78+
.map( TypeParameterElement::asType )
79+
.map( TypeMirror::toString )
80+
.collect( toSet() );
81+
this.element = element;
6282
}
6383

6484
@Override
@@ -334,27 +354,84 @@ private boolean isGeneratedIdUpsert() {
334354
private void preamble(StringBuilder declaration) {
335355
declaration
336356
.append("\n@Override\npublic ")
357+
.append(parameterTypeBopunds())
337358
.append(returnType())
338359
.append(' ')
339360
.append(methodName)
340361
.append('(');
341362
notNull(declaration);
363+
final var parameters = method.getParameters();
364+
assert parameters.size() == 1;
365+
final VariableElement element = parameters.get(0);
342366
declaration
343-
.append(annotationMetaEntity.importType(entity))
367+
.append(resolveAsString(element.asType()))
344368
.append(' ')
345-
.append(parameterName)
369+
.append(element.getSimpleName())
346370
.append(')')
347371
.append(" {\n");
348372
}
349373

374+
private String parameterTypeBopunds() {
375+
if ( method.getTypeParameters().isEmpty() ) {
376+
return "";
377+
}
378+
return method.getTypeParameters().stream()
379+
.map( this::resolveTypeParameter )
380+
.collect( joining( ", ", " <", "> " ) );
381+
}
382+
383+
private String resolveAsString(TypeMirror type) {
384+
if ( type.getKind().isPrimitive() || type.getKind() == VOID ) {
385+
return type.toString();
386+
}
387+
else if ( type instanceof DeclaredType declaredType ) {
388+
final var element = annotationMetaEntity.importType(
389+
((TypeElement) declaredType.asElement()).getQualifiedName().toString()
390+
);
391+
if ( declaredType.getTypeArguments().isEmpty() ) {
392+
return element;
393+
}
394+
return element + declaredType.getTypeArguments().stream().map( this::resolveAsString )
395+
.collect( joining( ",", "<", ">" ) );
396+
}
397+
else if ( type instanceof TypeVariable typeVariable ) {
398+
final var value = typeVariable.toString();
399+
if ( methodTypeParameters.contains( value ) ) {
400+
return value;
401+
}
402+
return annotationMetaEntity.importType( resolveTypeName( element, method.getEnclosingElement(), value ) );
403+
}
404+
else if ( type instanceof WildcardType wildcardType ) {
405+
return "?"
406+
+ (wildcardType.getExtendsBound() == null ? ""
407+
: " extends " + resolveAsString( wildcardType.getExtendsBound() ))
408+
+ (wildcardType.getSuperBound() == null ? ""
409+
: " super " + resolveAsString( wildcardType.getExtendsBound() ));
410+
}
411+
else if ( type instanceof ArrayType arrayType ) {
412+
return resolveAsString( arrayType.getComponentType() ) + "[]";
413+
}
414+
else {
415+
System.err.printf( "Type kind %s - %s%n", type.getKind(), type );
416+
throw new UnsupportedOperationException();
417+
}
418+
}
419+
420+
private String resolveTypeParameter(TypeParameterElement p) {
421+
final var type = (TypeVariable) p.asType();
422+
return type.toString()
423+
+ (type.getUpperBound().getKind() == TypeKind.NULL ? ""
424+
: " extends " + resolveAsString( type.getUpperBound() ))
425+
+ (type.getLowerBound().getKind() == TypeKind.NULL ? ""
426+
: " super " + resolveAsString( type.getLowerBound() ));
427+
}
428+
350429
private String returnType() {
351-
final String entityType = annotationMetaEntity.importType(entity);
352-
if ( isReactive() ) {
353-
return annotationMetaEntity.importType(UNI)
354-
+ '<' + (returnArgument ? entityType : "Void") + '>';
430+
if ( returnArgument ) {
431+
return resolveAsString(method.getReturnType());
355432
}
356433
else {
357-
return returnArgument ? entityType : "void";
434+
return isReactive() ? annotationMetaEntity.importType(UNI) + "<Void>" : "void";
358435
}
359436
}
360437

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -784,6 +784,11 @@ public static boolean isPrimitive(String paramType) {
784784
public static final Set<String> PRIMITIVE_TYPES =
785785
Set.of("boolean", "char", "long", "int", "short", "byte", "double", "float");
786786

787+
public static String resolveTypeName(TypeElement typeElement, Element element, String name) {
788+
final var mirror = resolveTypeMirror( typeElement, element, name );
789+
return mirror == null ? name : mirror.toString();
790+
}
791+
787792
public static @Nullable TypeMirror resolveTypeMirror(TypeElement typeElement, Element element, String name) {
788793
final var mirrorMap = resolveTypeParameters( typeElement.asType(), element, Map.of(), new HashSet<>() );
789794
return mirrorMap == null ? null : mirrorMap.get( name );
@@ -808,7 +813,7 @@ public static boolean isPrimitive(String paramType) {
808813
? generic.get( 0 ).getBounds().get( 0 )
809814
: typeArguments.get( n );
810815
final var value = mirror.toString();
811-
map.put( generic.get( n ).toString(), parametersMap.getOrDefault( value, mirror ) );
816+
map.put( generic.get( n ).asType().toString(), parametersMap.getOrDefault( value, mirror ) );
812817
}
813818
if ( typeElement.equals( element ) ) {
814819
return map;

0 commit comments

Comments
 (0)