4 * Hibernate, Relational Persistence for Idiomatic Java
6 * Copyright (c) 2008-2011, Red Hat Inc. or third-party contributors as
7 * indicated by the @author tags or express copyright attribution
8 * statements applied by the authors. All third-party contributions are
9 * distributed under license by Red Hat Inc.
11 * This copyrighted material is made available to anyone wishing to use, modify,
12 * copy, or redistribute it subject to the terms and conditions of the GNU
13 * Lesser General Public License, as published by the Free Software Foundation.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this distribution; if not, write to:
22 * Free Software Foundation, Inc.
23 * 51 Franklin Street, Fifth Floor
24 * Boston, MA 02110-1301 USA
26 package org
.hibernate
.collection
.internal
;
28 import java
.io
.Serializable
;
29 import java
.lang
.reflect
.Field
;
30 import java
.util
.ArrayList
;
31 import java
.util
.Collection
;
32 import java
.util
.Collections
;
33 import java
.util
.HashMap
;
34 import java
.util
.HashSet
;
35 import java
.util
.Iterator
;
36 import java
.util
.List
;
37 import java
.util
.ListIterator
;
40 import java
.util
.TreeMap
;
41 import java
.util
.TreeSet
;
43 import javax
.naming
.NamingException
;
45 import org
.hibernate
.AssertionFailure
;
46 import org
.hibernate
.HibernateException
;
47 import org
.hibernate
.LazyInitializationException
;
48 import org
.hibernate
.Session
;
49 import org
.hibernate
.collection
.spi
.PersistentCollection
;
50 import org
.hibernate
.engine
.internal
.ForeignKeys
;
51 import org
.hibernate
.engine
.spi
.CollectionEntry
;
52 import org
.hibernate
.engine
.spi
.EntityEntry
;
53 import org
.hibernate
.engine
.spi
.SessionFactoryImplementor
;
54 import org
.hibernate
.engine
.spi
.SessionImplementor
;
55 import org
.hibernate
.engine
.spi
.Status
;
56 import org
.hibernate
.engine
.spi
.TypedValue
;
57 import org
.hibernate
.internal
.SessionFactoryRegistry
;
58 import org
.hibernate
.internal
.util
.MarkerObject
;
59 import org
.hibernate
.internal
.util
.collections
.EmptyIterator
;
60 import org
.hibernate
.internal
.util
.collections
.IdentitySet
;
61 import org
.hibernate
.persister
.collection
.CollectionPersister
;
62 import org
.hibernate
.persister
.entity
.EntityPersister
;
63 import org
.hibernate
.pretty
.MessageHelper
;
64 import org
.hibernate
.type
.Type
;
65 import org
.jboss
.logging
.Logger
;
67 import eu
.etaxonomy
.cdm
.api
.application
.CdmApplicationRemoteConfiguration
;
68 import eu
.etaxonomy
.cdm
.api
.application
.CdmApplicationRemoteController
;
69 import eu
.etaxonomy
.cdm
.api
.application
.ICdmApplicationConfiguration
;
70 import eu
.etaxonomy
.cdm
.api
.cache
.ICachedCommonService
;
71 import eu
.etaxonomy
.cdm
.api
.cache
.CachedCommonServiceImpl
.CollectionField
;
72 import eu
.etaxonomy
.cdm
.api
.service
.ICommonService
;
73 import eu
.etaxonomy
.cdm
.model
.common
.PersistentMultiLanguageText
;
76 * Base class implementing {@link org.hibernate.collection.spi.PersistentCollection}
80 public abstract class AbstractPersistentCollection
implements Serializable
, PersistentCollection
{
81 private static final Logger log
= Logger
.getLogger( AbstractPersistentCollection
.class );
83 private static final long serialVersionUID
= -7238232378593030571L;
85 private transient SessionImplementor session
;
86 private boolean initialized
;
87 private transient List
<DelayedOperation
> operationQueue
;
88 private transient boolean directlyAccessible
;
89 private transient boolean initializing
;
91 private int cachedSize
= -1;
94 private Serializable key
;
95 // collections detect changes made via their public interface and mark
96 // themselves as dirty as a performance optimization
97 private boolean dirty
;
98 private Serializable storedSnapshot
;
100 private String sessionFactoryUuid
;
101 private boolean specjLazyLoad
= false;
104 public final String
getRole() {
109 public final Serializable
getKey() {
114 public final boolean isUnreferenced() {
119 public final boolean isDirty() {
124 public final void clearDirty() {
129 public final void dirty() {
134 public final Serializable
getStoredSnapshot() {
135 return storedSnapshot
;
138 //Careful: these methods do not initialize the collection.
141 * Is the initialized collection empty?
144 public abstract boolean empty();
147 * Called by any read-only method of the collection interface
149 protected final void read() {
154 * Called by the {@link Collection#size} method
156 @SuppressWarnings({"JavaDoc"})
157 protected boolean readSize() {
158 if ( !initialized
) {
159 if ( cachedSize
!= -1 && !hasQueuedOperations() ) {
163 // In remoting we are sure that session is null
164 // both when using property paths and switching off conversations
165 if(session
== null && remoting
) {
166 log
.info("--> readSize, of " + getRole() + " with key " + getKey());
169 boolean isExtraLazy
= withTemporarySessionIfNeeded(
170 new LazyInitializationWork
<Boolean
>() {
172 public Boolean
doWork() {
173 CollectionEntry entry
= session
.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection
.this );
175 if ( entry
!= null ) {
176 CollectionPersister persister
= entry
.getLoadedPersister();
177 if ( persister
.isExtraLazy() ) {
178 if ( hasQueuedOperations() ) {
181 cachedSize
= persister
.getSize( entry
.getLoadedKey(), session
);
189 throwLazyInitializationExceptionIfNotConnected();
204 public static interface LazyInitializationWork
<T
> {
208 private <T
> T
withTemporarySessionIfNeeded(LazyInitializationWork
<T
> lazyInitializationWork
) {
209 SessionImplementor originalSession
= null;
210 boolean isTempSession
= false;
211 boolean isJTA
= false;
213 if ( session
== null ) {
214 if ( specjLazyLoad
) {
215 session
= openTemporarySessionForLoading();
216 isTempSession
= true;
219 throwLazyInitializationException( "could not initialize proxy - no Session" );
222 else if ( !session
.isOpen() ) {
223 if ( specjLazyLoad
) {
224 originalSession
= session
;
225 session
= openTemporarySessionForLoading();
226 isTempSession
= true;
229 throwLazyInitializationException( "could not initialize proxy - the owning Session was closed" );
232 else if ( !session
.isConnected() ) {
233 if ( specjLazyLoad
) {
234 originalSession
= session
;
235 session
= openTemporarySessionForLoading();
236 isTempSession
= true;
239 throwLazyInitializationException( "could not initialize proxy - the owning Session is disconnected" );
243 if ( isTempSession
) {
244 // TODO: On the next major release, add an
245 // 'isJTA' or 'getTransactionFactory' method to Session.
246 isJTA
= session
.getTransactionCoordinator()
247 .getTransactionContext().getTransactionEnvironment()
248 .getTransactionFactory()
249 .compatibleWithJtaSynchronization();
252 // Explicitly handle the transactions only if we're not in
253 // a JTA environment. A lazy loading temporary session can
254 // be created even if a current session and transaction are
255 // open (ex: session.clear() was used). We must prevent
256 // multiple transactions.
257 ( ( Session
) session
).beginTransaction();
260 session
.getPersistenceContext().addUninitializedDetachedCollection(
261 session
.getFactory().getCollectionPersister( getRole() ),
267 return lazyInitializationWork
.doWork();
270 if ( isTempSession
) {
271 // make sure the just opened temp session gets closed!
274 ( ( Session
) session
).getTransaction().commit();
276 ( (Session
) session
).close();
278 catch (Exception e
) {
279 log
.warn( "Unable to close temporary session used to load lazy collection associated to no session" );
281 session
= originalSession
;
286 private SessionImplementor
openTemporarySessionForLoading() {
287 if ( sessionFactoryUuid
== null ) {
288 throwLazyInitializationException( "SessionFactory UUID not known to create temporary Session for loading" );
291 SessionFactoryImplementor sf
= (SessionFactoryImplementor
)
292 SessionFactoryRegistry
.INSTANCE
.getSessionFactory( sessionFactoryUuid
);
293 return (SessionImplementor
) sf
.openSession();
296 protected Boolean
readIndexExistence(final Object index
) {
297 if ( !initialized
) {
298 // In remoting we are sure that session is null
299 // both when using property paths and switching off conversations
300 if(session
== null && remoting
) {
301 log
.info("--> readIndexExistence, of " + getRole() + " with key " + getKey());
304 Boolean extraLazyExistenceCheck
= withTemporarySessionIfNeeded(
305 new LazyInitializationWork
<Boolean
>() {
307 public Boolean
doWork() {
308 CollectionEntry entry
= session
.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection
.this );
309 CollectionPersister persister
= entry
.getLoadedPersister();
310 if ( persister
.isExtraLazy() ) {
311 if ( hasQueuedOperations() ) {
314 return persister
.indexExists( entry
.getLoadedKey(), index
, session
);
323 if ( extraLazyExistenceCheck
!= null ) {
324 return extraLazyExistenceCheck
;
331 protected Boolean
readElementExistence(final Object element
) {
332 if ( !initialized
) {
333 // In remoting we are sure that session is null
334 // both when using property paths and switching off conversations
335 if(session
== null && remoting
) {
336 log
.info("--> readElementExistence, of " + getRole() + " with key " + getKey());
340 Boolean extraLazyExistenceCheck
= withTemporarySessionIfNeeded(
341 new LazyInitializationWork
<Boolean
>() {
343 public Boolean
doWork() {
344 CollectionEntry entry
= session
.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection
.this );
345 CollectionPersister persister
= entry
.getLoadedPersister();
346 if ( persister
.isExtraLazy() ) {
347 if ( hasQueuedOperations() ) {
350 return persister
.elementExists( entry
.getLoadedKey(), element
, session
);
359 if ( extraLazyExistenceCheck
!= null ) {
360 return extraLazyExistenceCheck
;
367 protected static final Object UNKNOWN
= new MarkerObject( "UNKNOWN" );
369 protected Object
readElementByIndex(final Object index
) {
370 if ( !initialized
) {
371 // In remoting we are sure that session is null
372 // both when using property paths and switching off conversations
373 if(session
== null && remoting
) {
374 log
.info("--> readElementByIndex, of " + getRole() + " with key " + getKey());
378 class ExtraLazyElementByIndexReader
implements LazyInitializationWork
{
379 private boolean isExtraLazy
;
380 private Object element
;
383 public Object
doWork() {
384 CollectionEntry entry
= session
.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection
.this );
385 CollectionPersister persister
= entry
.getLoadedPersister();
386 isExtraLazy
= persister
.isExtraLazy();
388 if ( hasQueuedOperations() ) {
391 element
= persister
.getElementByIndex( entry
.getLoadedKey(), index
, session
, owner
);
400 ExtraLazyElementByIndexReader reader
= new ExtraLazyElementByIndexReader();
401 //noinspection unchecked
402 withTemporarySessionIfNeeded( reader
);
403 if ( reader
.isExtraLazy
) {
404 return reader
.element
;
412 protected int getCachedSize() {
416 private boolean isConnectedToSession() {
417 return session
!= null &&
419 session
.getPersistenceContext().containsCollection( this );
423 * Called by any writer method of the collection interface
425 protected final void write() {
431 * Is this collection in a state that would allow us to
432 * "queue" operations?
434 @SuppressWarnings({"JavaDoc"})
435 protected boolean isOperationQueueEnabled() {
436 return !initialized
&&
437 isConnectedToSession() &&
438 isInverseCollection();
442 * Is this collection in a state that would allow us to
443 * "queue" puts? This is a special case, because of orphan
446 @SuppressWarnings({"JavaDoc"})
447 protected boolean isPutQueueEnabled() {
448 return !initialized
&&
449 isConnectedToSession() &&
450 isInverseOneToManyOrNoOrphanDelete();
454 * Is this collection in a state that would allow us to
455 * "queue" clear? This is a special case, because of orphan
458 @SuppressWarnings({"JavaDoc"})
459 protected boolean isClearQueueEnabled() {
460 return !initialized
&&
461 isConnectedToSession() &&
462 isInverseCollectionNoOrphanDelete();
466 * Is this the "inverse" end of a bidirectional association?
468 @SuppressWarnings({"JavaDoc"})
469 private boolean isInverseCollection() {
470 CollectionEntry ce
= session
.getPersistenceContext().getCollectionEntry( this );
471 return ce
!= null && ce
.getLoadedPersister().isInverse();
475 * Is this the "inverse" end of a bidirectional association with
476 * no orphan delete enabled?
478 @SuppressWarnings({"JavaDoc"})
479 private boolean isInverseCollectionNoOrphanDelete() {
480 CollectionEntry ce
= session
.getPersistenceContext().getCollectionEntry( this );
482 ce
.getLoadedPersister().isInverse() &&
483 !ce
.getLoadedPersister().hasOrphanDelete();
487 * Is this the "inverse" end of a bidirectional one-to-many, or
488 * of a collection with no orphan delete?
490 @SuppressWarnings({"JavaDoc"})
491 private boolean isInverseOneToManyOrNoOrphanDelete() {
492 CollectionEntry ce
= session
.getPersistenceContext().getCollectionEntry( this );
493 return ce
!= null && ce
.getLoadedPersister().isInverse() && (
494 ce
.getLoadedPersister().isOneToMany() ||
495 !ce
.getLoadedPersister().hasOrphanDelete()
502 @SuppressWarnings({"JavaDoc"})
503 protected final void queueOperation(DelayedOperation operation
) {
504 if ( operationQueue
== null ) {
505 operationQueue
= new ArrayList
<DelayedOperation
>( 10 );
507 operationQueue
.add( operation
);
508 dirty
= true; //needed so that we remove this collection from the second-level cache
512 * After reading all existing elements from the database,
513 * add the queued elements to the underlying collection.
515 protected final void performQueuedOperations() {
516 for ( DelayedOperation operation
: operationQueue
) {
522 * After flushing, re-init snapshot state.
525 public void setSnapshot(Serializable key
, String role
, Serializable snapshot
) {
528 this.storedSnapshot
= snapshot
;
532 * After flushing, clear any "queued" additions, since the
533 * database state is now synchronized with the memory state.
536 public void postAction() {
537 operationQueue
= null;
543 * Not called by Hibernate, but used by non-JDK serialization,
544 * eg. SOAP libraries.
546 public AbstractPersistentCollection() {
549 protected AbstractPersistentCollection(SessionImplementor session
) {
550 this.session
= session
;
554 * return the user-visible collection (or array) instance
557 public Object
getValue() {
562 * Called just before reading any rows from the JDBC result set
565 public void beginRead() {
566 // override on some subclasses
571 * Called after reading all rows from the JDBC result set
574 public boolean endRead() {
575 //override on some subclasses
576 return afterInitialize();
580 public boolean afterInitialize() {
582 //do this bit after setting initialized to true or it will recurse
583 if ( operationQueue
!= null ) {
584 performQueuedOperations();
585 operationQueue
= null;
595 * Initialize the collection, if possible, wrapping any exceptions
596 * in a runtime exception
598 * @param writing currently obsolete
600 * @throws LazyInitializationException if we cannot initialize
602 protected final void initialize(final boolean writing
) {
603 // In remoting we are sure that session is null
604 // both when using property paths and switching off conversations
605 if(session
== null && remoting
) {
614 withTemporarySessionIfNeeded(
615 new LazyInitializationWork
<Object
>() {
617 public Object
doWork() {
618 session
.initializeCollection( AbstractPersistentCollection
.this, writing
);
625 private void throwLazyInitializationExceptionIfNotConnected() {
626 if ( !isConnectedToSession() ) {
627 throwLazyInitializationException( "no session or session was closed" );
629 if ( !session
.isConnected() ) {
630 throwLazyInitializationException( "session is disconnected" );
634 private void throwLazyInitializationException(String message
) {
635 throw new LazyInitializationException(
636 "failed to lazily initialize a collection" +
637 (role
== null ?
"" : " of role: " + role
) +
642 protected final void setInitialized() {
643 this.initializing
= false;
644 this.initialized
= true;
647 protected final void setDirectlyAccessible(boolean directlyAccessible
) {
648 this.directlyAccessible
= directlyAccessible
;
652 * Could the application possibly have a direct reference to
653 * the underlying collection implementation?
656 public boolean isDirectlyAccessible() {
657 return directlyAccessible
;
661 * Disassociate this collection from the given session.
663 * @return true if this was currently associated with the given session
666 public final boolean unsetSession(SessionImplementor currentSession
) {
667 prepareForPossibleSpecialSpecjInitialization();
668 if ( currentSession
== this.session
) {
677 protected void prepareForPossibleSpecialSpecjInitialization() {
678 if ( session
!= null ) {
679 specjLazyLoad
= session
.getFactory().getSettings().isInitializeLazyStateOutsideTransactionsEnabled();
681 if ( specjLazyLoad
&& sessionFactoryUuid
== null ) {
683 sessionFactoryUuid
= (String
) session
.getFactory().getReference().get( "uuid" ).getContent();
685 catch (NamingException e
) {
686 //not much we can do if this fails...
694 * Associate the collection with the given session.
696 * @return false if the collection was already associated with the session
698 * @throws HibernateException if the collection was already associated
699 * with another open session
702 public final boolean setCurrentSession(SessionImplementor session
) throws HibernateException
{
703 if ( session
== this.session
) {
707 if ( isConnectedToSession() ) {
708 CollectionEntry ce
= session
.getPersistenceContext().getCollectionEntry( this );
710 throw new HibernateException(
711 "Illegal attempt to associate a collection with two open sessions"
715 throw new HibernateException(
716 "Illegal attempt to associate a collection with two open sessions: " +
717 MessageHelper
.collectionInfoString(
718 ce
.getLoadedPersister(), this,
719 ce
.getLoadedKey(), session
725 this.session
= session
;
732 * Do we need to completely recreate this collection when it changes?
735 public boolean needsRecreate(CollectionPersister persister
) {
740 * To be called internally by the session, forcing
741 * immediate initialization.
744 public final void forceInitialization() throws HibernateException
{
745 if ( !initialized
) {
746 if ( initializing
) {
747 throw new AssertionFailure( "force initialize loading collection" );
749 if ( session
== null ) {
750 throw new HibernateException( "collection is not associated with any session" );
752 if ( !session
.isConnected() ) {
753 throw new HibernateException( "disconnected session" );
755 session
.initializeCollection( this, false );
761 * Get the current snapshot from the session
763 @SuppressWarnings({"JavaDoc"})
764 protected final Serializable
getSnapshot() {
765 return session
.getPersistenceContext().getSnapshot( this );
769 * Is this instance initialized?
772 public final boolean wasInitialized() {
777 public boolean isRowUpdatePossible() {
782 * Does this instance have any "queued" additions?
785 public final boolean hasQueuedOperations() {
786 return operationQueue
!= null;
790 * Iterate the "queued" additions
793 public final Iterator
queuedAdditionIterator() {
794 if ( hasQueuedOperations() ) {
795 return new Iterator() {
799 public Object
next() {
800 return operationQueue
.get( i
++ ).getAddedInstance();
804 public boolean hasNext() {
805 return i
< operationQueue
.size();
809 public void remove() {
810 throw new UnsupportedOperationException();
815 return EmptyIterator
.INSTANCE
;
820 * Iterate the "queued" additions
823 @SuppressWarnings({"unchecked"})
824 public final Collection
getQueuedOrphans(String entityName
) {
825 if ( hasQueuedOperations() ) {
826 Collection additions
= new ArrayList( operationQueue
.size() );
827 Collection removals
= new ArrayList( operationQueue
.size() );
828 for ( DelayedOperation operation
: operationQueue
) {
829 additions
.add( operation
.getAddedInstance() );
830 removals
.add( operation
.getOrphan() );
832 return getOrphans( removals
, additions
, entityName
, session
);
835 return Collections
.EMPTY_LIST
;
840 * Called before inserting rows, to ensure that any surrogate keys
841 * are fully generated
844 public void preInsert(CollectionPersister persister
) throws HibernateException
{
848 * Called after inserting a row, to fetch the natively generated id
851 public void afterRowInsert(CollectionPersister persister
, Object entry
, int i
) throws HibernateException
{
855 * get all "orphaned" elements
858 public abstract Collection
getOrphans(Serializable snapshot
, String entityName
) throws HibernateException
;
861 * Get the current session
863 @SuppressWarnings({"JavaDoc"})
864 public final SessionImplementor
getSession() {
868 protected final class IteratorProxy
implements Iterator
{
869 protected final Iterator itr
;
871 public IteratorProxy(Iterator itr
) {
876 public boolean hasNext() {
877 return itr
.hasNext();
881 public Object
next() {
886 public void remove() {
893 protected final class ListIteratorProxy
implements ListIterator
{
894 protected final ListIterator itr
;
896 public ListIteratorProxy(ListIterator itr
) {
901 @SuppressWarnings({"unchecked"})
902 public void add(Object o
) {
908 public boolean hasNext() {
909 return itr
.hasNext();
913 public boolean hasPrevious() {
914 return itr
.hasPrevious();
918 public Object
next() {
923 public int nextIndex() {
924 return itr
.nextIndex();
928 public Object
previous() {
929 return itr
.previous();
933 public int previousIndex() {
934 return itr
.previousIndex();
938 public void remove() {
944 @SuppressWarnings({"unchecked"})
945 public void set(Object o
) {
952 protected class SetProxy
implements java
.util
.Set
{
953 protected final Collection set
;
955 public SetProxy(Collection set
) {
960 @SuppressWarnings({"unchecked"})
961 public boolean add(Object o
) {
967 @SuppressWarnings({"unchecked"})
968 public boolean addAll(Collection c
) {
970 return set
.addAll( c
);
974 public void clear() {
980 public boolean contains(Object o
) {
981 return set
.contains( o
);
985 public boolean containsAll(Collection c
) {
986 return set
.containsAll( c
);
990 public boolean isEmpty() {
991 return set
.isEmpty();
995 public Iterator
iterator() {
996 return new IteratorProxy( set
.iterator() );
1000 public boolean remove(Object o
) {
1002 return set
.remove( o
);
1006 public boolean removeAll(Collection c
) {
1008 return set
.removeAll( c
);
1012 public boolean retainAll(Collection c
) {
1014 return set
.retainAll( c
);
1023 public Object
[] toArray() {
1024 return set
.toArray();
1028 @SuppressWarnings({"unchecked"})
1029 public Object
[] toArray(Object
[] array
) {
1030 return set
.toArray( array
);
1035 protected final class ListProxy
implements java
.util
.List
{
1036 protected final List list
;
1038 public ListProxy(List list
) {
1043 @SuppressWarnings({"unchecked"})
1044 public void add(int index
, Object value
) {
1046 list
.add( index
, value
);
1050 @SuppressWarnings({"unchecked"})
1051 public boolean add(Object o
) {
1053 return list
.add( o
);
1057 @SuppressWarnings({"unchecked"})
1058 public boolean addAll(Collection c
) {
1060 return list
.addAll( c
);
1064 @SuppressWarnings({"unchecked"})
1065 public boolean addAll(int i
, Collection c
) {
1067 return list
.addAll( i
, c
);
1071 public void clear() {
1077 public boolean contains(Object o
) {
1078 return list
.contains( o
);
1082 public boolean containsAll(Collection c
) {
1083 return list
.containsAll( c
);
1087 public Object
get(int i
) {
1088 return list
.get( i
);
1092 public int indexOf(Object o
) {
1093 return list
.indexOf( o
);
1097 public boolean isEmpty() {
1098 return list
.isEmpty();
1102 public Iterator
iterator() {
1103 return new IteratorProxy( list
.iterator() );
1107 public int lastIndexOf(Object o
) {
1108 return list
.lastIndexOf( o
);
1112 public ListIterator
listIterator() {
1113 return new ListIteratorProxy( list
.listIterator() );
1117 public ListIterator
listIterator(int i
) {
1118 return new ListIteratorProxy( list
.listIterator( i
) );
1122 public Object
remove(int i
) {
1124 return list
.remove( i
);
1128 public boolean remove(Object o
) {
1130 return list
.remove( o
);
1134 public boolean removeAll(Collection c
) {
1136 return list
.removeAll( c
);
1140 public boolean retainAll(Collection c
) {
1142 return list
.retainAll( c
);
1146 @SuppressWarnings({"unchecked"})
1147 public Object
set(int i
, Object o
) {
1149 return list
.set( i
, o
);
1158 public List
subList(int i
, int j
) {
1159 return list
.subList( i
, j
);
1163 public Object
[] toArray() {
1164 return list
.toArray();
1168 @SuppressWarnings({"unchecked"})
1169 public Object
[] toArray(Object
[] array
) {
1170 return list
.toArray( array
);
1176 * Contract for operations which are part of a collection's operation queue.
1178 protected interface DelayedOperation
{
1179 public void operate();
1181 public Object
getAddedInstance();
1183 public Object
getOrphan();
1187 * Given a collection of entity instances that used to
1188 * belong to the collection, and a collection of instances
1189 * that currently belong, return a collection of orphans
1191 @SuppressWarnings({"JavaDoc", "unchecked"})
1192 protected static Collection
getOrphans(
1193 Collection oldElements
,
1194 Collection currentElements
,
1196 SessionImplementor session
) throws HibernateException
{
1199 if ( currentElements
.size() == 0 ) {
1200 return oldElements
; // no new elements, the old list contains only Orphans
1202 if ( oldElements
.size() == 0 ) {
1203 return oldElements
; // no old elements, so no Orphans neither
1206 final EntityPersister entityPersister
= session
.getFactory().getEntityPersister( entityName
);
1207 final Type idType
= entityPersister
.getIdentifierType();
1209 // create the collection holding the Orphans
1210 Collection res
= new ArrayList();
1212 // collect EntityIdentifier(s) of the *current* elements - add them into a HashSet for fast access
1213 java
.util
.Set currentIds
= new HashSet();
1214 java
.util
.Set currentSaving
= new IdentitySet();
1215 for ( Object current
: currentElements
) {
1216 if ( current
!= null && ForeignKeys
.isNotTransient( entityName
, current
, null, session
) ) {
1217 EntityEntry ee
= session
.getPersistenceContext().getEntry( current
);
1218 if ( ee
!= null && ee
.getStatus() == Status
.SAVING
) {
1219 currentSaving
.add( current
);
1222 Serializable currentId
= ForeignKeys
.getEntityIdentifierIfNotUnsaved(
1227 currentIds
.add( new TypedValue( idType
, currentId
, entityPersister
.getEntityMode() ) );
1232 // iterate over the *old* list
1233 for ( Object old
: oldElements
) {
1234 if ( !currentSaving
.contains( old
) ) {
1235 Serializable oldId
= ForeignKeys
.getEntityIdentifierIfNotUnsaved( entityName
, old
, session
);
1236 if ( !currentIds
.contains( new TypedValue( idType
, oldId
, entityPersister
.getEntityMode() ) ) ) {
1245 public static void identityRemove(
1249 SessionImplementor session
) throws HibernateException
{
1251 if ( object
!= null && ForeignKeys
.isNotTransient( entityName
, object
, null, session
) ) {
1252 final EntityPersister entityPersister
= session
.getFactory().getEntityPersister( entityName
);
1253 Type idType
= entityPersister
.getIdentifierType();
1255 Serializable idOfCurrent
= ForeignKeys
.getEntityIdentifierIfNotUnsaved( entityName
, object
, session
);
1256 Iterator itr
= list
.iterator();
1257 while ( itr
.hasNext() ) {
1258 Serializable idOfOld
= ForeignKeys
.getEntityIdentifierIfNotUnsaved( entityName
, itr
.next(), session
);
1259 if ( idType
.isEqual( idOfCurrent
, idOfOld
, session
.getFactory() ) ) {
1269 public Object
getIdentifier(Object entry
, int i
) {
1270 throw new UnsupportedOperationException();
1274 public Object
getOwner() {
1279 public void setOwner(Object owner
) {
1283 /** ------ Below is section of code which makes remote service calls ----- */
1284 // The affected methods are :
1285 // initialize(final boolean writing)
1287 // readIndexExistence(final Object index)
1288 // readElementExistence(final Object element)
1289 // readElementByIndex(final Object index)
1291 private static CdmApplicationRemoteConfiguration configuration
;
1292 private static boolean remoting
= false;
1294 public static void setConfiguration(CdmApplicationRemoteConfiguration conf
) {
1296 configuration
= conf
;
1300 private void remoteInitialize() {
1302 if (getOwner() != null && !initialized
) {
1305 String role
= getRole();
1306 String fieldName
= role
.substring(role
.lastIndexOf(".") + 1);
1307 log
.info("--> Remote Lazy Initializing Collection " + getRole() + " , key : " + getKey() + " , field : " + fieldName
);
1308 Object owner
= getOwner();
1310 if(configuration
== null) {
1311 throw new HibernateException("CdmApplicationRemoteConfiguration not initialized (null)");
1313 ICachedCommonService cachedCommonService
= configuration
.getCachedCommonService();
1314 if(cachedCommonService
== null) {
1315 throw new HibernateException("commonService not initialized (null)");
1318 PersistentCollection col
= cachedCommonService
.initializeCollection(this);
1321 Class
<?
> clazz
= getClass();
1322 if (clazz
!= null) {
1323 CollectionField cf
= cachedCommonService
.getCollectionField(col
);
1324 cachedCommonService
.updatePersistentCollection(cf
);
1325 Field field
= clazz
.getDeclaredField(cf
.getType().toString());
1326 field
.setAccessible(true);
1327 field
.set(this, cf
.getCollection());
1329 } catch (Exception ex
) {
1330 log
.warn(ex
.getMessage());