@@ -110,20 +110,18 @@ else if ( target instanceof Map<?, ?> map ) {
110110 }
111111 else {
112112 final PersistenceContext persistenceContext = session .getPersistenceContext ();
113- final PersistentCollection <?> collectionHolder = persistenceContext .getCollectionHolder ( target );
114- if ( collectionHolder != null ) {
115- if ( collectionHolder instanceof PersistentArrayHolder <?> arrayHolder ) {
116- persistenceContext .removeCollectionHolder ( target );
117- arrayHolder .beginRead ();
118- final PluralAttributeMapping attributeMapping =
119- persistenceContext .getCollectionEntry ( collectionHolder )
120- .getLoadedPersister ().getAttributeMapping ();
121- arrayHolder .injectLoadedState ( attributeMapping , null );
122- arrayHolder .endRead ();
123- arrayHolder .dirty ();
124- persistenceContext .addCollectionHolder ( collectionHolder );
125- return arrayHolder .getArray ();
126- }
113+ if ( persistenceContext .getCollectionHolder ( target )
114+ instanceof PersistentArrayHolder <?> arrayHolder ) {
115+ persistenceContext .removeCollectionHolder ( target );
116+ arrayHolder .beginRead ();
117+ final PluralAttributeMapping attributeMapping =
118+ persistenceContext .getCollectionEntry ( arrayHolder )
119+ .getLoadedPersister ().getAttributeMapping ();
120+ arrayHolder .injectLoadedState ( attributeMapping , null );
121+ arrayHolder .endRead ();
122+ arrayHolder .dirty ();
123+ persistenceContext .addCollectionHolder ( arrayHolder );
124+ return arrayHolder .getArray ();
127125 }
128126 }
129127 return null ;
@@ -142,8 +140,9 @@ private static Object replaceUninitializedOriginal(
142140 // A managed entity with an uninitialized collection is being merged,
143141 // We need to replace any detached entities in the queued operations
144142 // with managed copies.
145- final AbstractPersistentCollection <?> pc = (AbstractPersistentCollection <?>) original ;
146- pc .replaceQueuedOperationValues (
143+ final AbstractPersistentCollection <?> collection =
144+ (AbstractPersistentCollection <?>) original ;
145+ collection .replaceQueuedOperationValues (
147146 session .getFactory ()
148147 .getMappingMetamodel ()
149148 .getCollectionDescriptor ( type .getRole () ), copyCache
@@ -182,18 +181,20 @@ private static CompletionStage<Object> replaceOriginal(
182181 ).thenCompose ( result -> {
183182 if ( original == target ) {
184183 // get the elements back into the target making sure to handle dirty flag
185- final boolean wasClean =
186- target instanceof PersistentCollection <?> collection
187- && !collection .isDirty ();
188184 //TODO: this is a little inefficient, don't need to do a whole
189185 // deep replaceElements() call
190- return replaceElements ( type , result , target , owner , copyCache , session )
191- .thenApply ( unused -> {
192- if ( wasClean ) {
193- ( (PersistentCollection <?>) target ).clearDirty ();
194- }
195- return target ;
196- } );
186+ final CompletionStage <Object > replaced =
187+ replaceElements ( type , result , target , owner , copyCache , session );
188+ if ( target instanceof PersistentCollection <?> collection
189+ && !collection .isDirty () ) {
190+ return replaced .thenApply ( unused -> {
191+ collection .clearDirty ();
192+ return target ;
193+ } );
194+ }
195+ else {
196+ return replaced .thenApply ( unused -> target );
197+ }
197198 }
198199 else {
199200 return completedFuture ( result );
@@ -220,7 +221,7 @@ else if ( type instanceof CustomCollectionType ) {
220221 else if ( type instanceof MapType ) {
221222 return replaceMapTypeElements (
222223 type ,
223- (Map <Object , Object >) original ,
224+ (Map <?, ? >) original ,
224225 (Map <Object , Object >) target ,
225226 owner ,
226227 copyCache ,
@@ -247,64 +248,70 @@ private static CompletionStage<Object> replaceCollectionTypeElements(
247248 Map <Object , Object > copyCache ,
248249 SessionImplementor session ) {
249250 result .clear ();
250-
251251 // copy elements into newly empty target collection
252252 final Type elemType = type .getElementType ( session .getFactory () );
253- return loop (
254- (Collection <Object >) original , o -> getReplace ( elemType , o , owner , session , copyCache )
255- .thenAccept ( result ::add )
256- ).thenCompose ( unused -> {
257- // if the original is a PersistentCollection, and that original
258- // was not flagged as dirty, then reset the target's dirty flag
259- // here after the copy operation.
260- // </p>
261- // One thing to be careful of here is a "bare" original collection
262- // in which case we should never ever ever reset the dirty flag
263- // on the target because we simply do not know...
264- if ( original instanceof PersistentCollection <?> originalPersistentCollection
265- && result instanceof PersistentCollection <?> resultPersistentCollection ) {
266- return preserveSnapshot (
267- originalPersistentCollection , resultPersistentCollection ,
268- elemType , owner , copyCache , session
269- ).thenApply ( v -> {
270- if ( !originalPersistentCollection .isDirty () ) {
271- resultPersistentCollection .clearDirty ();
272- }
273- return result ;
274- } );
275- }
276- else {
277- return completedFuture ( result );
278- }
279- } );
253+ return loop ( (Collection <?>) original ,
254+ o -> getReplace ( elemType , o , owner , session , copyCache )
255+ .thenAccept ( result ::add ) )
256+ .thenCompose ( v -> preserveSnapshotIfNecessary ( original , result , owner , copyCache , session , elemType ) );
257+ }
258+
259+ private static CompletionStage <Object > preserveSnapshotIfNecessary (
260+ Object original ,
261+ Collection <Object > result ,
262+ Object owner ,
263+ Map <Object , Object > copyCache ,
264+ SessionImplementor session ,
265+ Type elemType ) {
266+ // if the original is a PersistentCollection, and that original
267+ // was not flagged as dirty, then reset the target's dirty flag
268+ // here after the copy operation.
269+ // </p>
270+ // One thing to be careful of here is a "bare" original collection
271+ // in which case we should never ever ever reset the dirty flag
272+ // on the target because we simply do not know...
273+ if ( original instanceof PersistentCollection <?> originalCollection
274+ && result instanceof PersistentCollection <?> resultCollection ) {
275+ return preserveSnapshot (
276+ originalCollection , resultCollection ,
277+ elemType , owner , copyCache , session
278+ ).thenApply ( v -> {
279+ if ( !originalCollection .isDirty () ) {
280+ resultCollection .clearDirty ();
281+ }
282+ return result ;
283+ } );
284+ }
285+ else {
286+ return completedFuture ( result );
287+ }
280288 }
281289
282290 private static CompletionStage <Object > replaceMapTypeElements (
283291 CollectionType type ,
284- Map <Object , Object > original ,
292+ Map <?, ? > original ,
285293 Map <Object , Object > target ,
286294 Object owner ,
287295 Map <Object , Object > copyCache ,
288296 SessionImplementor session ) {
289- final CollectionPersister persister = session .getFactory ().getRuntimeMetamodels ()
290- .getMappingMetamodel ().getCollectionDescriptor ( type .getRole () );
291- final Map <Object , Object > result = target ;
292- result .clear ();
293-
297+ final CollectionPersister persister =
298+ session .getFactory ().getRuntimeMetamodels ().getMappingMetamodel ()
299+ .getCollectionDescriptor ( type .getRole () );
300+ target .clear ();
294301 return loop (
295302 original .entrySet (), entry -> {
296- final Map .Entry <Object , Object > me = entry ;
303+ final Map .Entry <?, ? > me = entry ;
297304 return getReplace ( persister .getIndexType (), me .getKey (), owner , session , copyCache )
298305 .thenCompose ( key -> getReplace (
299306 persister .getElementType (),
300307 me .getValue (),
301308 owner ,
302309 session ,
303310 copyCache
304- ).thenAccept ( value -> result .put ( key , value ) )
311+ ).thenAccept ( value -> target .put ( key , value ) )
305312 );
306313 }
307- ).thenApply ( unused -> result );
314+ ).thenApply ( unused -> target );
308315 }
309316
310317 private static CompletionStage <Object > replaceArrayTypeElements (
@@ -325,8 +332,8 @@ private static CompletionStage<Object> replaceArrayTypeElements(
325332 }
326333
327334 final Type elemType = type .getElementType ( session .getFactory () );
328- return loop (
329- 0 , length , i -> getReplace ( elemType , Array .get ( original , i ), owner , session , copyCache )
335+ return loop ( 0 , length ,
336+ i -> getReplace ( elemType , Array .get ( original , i ), owner , session , copyCache )
330337 .thenApply ( o -> {
331338 Array .set ( result , i , o );
332339 return result ;
@@ -345,18 +352,14 @@ private static CompletionStage<Object> getReplace(
345352
346353 private static CompletionStage <Object > getReplace (
347354 Type elemType ,
348- Object o ,
355+ Object object ,
349356 Object target ,
350357 Object owner ,
351358 SessionImplementor session ,
352359 Map <Object , Object > copyCache ) {
353- if ( elemType instanceof EntityType ) {
354- return EntityTypes .replace ( (EntityType ) elemType , o , target , session , owner , copyCache );
355- }
356- else {
357- final Object replace = elemType .replace ( o , target , session , owner , copyCache );
358- return completedFuture ( replace );
359- }
360+ return elemType instanceof EntityType entityType
361+ ? EntityTypes .replace ( entityType , object , target , session , owner , copyCache )
362+ : completedFuture ( elemType .replace ( object , target , session , owner , copyCache ) );
360363 }
361364
362365 /**
@@ -374,7 +377,9 @@ private static CompletionStage<Void> preserveSnapshot(
374377 return createSnapshot ( original , result , elemType , owner , copyCache , session )
375378 .thenAccept ( serializable -> ce .resetStoredSnapshot ( result , serializable ) );
376379 }
377- return voidFuture ();
380+ else {
381+ return voidFuture ();
382+ }
378383 }
379384
380385 /**
@@ -412,38 +417,35 @@ private static CompletionStage<Serializable> createArraySnapshot(
412417 Object owner ,
413418 Map <Object , Object > copyCache ,
414419 SessionImplementor session ) {
415- return loop (
416- 0 , array . length , i -> getReplace ( elemType , array [i ], owner , session , copyCache )
420+ return loop ( 0 , array . length ,
421+ i -> getReplace ( elemType , array [i ], owner , session , copyCache )
417422 .thenAccept ( o -> array [i ] = o )
418423 ).thenApply ( unused -> array );
419424 }
420425
421426 /**
422427 * @see CollectionType#createMapSnapshot(Map, PersistentCollection, Type, Object, Map, SharedSessionContractImplementor)
423428 */
424- private static CompletionStage <Serializable > createMapSnapshot (
425- Map <?, ? > map ,
429+ private static < K , V > CompletionStage <Serializable > createMapSnapshot (
430+ Map <K , V > map ,
426431 PersistentCollection <?> result ,
427432 Type elemType ,
428433 Object owner ,
429434 Map <Object , Object > copyCache ,
430435 SessionImplementor session ) {
431436 final Map <?, ?> resultSnapshot = (Map <?, ?>) result .getStoredSnapshot ();
432- final Map <Object , Object > targetMap ;
433- if ( map instanceof SortedMap <?, ?> sortedMap ) {
434- //noinspection unchecked, rawtypes
435- targetMap = new TreeMap ( sortedMap .comparator () );
436- }
437- else {
438- targetMap = mapOfSize ( map .size () );
439- }
440- return loop (
441- map .entrySet (), entry ->
442- getReplace ( elemType , entry .getValue (), resultSnapshot , owner , session , copyCache )
443- .thenAccept ( newValue -> {
444- final Object key = entry .getKey ();
445- targetMap .put ( key == entry .getValue () ? newValue : key , newValue );
446- } )
437+ final Map <K , V > targetMap =
438+ map instanceof SortedMap <K , V > sortedMap
439+ ? new TreeMap <>( sortedMap .comparator () )
440+ : mapOfSize (map .size ());
441+ return loop ( map .entrySet (),
442+ entry -> getReplace ( elemType , entry .getValue (), resultSnapshot , owner , session , copyCache )
443+ .thenAccept ( newValue -> {
444+ final K key = entry .getKey ();
445+ final V value = entry .getValue ();
446+ //noinspection unchecked
447+ targetMap .put ( key == value ? (K ) newValue : key , (V ) newValue );
448+ } )
447449 ).thenApply ( v -> (Serializable ) targetMap );
448450 }
449451
@@ -457,8 +459,8 @@ private static CompletionStage<Serializable> createListSnapshot(
457459 Map <Object , Object > copyCache ,
458460 SessionImplementor session ) {
459461 final ArrayList <Object > targetList = new ArrayList <>( list .size () );
460- return loop (
461- list , obj -> getReplace ( elemType , obj , owner , session , copyCache )
462+ return loop ( list ,
463+ obj -> getReplace ( elemType , obj , owner , session , copyCache )
462464 .thenAccept ( targetList ::add )
463465 ).thenApply ( unused -> targetList );
464466 }
@@ -472,9 +474,9 @@ private static Object instantiateResultIfNecessary(CollectionType type, Object o
472474 // by default just use an unanticipated capacity since we don't
473475 // know how to extract the capacity to use from original here...
474476 return target == null
475- || target == original
476- || target == UNFETCHED_PROPERTY
477- || target instanceof PersistentCollection <?> collection && collection .isWrapper ( original )
477+ || target == original
478+ || target == UNFETCHED_PROPERTY
479+ || target instanceof PersistentCollection <?> collection && collection .isWrapper ( original )
478480 ? type .instantiate ( -1 )
479481 : target ;
480482 }
0 commit comments