Skip to content

Commit b321840

Browse files
cigalygavinking
authored andcommitted
HHH-19326 Properly handling generics parameter types
1 parent 2e7ede2 commit b321840

File tree

4 files changed

+99
-13
lines changed

4 files changed

+99
-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: 90 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,32 @@
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.IntersectionType;
14+
import javax.lang.model.type.TypeKind;
15+
import javax.lang.model.type.TypeMirror;
16+
import javax.lang.model.type.TypeVariable;
17+
import javax.lang.model.type.WildcardType;
18+
import java.util.Collection;
1019
import java.util.Set;
1120

1221
import static java.lang.Character.toUpperCase;
22+
import static java.util.stream.Collectors.joining;
23+
import static java.util.stream.Collectors.toSet;
24+
import static javax.lang.model.type.TypeKind.VOID;
1325
import static org.hibernate.processor.util.Constants.EVENT;
1426
import static org.hibernate.processor.util.Constants.INJECT;
1527
import static org.hibernate.processor.util.Constants.JD_LIFECYCLE_EVENT;
1628
import static org.hibernate.processor.util.Constants.LIST;
1729
import static org.hibernate.processor.util.Constants.NONNULL;
1830
import static org.hibernate.processor.util.Constants.TYPE_LITERAL;
1931
import static org.hibernate.processor.util.Constants.UNI;
32+
import static org.hibernate.processor.util.TypeUtils.resolveTypeName;
2033

2134
public class LifecycleMethod extends AbstractAnnotatedMethod {
2235
private final String entity;
@@ -28,6 +41,8 @@ public class LifecycleMethod extends AbstractAnnotatedMethod {
2841
private final ParameterKind parameterKind;
2942
private final boolean returnArgument;
3043
private final boolean hasGeneratedId;
44+
private final Collection<String> methodTypeParameters;
45+
private final TypeElement element;
3146

3247
public enum ParameterKind {
3348
NORMAL,
@@ -48,7 +63,8 @@ public LifecycleMethod(
4863
boolean addNonnullAnnotation,
4964
ParameterKind parameterKind,
5065
boolean returnArgument,
51-
boolean hasGeneratedId) {
66+
boolean hasGeneratedId,
67+
TypeElement element) {
5268
super(annotationMetaEntity, method, sessionName, sessionType);
5369
this.entity = entity;
5470
this.actualEntity = actualEntity;
@@ -59,6 +75,11 @@ public LifecycleMethod(
5975
this.parameterKind = parameterKind;
6076
this.returnArgument = returnArgument;
6177
this.hasGeneratedId = hasGeneratedId;
78+
this.methodTypeParameters = method.getTypeParameters().stream()
79+
.map( TypeParameterElement::asType )
80+
.map( TypeMirror::toString )
81+
.collect( toSet() );
82+
this.element = element;
6283
}
6384

6485
@Override
@@ -334,27 +355,86 @@ private boolean isGeneratedIdUpsert() {
334355
private void preamble(StringBuilder declaration) {
335356
declaration
336357
.append("\n@Override\npublic ")
358+
.append(parameterTypeBopunds())
337359
.append(returnType())
338360
.append(' ')
339361
.append(methodName)
340362
.append('(');
341363
notNull(declaration);
364+
final var parameters = method.getParameters();
365+
assert parameters.size() == 1;
366+
final VariableElement element = parameters.get(0);
342367
declaration
343-
.append(annotationMetaEntity.importType(entity))
368+
.append(resolveAsString(element.asType()))
344369
.append(' ')
345-
.append(parameterName)
370+
.append(element.getSimpleName())
346371
.append(')')
347372
.append(" {\n");
348373
}
349374

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

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)