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 ;
20
+ import org .hibernate .models .spi .TypeDetails ;
16
21
17
22
import static org .hibernate .models .spi .ClassDetails .CLASS_CLASS_DETAILS ;
18
23
import static org .hibernate .models .spi .ClassDetails .OBJECT_CLASS_DETAILS ;
@@ -30,18 +35,22 @@ public abstract class AbstractClassDetailsRegistry implements MutableClassDetail
30
35
protected final Map <String , ClassDetails > classDetailsMap ;
31
36
32
37
// subtype per type
33
- protected final Map <String , List <ClassDetails >> subTypeClassDetailsMap ;
38
+ protected final Map <String , Set <ClassDetails >> directSubTypeMap ;
39
+ // implementor by interface
40
+ protected final Map <String , Set <ClassDetails >> directImplementorMap ;
34
41
35
42
protected AbstractClassDetailsRegistry (ModelsContext context ) {
36
- this ( new ConcurrentHashMap <>(), new ConcurrentHashMap <>(), context );
43
+ this ( new ConcurrentHashMap <>(), new ConcurrentHashMap <>(), new ConcurrentHashMap <>(), context );
37
44
}
38
45
39
46
protected AbstractClassDetailsRegistry (
40
47
Map <String , ClassDetails > classDetailsMap ,
41
- Map <String , List <ClassDetails >> subTypeClassDetailsMap ,
48
+ Map <String , Set <ClassDetails >> directSubTypeMap ,
49
+ Map <String , Set <ClassDetails >> directImplementorMap ,
42
50
ModelsContext context ) {
43
51
this .classDetailsMap = classDetailsMap ;
44
- this .subTypeClassDetailsMap = subTypeClassDetailsMap ;
52
+ this .directSubTypeMap = directSubTypeMap ;
53
+ this .directImplementorMap = directImplementorMap ;
45
54
this .context = context ;
46
55
47
56
classDetailsMap .put ( CLASS_CLASS_DETAILS .getName (), CLASS_CLASS_DETAILS );
@@ -51,13 +60,22 @@ protected AbstractClassDetailsRegistry(
51
60
}
52
61
53
62
@ Override
54
- public List <ClassDetails > getDirectSubTypes (String superTypeName ) {
55
- return subTypeClassDetailsMap .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 ();
56
68
}
57
69
58
70
@ Override
59
- public void forEachDirectSubType (String superTypeName , ClassDetailsConsumer consumer ) {
60
- final List <ClassDetails > directSubTypes = getDirectSubTypes ( superTypeName );
71
+ public Set <ClassDetails > getDirectSubtypes (String typeName ) {
72
+ final Set <ClassDetails > directSubtypes = directSubTypeMap .get ( typeName );
73
+ return directSubtypes != null ? directSubtypes : Set .of ();
74
+ }
75
+
76
+ @ Override
77
+ public void forEachDirectSubtype (String typeName , ClassDetailsConsumer consumer ) {
78
+ final List <ClassDetails > directSubTypes = getDirectSubTypes ( typeName );
61
79
if ( directSubTypes == null ) {
62
80
return ;
63
81
}
@@ -66,6 +84,85 @@ public void forEachDirectSubType(String superTypeName, ClassDetailsConsumer cons
66
84
}
67
85
}
68
86
87
+ @ Override
88
+ public Set <ClassDetails > getDirectImplementors (String interfaceName ) {
89
+ final Set <ClassDetails > implementors = directImplementorMap .get ( interfaceName );
90
+ return implementors != null ? implementors : Set .of ();
91
+ }
92
+
93
+ @ Override
94
+ public void forEachDirectImplementor (String interfaceName , ClassDetailsConsumer consumer ) {
95
+ final Set <ClassDetails > directImplementors = getDirectImplementors ( interfaceName );
96
+ if ( directImplementors != null ) {
97
+ directImplementors .forEach ( consumer ::consume );
98
+ }
99
+ }
100
+
101
+ @ Override
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
+ }
108
+
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 );
119
+ }
120
+ } );
121
+ return result ;
122
+ }
123
+
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 );
134
+ } );
135
+
136
+ forEachDirectImplementor ( base , (implementor ) -> {
137
+ consumer .consume ( implementor );
138
+ walkInterfaceImplementors ( implementor , consumer );
139
+ } );
140
+ }
141
+
142
+ private void walkSubtypes (ClassDetails base , ClassDetailsConsumer consumer ) {
143
+ forEachDirectSubtype ( base .getName (), (subType ) -> {
144
+ consumer .consume ( subType );
145
+ walkSubtypes ( subType , consumer );
146
+ } );
147
+ }
148
+
149
+ private void walkInterfaceImplementors (ClassDetails implementor , ClassDetailsConsumer consumer ) {
150
+ if ( implementor .isInterface () ) {
151
+ // the direct interface implementor is itself an interface...
152
+ forEachDirectImplementor ( implementor .getName (), (implementorImplementor ) -> {
153
+ consumer .consume ( implementorImplementor );
154
+ walkInterfaceImplementors ( implementorImplementor , consumer );
155
+ } );
156
+ }
157
+ else {
158
+ // the direct interface implementor is itself a class...
159
+ forEachDirectSubtype ( implementor .getName (), (subtype ) -> {
160
+ consumer .consume ( subtype );
161
+ walkSubtypes ( subtype , consumer );
162
+ } );
163
+ }
164
+ }
165
+
69
166
@ Override
70
167
public ClassDetails findClassDetails (String name ) {
71
168
return classDetailsMap .get ( name );
@@ -119,14 +216,25 @@ public void addClassDetails(String name, ClassDetails classDetails) {
119
216
classDetailsMap .put ( name , classDetails );
120
217
121
218
if ( classDetails .getSuperClass () != null ) {
122
- List <ClassDetails > subTypes = subTypeClassDetailsMap .get ( classDetails .getSuperClass ().getName () );
219
+ Set <ClassDetails > subTypes = directSubTypeMap .get ( classDetails .getSuperClass ().getName () );
123
220
//noinspection Java8MapApi
124
221
if ( subTypes == null ) {
125
- subTypes = new ArrayList <>();
126
- subTypeClassDetailsMap .put ( classDetails .getSuperClass ().getName (), subTypes );
222
+ subTypes = new LinkedHashSet <>();
223
+ directSubTypeMap .put ( classDetails .getSuperClass ().getName (), subTypes );
127
224
}
128
225
subTypes .add ( classDetails );
129
226
}
227
+
228
+ final List <TypeDetails > implementedInterfaces = classDetails .getImplementedInterfaces ();
229
+ if ( implementedInterfaces != null ) {
230
+ implementedInterfaces .forEach ( (implementedInterface ) -> {
231
+ final Set <ClassDetails > directImplementors = directImplementorMap .computeIfAbsent (
232
+ implementedInterface .getName (),
233
+ (interfaceName ) -> new LinkedHashSet <>()
234
+ );
235
+ directImplementors .add ( classDetails );
236
+ } );
237
+ }
130
238
}
131
239
132
240
@ Override
@@ -172,7 +280,11 @@ public Map<String, ClassDetails> getClassDetailsMap() {
172
280
return Collections .unmodifiableMap ( classDetailsMap );
173
281
}
174
282
175
- public Map <String , List <ClassDetails >> getSubTypeClassDetailsMap () {
176
- return Collections .unmodifiableMap ( subTypeClassDetailsMap );
283
+ public Map <String , Set <ClassDetails >> getDirectSubTypeMap () {
284
+ return Collections .unmodifiableMap ( directSubTypeMap );
285
+ }
286
+
287
+ public Map <String , Set <ClassDetails >> getDirectImplementorMap () {
288
+ return Collections .unmodifiableMap ( directImplementorMap );
177
289
}
178
290
}
0 commit comments