44 */
55package org .hibernate .processor .annotation ;
66
7-
87import 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 ;
1018import java .util .Set ;
1119
1220import 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 ;
1324import static org .hibernate .processor .util .Constants .EVENT ;
1425import static org .hibernate .processor .util .Constants .INJECT ;
1526import static org .hibernate .processor .util .Constants .JD_LIFECYCLE_EVENT ;
1627import static org .hibernate .processor .util .Constants .LIST ;
1728import static org .hibernate .processor .util .Constants .NONNULL ;
1829import static org .hibernate .processor .util .Constants .TYPE_LITERAL ;
1930import static org .hibernate .processor .util .Constants .UNI ;
31+ import static org .hibernate .processor .util .TypeUtils .resolveTypeName ;
2032
2133public 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\n public " )
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
0 commit comments