2323import org .hibernate .metamodel .model .domain .ManagedDomainType ;
2424import org .hibernate .metamodel .model .domain .MapPersistentAttribute ;
2525import org .hibernate .metamodel .model .domain .PersistentAttribute ;
26+ import org .hibernate .metamodel .model .domain .PluralPersistentAttribute ;
2627import org .hibernate .query .sqm .SqmPathSource ;
2728
2829import jakarta .persistence .metamodel .Attribute ;
3940public abstract class AbstractGraph <J > extends AbstractGraphNode <J > implements GraphImplementor <J > {
4041
4142 private final ManagedDomainType <J > managedType ;
43+ private final Map <Class <?>, SubGraphImplementor <?>> subgraphs = new HashMap <>(1 );
4244 private Map <PersistentAttribute <? super J ,?>, AttributeNodeImplementor <?>> attributeNodes ;
43- private List <SubGraphImplementor <? extends J >> subgraphs ;
4445
4546 public AbstractGraph (ManagedDomainType <J > managedType , boolean mutable ) {
4647 super ( mutable );
@@ -50,8 +51,7 @@ public AbstractGraph(ManagedDomainType<J> managedType, boolean mutable) {
5051 protected AbstractGraph (ManagedDomainType <J > managedType , GraphImplementor <? super J > graph , boolean mutable ) {
5152 this ( managedType , mutable );
5253 attributeNodes = new HashMap <>( graph .getAttributeNodesByAttribute ().size () );
53- graph .getAttributeNodesByAttribute ()
54- .forEach ( (attribute , node ) -> attributeNodes .put ( attribute , node .makeCopy ( mutable ) ) );
54+ mergeInternal ( graph , mutable );
5555 }
5656
5757 protected AbstractGraph (GraphImplementor <J > graph , boolean mutable ) {
@@ -76,42 +76,61 @@ public RootGraphImplementor<J> makeRootGraph(String name, boolean mutable) {
7676 }
7777
7878 @ Override
79- public void merge (GraphImplementor <J > graph ) {
79+ public void merge (GraphImplementor <? super J > graph ) {
80+ merge ( graph , true );
81+ }
82+
83+ @ Override
84+ public void merge (GraphImplementor <? super J > graph , boolean mutable ) {
8085 if ( graph != null ) {
8186 verifyMutability ();
82- graph .getAttributeNodesByAttribute ().forEach ( (attribute , node ) -> {
83- final AttributeNodeImplementor <?> existingNode = findAttributeNode ( attribute );
84- if ( existingNode != null ) {
85- // keep the local one, but merge in the incoming one
86- mergeNode ( node , existingNode );
87- }
88- else {
89- addAttributeNode ( attribute , node .makeCopy ( true ) );
90- }
91- } );
87+ mergeInternal ( graph , mutable );
9288 }
9389 }
9490
95- private static <T > void mergeNode (AttributeNodeImplementor <?> node , AttributeNodeImplementor <T > existingNode ) {
91+ private void mergeInternal (GraphImplementor <? super J > graph , boolean mutable ) {
92+ graph .getAttributeNodesByAttribute ().forEach ( (attribute , node ) -> {
93+ final AttributeNodeImplementor <?> existingNode = findAttributeNode ( attribute );
94+ if ( existingNode != null ) {
95+ // keep the local one, but merge in the incoming one
96+ mergeNode ( node , existingNode , mutable );
97+ }
98+ else {
99+ addAttributeNode ( attribute , node .makeCopy ( mutable ), mutable );
100+ }
101+ } );
102+ graph .getSubGraphMap ().forEach ( (type , subgraph ) -> {
103+ final SubGraphImplementor <?> existing = subgraphs .get ( type );
104+ if ( existing != null ) {
105+ existing .merge ( (SubGraphImplementor ) subgraph , mutable );
106+ }
107+ else {
108+ subgraphs .put ( type , subgraph .makeCopy ( mutable ) );
109+ }
110+ } );
111+ }
112+
113+ private static <T > void mergeNode (
114+ AttributeNodeImplementor <?> node , AttributeNodeImplementor <T > existingNode , boolean mutable ) {
96115 if ( existingNode .getAttributeDescriptor () == node .getAttributeDescriptor () ) {
97116 @ SuppressWarnings ("unchecked" ) // safe, we just checked
98117 final AttributeNodeImplementor <T > castNode = (AttributeNodeImplementor <T >) node ;
99- existingNode .merge ( castNode );
118+ existingNode .merge ( castNode , mutable );
100119 }
101120 else {
102121 throw new AssertionFailure ( "Attributes should have been identical" );
103122 }
104123 }
105124
106- private <T > void addAttributeNode (PersistentAttribute <? super J , ?> attribute , AttributeNodeImplementor <T > node ) {
125+ private <T > void addAttributeNode (
126+ PersistentAttribute <? super J , ?> attribute , AttributeNodeImplementor <T > node , boolean mutable ) {
107127 final AttributeNodeImplementor <T > attributeNode = getNodeForPut ( node .getAttributeDescriptor () );
108128 if ( attributeNode == null ) {
109129 attributeNodes .put ( attribute , node );
110130 }
111131 else {
112132 // we assume the subgraph has been properly copied if needed
113- node .getSubGraphMap ().forEach ( (subtype , subgraph ) -> attributeNode .addSubGraph ( subgraph ) );
114- node .getKeySubGraphMap ().forEach ( (subtype , subgraph ) -> attributeNode .addKeySubGraph ( subgraph ) );
133+ node .merge ( attributeNode , mutable );
115134 }
116135 }
117136
@@ -126,8 +145,8 @@ public <AJ> AttributeNodeImplementor<AJ> findAttributeNode(String attributeName)
126145 @ SuppressWarnings ("unchecked" ) // The JPA API is unsafe by nature
127146 final PersistentAttribute <? super J , AJ > persistentAttribute = (PersistentAttribute <? super J , AJ >) attribute ;
128147 final AttributeNodeImplementor <AJ > node = attribute == null ? null : findAttributeNode ( persistentAttribute );
129- if ( node == null && subgraphs != null ) {
130- for ( SubGraphImplementor <? extends J > subgraph : subgraphs ) {
148+ if ( node == null ) {
149+ for ( SubGraphImplementor <?> subgraph : subgraphs . values () ) {
131150 final AttributeNodeImplementor <AJ > subgraphNode = subgraph .findAttributeNode ( attributeName );
132151 if ( subgraphNode != null ) {
133152 return subgraphNode ;
@@ -272,12 +291,22 @@ public <AJ> SubGraphImplementor<AJ> addSubGraph(PersistentAttribute<? super J, ?
272291 }
273292
274293 @ Override
275- public <AJ > SubGraphImplementor <AJ > addSubGraph (MapPersistentAttribute <? super J , ? super AJ , ? > attribute , ManagedDomainType <AJ > subtype ) {
294+ public <AJ > SubGraphImplementor <AJ > addSubGraph (PersistentAttribute <? super J , ? super AJ > attribute , ManagedDomainType <AJ > subtype ) {
276295 return findOrCreateAttributeNode ( attribute ).makeSubGraph ( subtype );
277296 }
278297
279298 @ Override
280- public <AJ > SubGraphImplementor <AJ > addKeySubGraph (PersistentAttribute <? super J , ? super AJ > attribute , ManagedDomainType <AJ > subtype ) {
299+ public <AJ > SubGraphImplementor <AJ > addElementSubGraph (PluralPersistentAttribute <? super J , ?, ? super AJ > attribute , Class <AJ > type ) {
300+ return findOrCreateAttributeNode ( attribute ).makeSubGraph ( type );
301+ }
302+
303+ @ Override
304+ public <AJ > SubGraphImplementor <AJ > addElementSubGraph (PluralPersistentAttribute <? super J , ?, ? super AJ > attribute , ManagedDomainType <AJ > type ) {
305+ return findOrCreateAttributeNode ( attribute ).makeSubGraph ( type );
306+ }
307+
308+ @ Override
309+ public <AJ > SubGraphImplementor <AJ > addKeySubGraph (MapPersistentAttribute <? super J , ? super AJ , ?> attribute , ManagedDomainType <AJ > subtype ) {
281310 return findOrCreateAttributeNode ( attribute ).makeKeySubGraph ( subtype );
282311 }
283312
@@ -328,13 +357,44 @@ public <E> SubGraphImplementor<E> addTreatedElementSubgraph(
328357 }
329358
330359 @ Override
331- public <S extends J > SubGraphImplementor <S > addTreatedSubGraph (Class <S > type ) {
332- final ManagedDomainType <S > managedDomainType = getGraphedType ().getMetamodel ().managedType ( type );
333- final SubGraphImpl <S > subgraph = new SubGraphImpl <>( managedDomainType , this , true );
334- if ( subgraphs == null ) {
335- subgraphs = new ArrayList <>( 1 );
360+ public <S extends J > SubGraphImplementor <S > addTreatedSubGraph (ManagedDomainType <S > type ) {
361+ if ( getGraphedType ().equals ( type ) ) {
362+ //noinspection unchecked
363+ return (SubGraphImplementor <S >) this ;
364+ }
365+ else {
366+ final Class <S > javaType = type .getJavaType ();
367+ final SubGraphImplementor <S > castSubgraph = subgraph ( javaType );
368+ if ( castSubgraph == null ) {
369+ final SubGraphImpl <S > subgraph = new SubGraphImpl <>( type , true );
370+ subgraphs .put ( javaType , subgraph );
371+ return subgraph ;
372+ }
373+ else {
374+ return castSubgraph ;
375+ }
376+ }
377+ }
378+
379+ private <S extends J > SubGraphImplementor <S > subgraph (Class <S > javaType ) {
380+ final SubGraphImplementor <?> existing = subgraphs .get ( javaType );
381+ if ( existing != null ) {
382+ @ SuppressWarnings ("unchecked" )
383+ final SubGraphImplementor <S > castSubgraph = (SubGraphImplementor <S >) existing ;
384+ return castSubgraph ;
385+ }
386+ else {
387+ return null ;
336388 }
337- subgraphs .add ( subgraph );
338- return subgraph ;
389+ }
390+
391+ @ Override
392+ public <S extends J > SubGraphImplementor <S > addTreatedSubGraph (Class <S > type ) {
393+ return addTreatedSubGraph ( getGraphedType ().getMetamodel ().managedType ( type ) );
394+ }
395+
396+ @ Override
397+ public Map <Class <?>, SubGraphImplementor <?>> getSubGraphMap () {
398+ return subgraphs ;
339399 }
340400}
0 commit comments