13
13
import org .hibernate .models .UnknownClassException ;
14
14
import org .hibernate .models .spi .ClassDetails ;
15
15
import org .hibernate .models .spi .ModelsContext ;
16
+ import org .hibernate .models .spi .TypeDetails ;
16
17
17
18
import static org .hibernate .models .spi .ClassDetails .CLASS_CLASS_DETAILS ;
18
19
import static org .hibernate .models .spi .ClassDetails .OBJECT_CLASS_DETAILS ;
@@ -30,18 +31,22 @@ public abstract class AbstractClassDetailsRegistry implements MutableClassDetail
30
31
protected final Map <String , ClassDetails > classDetailsMap ;
31
32
32
33
// subtype per type
33
- protected final Map <String , List <ClassDetails >> subTypeClassDetailsMap ;
34
+ protected final Map <String , List <ClassDetails >> directSubTypeMap ;
35
+ // implementor by interface
36
+ protected final Map <String , List <ClassDetails >> directImplementorMap ;
34
37
35
38
protected AbstractClassDetailsRegistry (ModelsContext context ) {
36
- this ( new ConcurrentHashMap <>(), new ConcurrentHashMap <>(), context );
39
+ this ( new ConcurrentHashMap <>(), new ConcurrentHashMap <>(), new ConcurrentHashMap <>(), context );
37
40
}
38
41
39
42
protected AbstractClassDetailsRegistry (
40
43
Map <String , ClassDetails > classDetailsMap ,
41
- Map <String , List <ClassDetails >> subTypeClassDetailsMap ,
44
+ Map <String , List <ClassDetails >> directSubTypeMap ,
45
+ Map <String , List <ClassDetails >> directImplementorMap ,
42
46
ModelsContext context ) {
43
47
this .classDetailsMap = classDetailsMap ;
44
- this .subTypeClassDetailsMap = subTypeClassDetailsMap ;
48
+ this .directSubTypeMap = directSubTypeMap ;
49
+ this .directImplementorMap = directImplementorMap ;
45
50
this .context = context ;
46
51
47
52
classDetailsMap .put ( CLASS_CLASS_DETAILS .getName (), CLASS_CLASS_DETAILS );
@@ -52,7 +57,7 @@ protected AbstractClassDetailsRegistry(
52
57
53
58
@ Override
54
59
public List <ClassDetails > getDirectSubTypes (String superTypeName ) {
55
- return subTypeClassDetailsMap .get ( superTypeName );
60
+ return directSubTypeMap .get ( superTypeName );
56
61
}
57
62
58
63
@ Override
@@ -66,6 +71,62 @@ public void forEachDirectSubType(String superTypeName, ClassDetailsConsumer cons
66
71
}
67
72
}
68
73
74
+ @ Override
75
+ public List <ClassDetails > getDirectImplementors (String interfaceName ) {
76
+ return directImplementorMap .get ( interfaceName );
77
+ }
78
+
79
+ @ Override
80
+ public void forEachDirectImplementor (String interfaceName , ClassDetailsConsumer consumer ) {
81
+ final List <ClassDetails > directImplementors = getDirectImplementors ( interfaceName );
82
+ if ( directImplementors != null ) {
83
+ directImplementors .forEach ( consumer ::consume );
84
+ }
85
+ }
86
+
87
+ @ Override
88
+ public List <ClassDetails > findConcreteTypes (String base ) {
89
+ final List <ClassDetails > result = new ArrayList <>();
90
+
91
+ forEachDirectSubType ( base , (subType ) -> {
92
+ if ( !subType .isAbstract () ) {
93
+ result .add ( subType );
94
+ }
95
+ collectConcreteTypesFromClass ( subType , result ::add );
96
+ } );
97
+
98
+ forEachDirectImplementor ( base , (implementor ) -> {
99
+ collectConcreteTypesFromInterfaceImplementor ( implementor , result ::add );
100
+ } );
101
+
102
+ return result ;
103
+ }
104
+
105
+ private void collectConcreteTypesFromClass (ClassDetails base , ClassDetailsConsumer collector ) {
106
+ forEachDirectSubType ( base .getName (), (subType ) -> {
107
+ if ( !subType .isAbstract () ) {
108
+ collector .consume ( subType );
109
+ }
110
+ collectConcreteTypesFromClass ( subType , collector );
111
+ } );
112
+ }
113
+
114
+ private void collectConcreteTypesFromInterfaceImplementor (ClassDetails implementor , ClassDetailsConsumer collector ) {
115
+ if ( implementor .isInterface () ) {
116
+ // the direct interface implementor is itself an interface...
117
+ forEachDirectImplementor ( implementor .getName (), (implementorImplementor ) -> {
118
+ collectConcreteTypesFromInterfaceImplementor ( implementor , collector );
119
+ } );
120
+ }
121
+ else {
122
+ // the direct interface implementor is itself a class...
123
+ if ( !implementor .isAbstract () ) {
124
+ collector .consume ( implementor );
125
+ }
126
+ collectConcreteTypesFromClass ( implementor , collector );
127
+ }
128
+ }
129
+
69
130
@ Override
70
131
public ClassDetails findClassDetails (String name ) {
71
132
return classDetailsMap .get ( name );
@@ -119,14 +180,25 @@ public void addClassDetails(String name, ClassDetails classDetails) {
119
180
classDetailsMap .put ( name , classDetails );
120
181
121
182
if ( classDetails .getSuperClass () != null ) {
122
- List <ClassDetails > subTypes = subTypeClassDetailsMap .get ( classDetails .getSuperClass ().getName () );
183
+ List <ClassDetails > subTypes = directSubTypeMap .get ( classDetails .getSuperClass ().getName () );
123
184
//noinspection Java8MapApi
124
185
if ( subTypes == null ) {
125
186
subTypes = new ArrayList <>();
126
- subTypeClassDetailsMap .put ( classDetails .getSuperClass ().getName (), subTypes );
187
+ directSubTypeMap .put ( classDetails .getSuperClass ().getName (), subTypes );
127
188
}
128
189
subTypes .add ( classDetails );
129
190
}
191
+
192
+ final List <TypeDetails > implementedInterfaces = classDetails .getImplementedInterfaces ();
193
+ if ( implementedInterfaces != null ) {
194
+ implementedInterfaces .forEach ( (implementedInterface ) -> {
195
+ final List <ClassDetails > directImplementors = directImplementorMap .computeIfAbsent (
196
+ implementedInterface .getName (),
197
+ (interfaceName ) -> new ArrayList <>()
198
+ );
199
+ directImplementors .add ( classDetails );
200
+ } );
201
+ }
130
202
}
131
203
132
204
@ Override
@@ -172,7 +244,7 @@ public Map<String, ClassDetails> getClassDetailsMap() {
172
244
return Collections .unmodifiableMap ( classDetailsMap );
173
245
}
174
246
175
- public Map <String , List <ClassDetails >> getSubTypeClassDetailsMap () {
176
- return Collections .unmodifiableMap ( subTypeClassDetailsMap );
247
+ public Map <String , List <ClassDetails >> getDirectSubTypeMap () {
248
+ return Collections .unmodifiableMap ( directSubTypeMap );
177
249
}
178
250
}
0 commit comments