66
77import java .util .ArrayList ;
88import java .util .Collections ;
9+ import java .util .LinkedHashSet ;
910import java .util .List ;
1011import java .util .Map ;
12+ import java .util .Set ;
1113import java .util .concurrent .ConcurrentHashMap ;
14+ import java .util .function .Predicate ;
1215
1316import org .hibernate .models .UnknownClassException ;
17+ import org .hibernate .models .internal .util .CollectionHelper ;
1418import org .hibernate .models .spi .ClassDetails ;
1519import org .hibernate .models .spi .ModelsContext ;
1620import org .hibernate .models .spi .TypeDetails ;
@@ -31,18 +35,18 @@ public abstract class AbstractClassDetailsRegistry implements MutableClassDetail
3135 protected final Map <String , ClassDetails > classDetailsMap ;
3236
3337 // subtype per type
34- protected final Map <String , List <ClassDetails >> directSubTypeMap ;
38+ protected final Map <String , Set <ClassDetails >> directSubTypeMap ;
3539 // implementor by interface
36- protected final Map <String , List <ClassDetails >> directImplementorMap ;
40+ protected final Map <String , Set <ClassDetails >> directImplementorMap ;
3741
3842 protected AbstractClassDetailsRegistry (ModelsContext context ) {
3943 this ( new ConcurrentHashMap <>(), new ConcurrentHashMap <>(), new ConcurrentHashMap <>(), context );
4044 }
4145
4246 protected AbstractClassDetailsRegistry (
4347 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 ,
4650 ModelsContext context ) {
4751 this .classDetailsMap = classDetailsMap ;
4852 this .directSubTypeMap = directSubTypeMap ;
@@ -56,8 +60,17 @@ protected AbstractClassDetailsRegistry(
5660 }
5761
5862 @ 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 ();
6174 }
6275
6376 @ Override
@@ -72,58 +85,81 @@ public void forEachDirectSubType(String superTypeName, ClassDetailsConsumer cons
7285 }
7386
7487 @ 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 ();
7791 }
7892
7993 @ Override
8094 public void forEachDirectImplementor (String interfaceName , ClassDetailsConsumer consumer ) {
81- final List <ClassDetails > directImplementors = getDirectImplementors ( interfaceName );
95+ final Set <ClassDetails > directImplementors = getDirectImplementors ( interfaceName );
8296 if ( directImplementors != null ) {
8397 directImplementors .forEach ( consumer ::consume );
8498 }
8599 }
86100
87101 @ 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+ }
90108
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 );
94119 }
95- collectConcreteTypesFromClass ( subType , result ::add );
96120 } );
121+ return result ;
122+ }
97123
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 );
100134 } );
101135
102- return result ;
136+ forEachDirectImplementor ( base , (implementor ) -> {
137+ consumer .consume ( implementor );
138+ walkInterfaceImplementors ( implementor , consumer );
139+ } );
103140 }
104141
105- private void collectConcreteTypesFromClass (ClassDetails base , ClassDetailsConsumer collector ) {
142+ private void walkSubtypes (ClassDetails base , ClassDetailsConsumer consumer ) {
106143 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 );
111146 } );
112147 }
113148
114- private void collectConcreteTypesFromInterfaceImplementor (ClassDetails implementor , ClassDetailsConsumer collector ) {
149+ private void walkInterfaceImplementors (ClassDetails implementor , ClassDetailsConsumer consumer ) {
115150 if ( implementor .isInterface () ) {
116151 // the direct interface implementor is itself an interface...
117152 forEachDirectImplementor ( implementor .getName (), (implementorImplementor ) -> {
118- collectConcreteTypesFromInterfaceImplementor ( implementor , collector );
153+ consumer .consume ( implementorImplementor );
154+ walkInterfaceImplementors ( implementorImplementor , consumer );
119155 } );
120156 }
121157 else {
122158 // 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+ } );
127163 }
128164 }
129165
@@ -180,10 +216,10 @@ public void addClassDetails(String name, ClassDetails classDetails) {
180216 classDetailsMap .put ( name , classDetails );
181217
182218 if ( classDetails .getSuperClass () != null ) {
183- List <ClassDetails > subTypes = directSubTypeMap .get ( classDetails .getSuperClass ().getName () );
219+ Set <ClassDetails > subTypes = directSubTypeMap .get ( classDetails .getSuperClass ().getName () );
184220 //noinspection Java8MapApi
185221 if ( subTypes == null ) {
186- subTypes = new ArrayList <>();
222+ subTypes = new LinkedHashSet <>();
187223 directSubTypeMap .put ( classDetails .getSuperClass ().getName (), subTypes );
188224 }
189225 subTypes .add ( classDetails );
@@ -192,9 +228,9 @@ public void addClassDetails(String name, ClassDetails classDetails) {
192228 final List <TypeDetails > implementedInterfaces = classDetails .getImplementedInterfaces ();
193229 if ( implementedInterfaces != null ) {
194230 implementedInterfaces .forEach ( (implementedInterface ) -> {
195- final List <ClassDetails > directImplementors = directImplementorMap .computeIfAbsent (
231+ final Set <ClassDetails > directImplementors = directImplementorMap .computeIfAbsent (
196232 implementedInterface .getName (),
197- (interfaceName ) -> new ArrayList <>()
233+ (interfaceName ) -> new LinkedHashSet <>()
198234 );
199235 directImplementors .add ( classDetails );
200236 } );
@@ -244,7 +280,11 @@ public Map<String, ClassDetails> getClassDetailsMap() {
244280 return Collections .unmodifiableMap ( classDetailsMap );
245281 }
246282
247- public Map <String , List <ClassDetails >> getDirectSubTypeMap () {
283+ public Map <String , Set <ClassDetails >> getDirectSubTypeMap () {
248284 return Collections .unmodifiableMap ( directSubTypeMap );
249285 }
286+
287+ public Map <String , Set <ClassDetails >> getDirectImplementorMap () {
288+ return Collections .unmodifiableMap ( directImplementorMap );
289+ }
250290}
0 commit comments