1313import org .hibernate .models .UnknownClassException ;
1414import org .hibernate .models .spi .ClassDetails ;
1515import org .hibernate .models .spi .ModelsContext ;
16+ import org .hibernate .models .spi .TypeDetails ;
1617
1718import static org .hibernate .models .spi .ClassDetails .CLASS_CLASS_DETAILS ;
1819import static org .hibernate .models .spi .ClassDetails .OBJECT_CLASS_DETAILS ;
@@ -30,18 +31,22 @@ public abstract class AbstractClassDetailsRegistry implements MutableClassDetail
3031 protected final Map <String , ClassDetails > classDetailsMap ;
3132
3233 // 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 ;
3437
3538 protected AbstractClassDetailsRegistry (ModelsContext context ) {
36- this ( new ConcurrentHashMap <>(), new ConcurrentHashMap <>(), context );
39+ this ( new ConcurrentHashMap <>(), new ConcurrentHashMap <>(), new ConcurrentHashMap <>(), context );
3740 }
3841
3942 protected AbstractClassDetailsRegistry (
4043 Map <String , ClassDetails > classDetailsMap ,
41- Map <String , List <ClassDetails >> subTypeClassDetailsMap ,
44+ Map <String , List <ClassDetails >> directSubTypeMap ,
45+ Map <String , List <ClassDetails >> directImplementorMap ,
4246 ModelsContext context ) {
4347 this .classDetailsMap = classDetailsMap ;
44- this .subTypeClassDetailsMap = subTypeClassDetailsMap ;
48+ this .directSubTypeMap = directSubTypeMap ;
49+ this .directImplementorMap = directImplementorMap ;
4550 this .context = context ;
4651
4752 classDetailsMap .put ( CLASS_CLASS_DETAILS .getName (), CLASS_CLASS_DETAILS );
@@ -52,7 +57,7 @@ protected AbstractClassDetailsRegistry(
5257
5358 @ Override
5459 public List <ClassDetails > getDirectSubTypes (String superTypeName ) {
55- return subTypeClassDetailsMap .get ( superTypeName );
60+ return directSubTypeMap .get ( superTypeName );
5661 }
5762
5863 @ Override
@@ -66,6 +71,62 @@ public void forEachDirectSubType(String superTypeName, ClassDetailsConsumer cons
6671 }
6772 }
6873
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+
69130 @ Override
70131 public ClassDetails findClassDetails (String name ) {
71132 return classDetailsMap .get ( name );
@@ -119,14 +180,25 @@ public void addClassDetails(String name, ClassDetails classDetails) {
119180 classDetailsMap .put ( name , classDetails );
120181
121182 if ( classDetails .getSuperClass () != null ) {
122- List <ClassDetails > subTypes = subTypeClassDetailsMap .get ( classDetails .getSuperClass ().getName () );
183+ List <ClassDetails > subTypes = directSubTypeMap .get ( classDetails .getSuperClass ().getName () );
123184 //noinspection Java8MapApi
124185 if ( subTypes == null ) {
125186 subTypes = new ArrayList <>();
126- subTypeClassDetailsMap .put ( classDetails .getSuperClass ().getName (), subTypes );
187+ directSubTypeMap .put ( classDetails .getSuperClass ().getName (), subTypes );
127188 }
128189 subTypes .add ( classDetails );
129190 }
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+ }
130202 }
131203
132204 @ Override
@@ -172,7 +244,7 @@ public Map<String, ClassDetails> getClassDetailsMap() {
172244 return Collections .unmodifiableMap ( classDetailsMap );
173245 }
174246
175- public Map <String , List <ClassDetails >> getSubTypeClassDetailsMap () {
176- return Collections .unmodifiableMap ( subTypeClassDetailsMap );
247+ public Map <String , List <ClassDetails >> getDirectSubTypeMap () {
248+ return Collections .unmodifiableMap ( directSubTypeMap );
177249 }
178250}
0 commit comments