44 */
55package org .hibernate .models .internal .jdk ;
66
7+ import org .hibernate .models .internal .TypeVariableReferenceDetailsImpl ;
8+ import org .hibernate .models .spi .ModelsContext ;
9+ import org .hibernate .models .spi .TypeDetails ;
10+ import org .hibernate .models .spi .TypeVariableDetails ;
11+
712import java .lang .reflect .GenericArrayType ;
813import java .lang .reflect .ParameterizedType ;
914import java .lang .reflect .Type ;
1419import java .util .List ;
1520import java .util .Map ;
1621
17- import org .hibernate .models .internal .TypeVariableReferenceDetailsImpl ;
18- import org .hibernate .models .internal .util .CollectionHelper ;
19- import org .hibernate .models .spi .ModelsContext ;
20- import org .hibernate .models .spi .TypeDetails ;
21- import org .hibernate .models .spi .TypeVariableDetails ;
22-
2322/**
2423 * @author Steve Ebersole
2524 */
2625public class JdkTrackingTypeSwitcher implements JdkTypeSwitcher {
2726 private final JdkTrackingTypeSwitch typeSwitch ;
2827
29- private List <String > typeVariableIdentifiers ;
28+ private Map <String , TypeVariableResolution > typeVariables ;
3029 private Map <String , List <TypeVariableReferenceDetailsImpl >> typeVariableRefXref ;
3130
3231 public static TypeDetails standardSwitchType (
@@ -41,8 +40,7 @@ public JdkTrackingTypeSwitcher(ModelsContext modelsContext) {
4140
4241 @ Override
4342 public TypeDetails switchType (Type type ) {
44- //noinspection rawtypes
45- if ( type instanceof Class classType ) {
43+ if ( type instanceof Class <?> classType ) {
4644 return typeSwitch .caseClass ( classType );
4745 }
4846
@@ -54,8 +52,7 @@ public TypeDetails switchType(Type type) {
5452 return typeSwitch .caseParameterizedType ( parameterizedType );
5553 }
5654
57- //noinspection rawtypes
58- if ( type instanceof TypeVariable typeVariable ) {
55+ if ( type instanceof TypeVariable <?> typeVariable ) {
5956 return switchTypeVariable ( type , typeVariable );
6057 }
6158
@@ -66,39 +63,60 @@ public TypeDetails switchType(Type type) {
6663 return typeSwitch .defaultCase ( type );
6764 }
6865
69- private TypeDetails switchTypeVariable (Type type , @ SuppressWarnings ("rawtypes" ) TypeVariable typeVariable ) {
70- if ( typeVariableIdentifiers == null ) {
71- typeVariableIdentifiers = new ArrayList <>();
66+ private TypeDetails switchTypeVariable (Type type , TypeVariable <?> typeVariable ) {
67+ final TypeVariableResolution resolution = new TypeVariableResolution ();
68+ if ( typeVariables == null ) {
69+ typeVariables = new HashMap <>();
70+ typeVariables .put ( typeVariable .getName (), resolution );
7271 }
7372 else {
74- if ( typeVariableIdentifiers .contains ( typeVariable .getTypeName () ) ) {
73+ final TypeVariableResolution existingResolution = typeVariables .putIfAbsent (
74+ typeVariable .getTypeName (),
75+ resolution
76+ );
77+ if ( existingResolution != null ) {
78+ final TypeVariableDetails details = existingResolution .getDetails ();
79+ if ( details != null ) {
80+ // The type variable has already been switched, so we can return the original details
81+ return details ;
82+ }
7583 // this should indicate a "recursive" type var (e.g. `T extends Comparable<T>`)
7684 final TypeVariableReferenceDetailsImpl reference = new TypeVariableReferenceDetailsImpl ( type .getTypeName () );
7785 if ( typeVariableRefXref == null ) {
7886 typeVariableRefXref = new HashMap <>();
79- final List <TypeVariableReferenceDetailsImpl > list = typeVariableRefXref .computeIfAbsent (
80- type .getTypeName (),
81- (s ) -> new ArrayList <>()
82- );
83- list .add ( reference );
8487 }
88+ final List <TypeVariableReferenceDetailsImpl > list = typeVariableRefXref .computeIfAbsent (
89+ type .getTypeName (),
90+ (s ) -> new ArrayList <>()
91+ );
92+ list .add ( reference );
8593 return reference ;
8694 }
8795 }
88- typeVariableIdentifiers .add ( typeVariable .getTypeName () );
8996
9097 final TypeVariableDetails switched = typeSwitch .caseTypeVariable ( typeVariable );
9198 assert switched != null ;
99+ resolution .setDetails ( switched );
92100
93101 if ( typeVariableRefXref != null ) {
94- final List <TypeVariableReferenceDetailsImpl > list = typeVariableRefXref .get ( typeVariable .getTypeName () );
95- if ( CollectionHelper .isNotEmpty ( list ) ) {
96- for ( TypeVariableReferenceDetailsImpl reference : list ) {
97- reference .setTarget ( switched );
98- }
102+ final List <TypeVariableReferenceDetailsImpl > list = typeVariableRefXref .remove ( typeVariable .getTypeName () );
103+ if ( list != null ) {
104+ list .forEach ( reference -> reference .setTarget ( switched ) );
99105 }
100106 }
101107
102108 return switched ;
103109 }
110+
111+ private static class TypeVariableResolution {
112+ private TypeVariableDetails details ;
113+
114+ public void setDetails (TypeVariableDetails details ) {
115+ this .details = details ;
116+ }
117+
118+ public TypeVariableDetails getDetails () {
119+ return details ;
120+ }
121+ }
104122}
0 commit comments