4
4
*/
5
5
package org .hibernate .models .internal .jdk ;
6
6
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
+
7
12
import java .lang .reflect .GenericArrayType ;
8
13
import java .lang .reflect .ParameterizedType ;
9
14
import java .lang .reflect .Type ;
14
19
import java .util .List ;
15
20
import java .util .Map ;
16
21
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
-
23
22
/**
24
23
* @author Steve Ebersole
25
24
*/
26
25
public class JdkTrackingTypeSwitcher implements JdkTypeSwitcher {
27
26
private final JdkTrackingTypeSwitch typeSwitch ;
28
27
29
- private List <String > typeVariableIdentifiers ;
28
+ private Map <String , TypeVariableResolution > typeVariables ;
30
29
private Map <String , List <TypeVariableReferenceDetailsImpl >> typeVariableRefXref ;
31
30
32
31
public static TypeDetails standardSwitchType (
@@ -41,8 +40,7 @@ public JdkTrackingTypeSwitcher(ModelsContext modelsContext) {
41
40
42
41
@ Override
43
42
public TypeDetails switchType (Type type ) {
44
- //noinspection rawtypes
45
- if ( type instanceof Class classType ) {
43
+ if ( type instanceof Class <?> classType ) {
46
44
return typeSwitch .caseClass ( classType );
47
45
}
48
46
@@ -54,8 +52,7 @@ public TypeDetails switchType(Type type) {
54
52
return typeSwitch .caseParameterizedType ( parameterizedType );
55
53
}
56
54
57
- //noinspection rawtypes
58
- if ( type instanceof TypeVariable typeVariable ) {
55
+ if ( type instanceof TypeVariable <?> typeVariable ) {
59
56
return switchTypeVariable ( type , typeVariable );
60
57
}
61
58
@@ -66,39 +63,60 @@ public TypeDetails switchType(Type type) {
66
63
return typeSwitch .defaultCase ( type );
67
64
}
68
65
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 );
72
71
}
73
72
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
+ }
75
83
// this should indicate a "recursive" type var (e.g. `T extends Comparable<T>`)
76
84
final TypeVariableReferenceDetailsImpl reference = new TypeVariableReferenceDetailsImpl ( type .getTypeName () );
77
85
if ( typeVariableRefXref == null ) {
78
86
typeVariableRefXref = new HashMap <>();
79
- final List <TypeVariableReferenceDetailsImpl > list = typeVariableRefXref .computeIfAbsent (
80
- type .getTypeName (),
81
- (s ) -> new ArrayList <>()
82
- );
83
- list .add ( reference );
84
87
}
88
+ final List <TypeVariableReferenceDetailsImpl > list = typeVariableRefXref .computeIfAbsent (
89
+ type .getTypeName (),
90
+ (s ) -> new ArrayList <>()
91
+ );
92
+ list .add ( reference );
85
93
return reference ;
86
94
}
87
95
}
88
- typeVariableIdentifiers .add ( typeVariable .getTypeName () );
89
96
90
97
final TypeVariableDetails switched = typeSwitch .caseTypeVariable ( typeVariable );
91
98
assert switched != null ;
99
+ resolution .setDetails ( switched );
92
100
93
101
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 ) );
99
105
}
100
106
}
101
107
102
108
return switched ;
103
109
}
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
+ }
104
122
}
0 commit comments