99import java .io .Serializable ;
1010import java .lang .reflect .Field ;
1111import java .util .ArrayList ;
12+ import java .util .Arrays ;
1213import java .util .Collection ;
1314import java .util .HashMap ;
1415import java .util .HashSet ;
7374import static org .hibernate .metamodel .internal .InjectionHelper .injectTypedQueryReference ;
7475
7576/**
76- *
7777 * @author Steve Ebersole
7878 */
7979public class JpaMetamodelImpl implements JpaMetamodelImplementor , Serializable {
@@ -106,7 +106,7 @@ private ImportInfo(String importedName, Class<T> loadedClass) {
106106 private final Map <Class <?>, String > entityProxyInterfaceMap = new HashMap <>();
107107
108108 private final Map <String , ImportInfo <?>> nameToImportMap = new ConcurrentHashMap <>();
109- private final Map <String ,Object > knownInvalidnameToImportMap = new ConcurrentHashMap <>();
109+ private final Map <String , Object > knownInvalidnameToImportMap = new ConcurrentHashMap <>();
110110
111111
112112 public JpaMetamodelImpl (
@@ -143,13 +143,14 @@ public JpaCompliance getJpaCompliance() {
143143 public <X > ManagedDomainType <X > managedType (String typeName ) {
144144 final ManagedDomainType <X > managedType = findManagedType ( typeName );
145145 if ( managedType == null ) {
146- throw new IllegalArgumentException ("Not a managed type: " + typeName );
146+ throw new IllegalArgumentException ( "Not a managed type: " + typeName );
147147 }
148148 return managedType ;
149149 }
150150
151151 @ Override
152- @ Nullable public EntityDomainType <?> findEntityType (@ Nullable String entityName ) {
152+ @ Nullable
153+ public EntityDomainType <?> findEntityType (@ Nullable String entityName ) {
153154 if ( entityName == null ) {
154155 return null ;
155156 }
@@ -162,18 +163,19 @@ public EntityDomainType<?> entity(String entityName) {
162163 final EntityDomainType <?> entityType = findEntityType ( entityName );
163164 if ( entityType == null ) {
164165 // per JPA
165- throw new IllegalArgumentException ("Not an entity: " + entityName );
166+ throw new IllegalArgumentException ( "Not an entity: " + entityName );
166167 }
167168 return entityType ;
168169 }
169170
170171 @ Override
171- @ Nullable public EmbeddableDomainType <?> findEmbeddableType (@ Nullable String embeddableName ) {
172+ @ Nullable
173+ public EmbeddableDomainType <?> findEmbeddableType (@ Nullable String embeddableName ) {
172174 if ( embeddableName == null ) {
173175 return null ;
174176 }
175177 final ManagedDomainType <?> managedType = managedTypeByName .get ( embeddableName );
176- if ( !( managedType instanceof EmbeddableDomainType <?> embeddableDomainType ) ) {
178+ if ( !(managedType instanceof EmbeddableDomainType <?> embeddableDomainType ) ) {
177179 return null ;
178180 }
179181 return embeddableDomainType ;
@@ -183,7 +185,7 @@ public EntityDomainType<?> entity(String entityName) {
183185 public EmbeddableDomainType <?> embeddable (String embeddableName ) {
184186 final EmbeddableDomainType <?> embeddableType = findEmbeddableType ( embeddableName );
185187 if ( embeddableType == null ) {
186- throw new IllegalArgumentException ("Not an embeddable: " + embeddableName );
188+ throw new IllegalArgumentException ( "Not an embeddable: " + embeddableName );
187189 }
188190 return embeddableType ;
189191 }
@@ -226,7 +228,8 @@ public <X> EntityDomainType<X> resolveHqlEntityReference(String entityName) {
226228 }
227229
228230 @ Override
229- @ Nullable public <X > ManagedDomainType <X > findManagedType (Class <X > cls ) {
231+ @ Nullable
232+ public <X > ManagedDomainType <X > findManagedType (Class <X > cls ) {
230233 //noinspection unchecked
231234 return (ManagedDomainType <X >) managedTypeByClass .get ( cls );
232235 }
@@ -242,9 +245,10 @@ public <X> ManagedDomainType<X> managedType(Class<X> cls) {
242245 }
243246
244247 @ Override
245- @ Nullable public <X > EntityDomainType <X > findEntityType (Class <X > cls ) {
248+ @ Nullable
249+ public <X > EntityDomainType <X > findEntityType (Class <X > cls ) {
246250 final ManagedType <?> type = managedTypeByClass .get ( cls );
247- if ( !( type instanceof EntityDomainType <?> ) ) {
251+ if ( !(type instanceof EntityDomainType <?>) ) {
248252 return null ;
249253 }
250254 //noinspection unchecked
@@ -263,7 +267,7 @@ public <X> EntityDomainType<X> entity(Class<X> cls) {
263267 @ Override
264268 public @ Nullable <X > EmbeddableDomainType <X > findEmbeddableType (Class <X > cls ) {
265269 final ManagedType <?> type = managedTypeByClass .get ( cls );
266- if ( !( type instanceof EmbeddableDomainType <?> ) ) {
270+ if ( !(type instanceof EmbeddableDomainType <?>) ) {
267271 return null ;
268272 }
269273 //noinspection unchecked
@@ -281,7 +285,7 @@ public <X> EmbeddableDomainType<X> embeddable(Class<X> cls) {
281285
282286 private Collection <ManagedDomainType <?>> getAllManagedTypes () {
283287 // should never happen
284- return switch (jpaMetaModelPopulationSetting ) {
288+ return switch ( jpaMetaModelPopulationSetting ) {
285289 case IGNORE_UNSUPPORTED -> managedTypeByClass .values ();
286290 case ENABLED -> managedTypeByName .values ();
287291 case DISABLED -> emptySet ();
@@ -311,7 +315,7 @@ public Set<EmbeddableType<?>> getEmbeddables() {
311315
312316 @ Override
313317 public @ Nullable Set <String > getEnumTypesForValue (String enumValue ) {
314- return allowedEnumLiteralsToEnumTypeNames .get ( enumValue );
318+ return allowedEnumLiteralsToEnumTypeNames .get ( enumValue );
315319 }
316320
317321 @ Override
@@ -388,7 +392,8 @@ public <T> void addNamedEntityGraph(String graphName, RootGraphImplementor<T> en
388392 }
389393 }
390394
391- @ Override @ SuppressWarnings ("unchecked" )
395+ @ Override
396+ @ SuppressWarnings ("unchecked" )
392397 public <T > RootGraphImplementor <T > findEntityGraphByName (String name ) {
393398 return (RootGraphImplementor <T >) entityGraphMap .get ( name );
394399 }
@@ -490,21 +495,54 @@ private void applyNamedEntityGraphs(Collection<NamedEntityGraphDefinition> named
490495 if ( entityType == null ) {
491496 throw new IllegalArgumentException (
492497 "Attempted to register named entity graph [" + definition .getRegisteredName ()
493- + "] for unknown entity [" + definition .getEntityName () + "]"
498+ + "] for unknown entity [" + definition .getEntityName () + "]"
494499
495500 );
496501 }
502+
497503 final NamedEntityGraph namedEntityGraph = definition .getAnnotation ();
498504 final RootGraphImpl <?> entityGraph =
499- createRootGraph ( definition .getRegisteredName (), entityType ,
500- namedEntityGraph .includeAllAttributes () );
501- if ( namedEntityGraph .attributeNodes () != null ) {
502- applyNamedAttributeNodes ( namedEntityGraph .attributeNodes (), namedEntityGraph , entityGraph );
503- }
505+ createEntityGraph (
506+ namedEntityGraph ,
507+ definition .getRegisteredName (),
508+ entityType ,
509+ namedEntityGraph .includeAllAttributes ()
510+ );
511+
504512 entityGraphMap .put ( definition .getRegisteredName (), entityGraph );
505513 }
506514 }
507515
516+ private <T > RootGraphImpl <T > createEntityGraph (
517+ NamedEntityGraph namedEntityGraph ,
518+ String registeredName ,
519+ EntityDomainType <T > entityType ,
520+ boolean includeAllAttributes ) {
521+ final RootGraphImpl <T > entityGraph =
522+ createRootGraph ( registeredName , entityType , includeAllAttributes );
523+
524+ if ( namedEntityGraph .subclassSubgraphs () != null ) {
525+ Arrays
526+ .stream ( namedEntityGraph .subclassSubgraphs () )
527+ .forEach ( subclassSubgraph -> {
528+ GraphImplementor <?> subgraph = (GraphImplementor <?>) entityGraph .addTreatedSubgraph (
529+ (Class ) subclassSubgraph .type () );
530+
531+ applyNamedAttributeNodes (
532+ subclassSubgraph .attributeNodes (),
533+ namedEntityGraph ,
534+ subgraph
535+ );
536+ } );
537+ }
538+
539+ if ( namedEntityGraph .attributeNodes () != null ) {
540+ applyNamedAttributeNodes ( namedEntityGraph .attributeNodes (), namedEntityGraph , entityGraph );
541+ }
542+
543+ return entityGraph ;
544+ }
545+
508546 private static <T > RootGraphImpl <T > createRootGraph (
509547 String name , EntityDomainType <T > entityType , boolean includeAllAttributes ) {
510548 final RootGraphImpl <T > entityGraph = new RootGraphImpl <>( name , entityType );
@@ -521,31 +559,41 @@ private void applyNamedAttributeNodes(
521559 NamedEntityGraph namedEntityGraph ,
522560 GraphImplementor <?> graphNode ) {
523561 for ( NamedAttributeNode namedAttributeNode : namedAttributeNodes ) {
524- final AttributeNodeImplementor <?> attributeNode =
525- graphNode .findOrCreateAttributeNode ( namedAttributeNode .value () );
562+ final String value = namedAttributeNode .value ();
563+ final AttributeNodeImplementor <?> attributeNode = (AttributeNodeImplementor <?>) graphNode .addAttributeNode ( value );
564+
526565 if ( isNotEmpty ( namedAttributeNode .subgraph () ) ) {
527566 applyNamedSubgraphs (
528567 namedEntityGraph ,
529568 namedAttributeNode .subgraph (),
530- attributeNode .makeSubGraph ()
569+ attributeNode ,
570+ false
531571 );
532572 }
533573 if ( isNotEmpty ( namedAttributeNode .keySubgraph () ) ) {
534574 applyNamedSubgraphs (
535575 namedEntityGraph ,
536576 namedAttributeNode .keySubgraph (),
537- attributeNode .makeKeySubGraph ()
577+ attributeNode ,
578+ true
538579 );
539580 }
540581 }
541582 }
542583
543- private void applyNamedSubgraphs (
584+ @ SuppressWarnings ({"unchecked" , "rawtypes" })
585+ private <T > void applyNamedSubgraphs (
544586 NamedEntityGraph namedEntityGraph ,
545587 String subgraphName ,
546- SubGraphImplementor <?> subgraph ) {
588+ AttributeNodeImplementor < T > attributeNode , Boolean isKeySubGraph ) {
547589 for ( NamedSubgraph namedSubgraph : namedEntityGraph .subgraphs () ) {
548590 if ( subgraphName .equals ( namedSubgraph .name () ) ) {
591+ var isDefaultSubgraphType = namedSubgraph .type ().equals ( void .class );
592+ Class subGraphType = isDefaultSubgraphType ? null : namedSubgraph .type ();
593+
594+ final SubGraphImplementor <?> subgraph = makeAttributeNodeSubgraph ( attributeNode , isKeySubGraph ,
595+ subGraphType );
596+
549597 applyNamedAttributeNodes (
550598 namedSubgraph .attributeNodes (),
551599 namedEntityGraph ,
@@ -555,6 +603,18 @@ private void applyNamedSubgraphs(
555603 }
556604 }
557605
606+ private static <T > SubGraphImplementor <?> makeAttributeNodeSubgraph (AttributeNodeImplementor <T > attributeNode , Boolean isKeySubGraph , Class <T > subGraphType ) {
607+
608+ if ( isKeySubGraph ) {
609+ return subGraphType != null ? attributeNode .makeKeySubGraph ( subGraphType )
610+ : attributeNode .makeKeySubGraph ();
611+ }
612+
613+ return subGraphType != null ?
614+ attributeNode .makeSubGraph ( subGraphType ) :
615+ attributeNode .makeSubGraph ();
616+ }
617+
558618 private <X > Class <X > resolveRequestedClass (String entityName ) {
559619 try {
560620 return getServiceRegistry ().requireService ( ClassLoaderService .class )
@@ -609,8 +669,8 @@ public <T> EntityDomainType<T> resolveEntityReference(Class<T> javaType) {
609669 // incorrect results
610670 final ManagedDomainType <?> superType = managedType .getSuperType ();
611671 if ( superType != null
612- && superType .getPersistenceType () == Type .PersistenceType .ENTITY
613- && javaType .isAssignableFrom ( superType .getJavaType () ) ) {
672+ && superType .getPersistenceType () == Type .PersistenceType .ENTITY
673+ && javaType .isAssignableFrom ( superType .getJavaType () ) ) {
614674 continue ;
615675 }
616676
@@ -631,7 +691,8 @@ public <T> EntityDomainType<T> resolveEntityReference(Class<T> javaType) {
631691 }
632692 }
633693
634- throw new EntityTypeException ( "Could not resolve entity class '" + javaType .getName () + "'" , javaType .getName () );
694+ throw new EntityTypeException ( "Could not resolve entity class '" + javaType .getName () + "'" ,
695+ javaType .getName () );
635696 }
636697
637698 @ Override
@@ -719,7 +780,7 @@ private void populateStaticMetamodel(MetadataImplementor bootMetamodel, Metadata
719780 -> injectTypedQueryReference ( definition , namedQueryMetamodelClass ( definition , context ) ) );
720781 bootMetamodel .visitNamedNativeQueryDefinitions ( definition
721782 -> injectTypedQueryReference ( definition , namedQueryMetamodelClass ( definition , context ) ) );
722- bootMetamodel .getNamedEntityGraphs ().values ().forEach (definition
783+ bootMetamodel .getNamedEntityGraphs ().values ().forEach ( definition
723784 -> injectEntityGraph ( definition , graphMetamodelClass ( definition , context ), this ) );
724785 }
725786
0 commit comments