6
6
7
7
import java .util .ArrayList ;
8
8
import java .util .Collections ;
9
+ import java .util .LinkedHashSet ;
9
10
import java .util .List ;
10
11
import java .util .Map ;
12
+ import java .util .Set ;
11
13
import java .util .concurrent .ConcurrentHashMap ;
14
+ import java .util .function .Predicate ;
12
15
13
16
import org .hibernate .models .UnknownClassException ;
17
+ import org .hibernate .models .internal .util .CollectionHelper ;
14
18
import org .hibernate .models .spi .ClassDetails ;
15
19
import org .hibernate .models .spi .ModelsContext ;
16
20
import org .hibernate .models .spi .TypeDetails ;
@@ -31,18 +35,18 @@ public abstract class AbstractClassDetailsRegistry implements MutableClassDetail
31
35
protected final Map <String , ClassDetails > classDetailsMap ;
32
36
33
37
// subtype per type
34
- protected final Map <String , List <ClassDetails >> directSubTypeMap ;
38
+ protected final Map <String , Set <ClassDetails >> directSubTypeMap ;
35
39
// implementor by interface
36
- protected final Map <String , List <ClassDetails >> directImplementorMap ;
40
+ protected final Map <String , Set <ClassDetails >> directImplementorMap ;
37
41
38
42
protected AbstractClassDetailsRegistry (ModelsContext context ) {
39
43
this ( new ConcurrentHashMap <>(), new ConcurrentHashMap <>(), new ConcurrentHashMap <>(), context );
40
44
}
41
45
42
46
protected AbstractClassDetailsRegistry (
43
47
Map <String , ClassDetails > classDetailsMap ,
44
- Map <String , List <ClassDetails >> directSubTypeMap ,
45
- Map <String , List <ClassDetails >> directImplementorMap ,
48
+ Map <String , Set <ClassDetails >> directSubTypeMap ,
49
+ Map <String , Set <ClassDetails >> directImplementorMap ,
46
50
ModelsContext context ) {
47
51
this .classDetailsMap = classDetailsMap ;
48
52
this .directSubTypeMap = directSubTypeMap ;
@@ -56,8 +60,17 @@ protected AbstractClassDetailsRegistry(
56
60
}
57
61
58
62
@ Override
59
- public List <ClassDetails > getDirectSubTypes (String superTypeName ) {
60
- return directSubTypeMap .get ( superTypeName );
63
+ public List <ClassDetails > getDirectSubTypes (String typeName ) {
64
+ final Set <ClassDetails > directSubtypes = getDirectSubtypes ( typeName );
65
+ return CollectionHelper .isNotEmpty ( directSubtypes )
66
+ ? new ArrayList <>( directSubtypes )
67
+ : List .of ();
68
+ }
69
+
70
+ @ Override
71
+ public Set <ClassDetails > getDirectSubtypes (String typeName ) {
72
+ final Set <ClassDetails > directSubtypes = directSubTypeMap .get ( typeName );
73
+ return directSubtypes != null ? directSubtypes : Set .of ();
61
74
}
62
75
63
76
@ Override
@@ -72,58 +85,81 @@ public void forEachDirectSubType(String superTypeName, ClassDetailsConsumer cons
72
85
}
73
86
74
87
@ Override
75
- public List <ClassDetails > getDirectImplementors (String interfaceName ) {
76
- return directImplementorMap .get ( interfaceName );
88
+ public Set <ClassDetails > getDirectImplementors (String interfaceName ) {
89
+ final Set <ClassDetails > implementors = directImplementorMap .get ( interfaceName );
90
+ return implementors != null ? implementors : Set .of ();
77
91
}
78
92
79
93
@ Override
80
94
public void forEachDirectImplementor (String interfaceName , ClassDetailsConsumer consumer ) {
81
- final List <ClassDetails > directImplementors = getDirectImplementors ( interfaceName );
95
+ final Set <ClassDetails > directImplementors = getDirectImplementors ( interfaceName );
82
96
if ( directImplementors != null ) {
83
97
directImplementors .forEach ( consumer ::consume );
84
98
}
85
99
}
86
100
87
101
@ Override
88
- public List <ClassDetails > findConcreteTypes (String base ) {
89
- final List <ClassDetails > result = new ArrayList <>();
102
+ public Set <ClassDetails > findConcreteTypes (String base , boolean includeBase ) {
103
+ final Set <ClassDetails > result = new LinkedHashSet <>();
104
+ walkImplementors ( base , includeBase , classDetails -> {
105
+ if ( !classDetails .isAbstract () && !classDetails .isInterface () ) {
106
+ result .add ( classDetails );
107
+ }
90
108
91
- forEachDirectSubType ( base , (subType ) -> {
92
- if ( !subType .isAbstract () ) {
93
- result .add ( subType );
109
+ });
110
+ return result ;
111
+ }
112
+
113
+ @ Override
114
+ public Set <ClassDetails > collectImplementors (String base , boolean includeBase , Predicate <ClassDetails > exclusions ) {
115
+ final Set <ClassDetails > result = new LinkedHashSet <>();
116
+ walkImplementors ( base , includeBase , classDetails -> {
117
+ if ( exclusions == null || !exclusions .test ( classDetails ) ) {
118
+ result .add ( classDetails );
94
119
}
95
- collectConcreteTypesFromClass ( subType , result ::add );
96
120
} );
121
+ return result ;
122
+ }
97
123
98
- forEachDirectImplementor ( base , (implementor ) -> {
99
- collectConcreteTypesFromInterfaceImplementor ( implementor , result ::add );
124
+ @ Override
125
+ public void walkImplementors (String base , boolean includeBase , ClassDetailsConsumer consumer ) {
126
+ if ( includeBase ) {
127
+ final ClassDetails baseDetails = resolveClassDetails ( base );
128
+ consumer .consume ( baseDetails );
129
+ }
130
+
131
+ forEachDirectSubType ( base , (subType ) -> {
132
+ consumer .consume ( subType );
133
+ walkSubtypes ( subType , consumer );
100
134
} );
101
135
102
- return result ;
136
+ forEachDirectImplementor ( base , (implementor ) -> {
137
+ consumer .consume ( implementor );
138
+ walkInterfaceImplementors ( implementor , consumer );
139
+ } );
103
140
}
104
141
105
- private void collectConcreteTypesFromClass (ClassDetails base , ClassDetailsConsumer collector ) {
142
+ private void walkSubtypes (ClassDetails base , ClassDetailsConsumer consumer ) {
106
143
forEachDirectSubType ( base .getName (), (subType ) -> {
107
- if ( !subType .isAbstract () ) {
108
- collector .consume ( subType );
109
- }
110
- collectConcreteTypesFromClass ( subType , collector );
144
+ consumer .consume ( subType );
145
+ walkSubtypes ( subType , consumer );
111
146
} );
112
147
}
113
148
114
- private void collectConcreteTypesFromInterfaceImplementor (ClassDetails implementor , ClassDetailsConsumer collector ) {
149
+ private void walkInterfaceImplementors (ClassDetails implementor , ClassDetailsConsumer consumer ) {
115
150
if ( implementor .isInterface () ) {
116
151
// the direct interface implementor is itself an interface...
117
152
forEachDirectImplementor ( implementor .getName (), (implementorImplementor ) -> {
118
- collectConcreteTypesFromInterfaceImplementor ( implementor , collector );
153
+ consumer .consume ( implementorImplementor );
154
+ walkInterfaceImplementors ( implementorImplementor , consumer );
119
155
} );
120
156
}
121
157
else {
122
158
// the direct interface implementor is itself a class...
123
- if ( ! implementor .isAbstract () ) {
124
- collector .consume ( implementor );
125
- }
126
- collectConcreteTypesFromClass ( implementor , collector );
159
+ forEachDirectSubType ( implementor .getName (), ( subtype ) -> {
160
+ consumer .consume ( subtype );
161
+ walkSubtypes ( subtype , consumer );
162
+ } );
127
163
}
128
164
}
129
165
@@ -180,10 +216,10 @@ public void addClassDetails(String name, ClassDetails classDetails) {
180
216
classDetailsMap .put ( name , classDetails );
181
217
182
218
if ( classDetails .getSuperClass () != null ) {
183
- List <ClassDetails > subTypes = directSubTypeMap .get ( classDetails .getSuperClass ().getName () );
219
+ Set <ClassDetails > subTypes = directSubTypeMap .get ( classDetails .getSuperClass ().getName () );
184
220
//noinspection Java8MapApi
185
221
if ( subTypes == null ) {
186
- subTypes = new ArrayList <>();
222
+ subTypes = new LinkedHashSet <>();
187
223
directSubTypeMap .put ( classDetails .getSuperClass ().getName (), subTypes );
188
224
}
189
225
subTypes .add ( classDetails );
@@ -192,9 +228,9 @@ public void addClassDetails(String name, ClassDetails classDetails) {
192
228
final List <TypeDetails > implementedInterfaces = classDetails .getImplementedInterfaces ();
193
229
if ( implementedInterfaces != null ) {
194
230
implementedInterfaces .forEach ( (implementedInterface ) -> {
195
- final List <ClassDetails > directImplementors = directImplementorMap .computeIfAbsent (
231
+ final Set <ClassDetails > directImplementors = directImplementorMap .computeIfAbsent (
196
232
implementedInterface .getName (),
197
- (interfaceName ) -> new ArrayList <>()
233
+ (interfaceName ) -> new LinkedHashSet <>()
198
234
);
199
235
directImplementors .add ( classDetails );
200
236
} );
@@ -244,7 +280,11 @@ public Map<String, ClassDetails> getClassDetailsMap() {
244
280
return Collections .unmodifiableMap ( classDetailsMap );
245
281
}
246
282
247
- public Map <String , List <ClassDetails >> getDirectSubTypeMap () {
283
+ public Map <String , Set <ClassDetails >> getDirectSubTypeMap () {
248
284
return Collections .unmodifiableMap ( directSubTypeMap );
249
285
}
286
+
287
+ public Map <String , Set <ClassDetails >> getDirectImplementorMap () {
288
+ return Collections .unmodifiableMap ( directImplementorMap );
289
+ }
250
290
}
0 commit comments