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
.CdmApplicationRemoteController
;
68 import eu
.etaxonomy
.cdm
.api
.application
.ICdmApplicationConfiguration
;
69 import eu
.etaxonomy
.cdm
.api
.service
.ICommonService
;
70 import eu
.etaxonomy
.cdm
.model
.common
.PersistentMultiLanguageText
;
73 * Base class implementing {@link org.hibernate.collection.spi.PersistentCollection}
77 public abstract class AbstractPersistentCollection
implements Serializable
, PersistentCollection
{
78 private static final Logger log
= Logger
.getLogger( AbstractPersistentCollection
.class );
80 private static final long serialVersionUID
= -7238232378593030571L;
82 private transient SessionImplementor session
;
83 private boolean initialized
;
84 private transient List
<DelayedOperation
> operationQueue
;
85 private transient boolean directlyAccessible
;
86 private transient boolean initializing
;
88 private int cachedSize
= -1;
91 private Serializable key
;
92 // collections detect changes made via their public interface and mark
93 // themselves as dirty as a performance optimization
94 private boolean dirty
;
95 private Serializable storedSnapshot
;
97 private String sessionFactoryUuid
;
98 private boolean specjLazyLoad
= false;
100 public final String
getRole() {
104 public final Serializable
getKey() {
108 public final boolean isUnreferenced() {
112 public final boolean isDirty() {
116 public final void clearDirty() {
120 public final void dirty() {
124 public final Serializable
getStoredSnapshot() {
125 return storedSnapshot
;
128 //Careful: these methods do not initialize the collection.
131 * Is the initialized collection empty?
133 public abstract boolean empty();
136 * Called by any read-only method of the collection interface
138 protected final void read() {
143 * Called by the {@link Collection#size} method
145 @SuppressWarnings({"JavaDoc"})
146 protected boolean readSize() {
147 if ( !initialized
) {
148 if ( cachedSize
!= -1 && !hasQueuedOperations() ) {
152 // In remoting we are sure that session is null
153 // both when using property paths and switching off conversations
154 if(session
== null && remoting
) {
155 log
.info("--> readSize, of " + getRole() + " with key " + getKey());
158 boolean isExtraLazy
= withTemporarySessionIfNeeded(
159 new LazyInitializationWork
<Boolean
>() {
161 public Boolean
doWork() {
162 CollectionEntry entry
= session
.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection
.this );
164 if ( entry
!= null ) {
165 CollectionPersister persister
= entry
.getLoadedPersister();
166 if ( persister
.isExtraLazy() ) {
167 if ( hasQueuedOperations() ) {
170 cachedSize
= persister
.getSize( entry
.getLoadedKey(), session
);
178 throwLazyInitializationExceptionIfNotConnected();
193 public static interface LazyInitializationWork
<T
> {
197 private <T
> T
withTemporarySessionIfNeeded(LazyInitializationWork
<T
> lazyInitializationWork
) {
198 SessionImplementor originalSession
= null;
199 boolean isTempSession
= false;
200 boolean isJTA
= false;
202 if ( session
== null ) {
203 if ( specjLazyLoad
) {
204 session
= openTemporarySessionForLoading();
205 isTempSession
= true;
208 throwLazyInitializationException( "could not initialize proxy - no Session" );
211 else if ( !session
.isOpen() ) {
212 if ( specjLazyLoad
) {
213 originalSession
= session
;
214 session
= openTemporarySessionForLoading();
215 isTempSession
= true;
218 throwLazyInitializationException( "could not initialize proxy - the owning Session was closed" );
221 else if ( !session
.isConnected() ) {
222 if ( specjLazyLoad
) {
223 originalSession
= session
;
224 session
= openTemporarySessionForLoading();
225 isTempSession
= true;
228 throwLazyInitializationException( "could not initialize proxy - the owning Session is disconnected" );
232 if ( isTempSession
) {
233 // TODO: On the next major release, add an
234 // 'isJTA' or 'getTransactionFactory' method to Session.
235 isJTA
= session
.getTransactionCoordinator()
236 .getTransactionContext().getTransactionEnvironment()
237 .getTransactionFactory()
238 .compatibleWithJtaSynchronization();
241 // Explicitly handle the transactions only if we're not in
242 // a JTA environment. A lazy loading temporary session can
243 // be created even if a current session and transaction are
244 // open (ex: session.clear() was used). We must prevent
245 // multiple transactions.
246 ( ( Session
) session
).beginTransaction();
249 session
.getPersistenceContext().addUninitializedDetachedCollection(
250 session
.getFactory().getCollectionPersister( getRole() ),
256 return lazyInitializationWork
.doWork();
259 if ( isTempSession
) {
260 // make sure the just opened temp session gets closed!
263 ( ( Session
) session
).getTransaction().commit();
265 ( (Session
) session
).close();
267 catch (Exception e
) {
268 log
.warn( "Unable to close temporary session used to load lazy collection associated to no session" );
270 session
= originalSession
;
275 private SessionImplementor
openTemporarySessionForLoading() {
276 if ( sessionFactoryUuid
== null ) {
277 throwLazyInitializationException( "SessionFactory UUID not known to create temporary Session for loading" );
280 SessionFactoryImplementor sf
= (SessionFactoryImplementor
)
281 SessionFactoryRegistry
.INSTANCE
.getSessionFactory( sessionFactoryUuid
);
282 return (SessionImplementor
) sf
.openSession();
285 protected Boolean
readIndexExistence(final Object index
) {
286 if ( !initialized
) {
287 // In remoting we are sure that session is null
288 // both when using property paths and switching off conversations
289 if(session
== null && remoting
) {
290 log
.info("--> readIndexExistence, of " + getRole() + " with key " + getKey());
293 Boolean extraLazyExistenceCheck
= withTemporarySessionIfNeeded(
294 new LazyInitializationWork
<Boolean
>() {
296 public Boolean
doWork() {
297 CollectionEntry entry
= session
.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection
.this );
298 CollectionPersister persister
= entry
.getLoadedPersister();
299 if ( persister
.isExtraLazy() ) {
300 if ( hasQueuedOperations() ) {
303 return persister
.indexExists( entry
.getLoadedKey(), index
, session
);
312 if ( extraLazyExistenceCheck
!= null ) {
313 return extraLazyExistenceCheck
;
320 protected Boolean
readElementExistence(final Object element
) {
321 if ( !initialized
) {
322 // In remoting we are sure that session is null
323 // both when using property paths and switching off conversations
324 if(session
== null && remoting
) {
325 log
.info("--> readElementExistence, of " + getRole() + " with key " + getKey());
329 Boolean extraLazyExistenceCheck
= withTemporarySessionIfNeeded(
330 new LazyInitializationWork
<Boolean
>() {
332 public Boolean
doWork() {
333 CollectionEntry entry
= session
.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection
.this );
334 CollectionPersister persister
= entry
.getLoadedPersister();
335 if ( persister
.isExtraLazy() ) {
336 if ( hasQueuedOperations() ) {
339 return persister
.elementExists( entry
.getLoadedKey(), element
, session
);
348 if ( extraLazyExistenceCheck
!= null ) {
349 return extraLazyExistenceCheck
;
356 protected static final Object UNKNOWN
= new MarkerObject( "UNKNOWN" );
358 protected Object
readElementByIndex(final Object index
) {
359 if ( !initialized
) {
360 // In remoting we are sure that session is null
361 // both when using property paths and switching off conversations
362 if(session
== null && remoting
) {
363 log
.info("--> readElementByIndex, of " + getRole() + " with key " + getKey());
367 class ExtraLazyElementByIndexReader
implements LazyInitializationWork
{
368 private boolean isExtraLazy
;
369 private Object element
;
372 public Object
doWork() {
373 CollectionEntry entry
= session
.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection
.this );
374 CollectionPersister persister
= entry
.getLoadedPersister();
375 isExtraLazy
= persister
.isExtraLazy();
377 if ( hasQueuedOperations() ) {
380 element
= persister
.getElementByIndex( entry
.getLoadedKey(), index
, session
, owner
);
389 ExtraLazyElementByIndexReader reader
= new ExtraLazyElementByIndexReader();
390 //noinspection unchecked
391 withTemporarySessionIfNeeded( reader
);
392 if ( reader
.isExtraLazy
) {
393 return reader
.element
;
401 protected int getCachedSize() {
405 private boolean isConnectedToSession() {
406 return session
!= null &&
408 session
.getPersistenceContext().containsCollection( this );
412 * Called by any writer method of the collection interface
414 protected final void write() {
420 * Is this collection in a state that would allow us to
421 * "queue" operations?
423 @SuppressWarnings({"JavaDoc"})
424 protected boolean isOperationQueueEnabled() {
425 return !initialized
&&
426 isConnectedToSession() &&
427 isInverseCollection();
431 * Is this collection in a state that would allow us to
432 * "queue" puts? This is a special case, because of orphan
435 @SuppressWarnings({"JavaDoc"})
436 protected boolean isPutQueueEnabled() {
437 return !initialized
&&
438 isConnectedToSession() &&
439 isInverseOneToManyOrNoOrphanDelete();
443 * Is this collection in a state that would allow us to
444 * "queue" clear? This is a special case, because of orphan
447 @SuppressWarnings({"JavaDoc"})
448 protected boolean isClearQueueEnabled() {
449 return !initialized
&&
450 isConnectedToSession() &&
451 isInverseCollectionNoOrphanDelete();
455 * Is this the "inverse" end of a bidirectional association?
457 @SuppressWarnings({"JavaDoc"})
458 private boolean isInverseCollection() {
459 CollectionEntry ce
= session
.getPersistenceContext().getCollectionEntry( this );
460 return ce
!= null && ce
.getLoadedPersister().isInverse();
464 * Is this the "inverse" end of a bidirectional association with
465 * no orphan delete enabled?
467 @SuppressWarnings({"JavaDoc"})
468 private boolean isInverseCollectionNoOrphanDelete() {
469 CollectionEntry ce
= session
.getPersistenceContext().getCollectionEntry( this );
471 ce
.getLoadedPersister().isInverse() &&
472 !ce
.getLoadedPersister().hasOrphanDelete();
476 * Is this the "inverse" end of a bidirectional one-to-many, or
477 * of a collection with no orphan delete?
479 @SuppressWarnings({"JavaDoc"})
480 private boolean isInverseOneToManyOrNoOrphanDelete() {
481 CollectionEntry ce
= session
.getPersistenceContext().getCollectionEntry( this );
482 return ce
!= null && ce
.getLoadedPersister().isInverse() && (
483 ce
.getLoadedPersister().isOneToMany() ||
484 !ce
.getLoadedPersister().hasOrphanDelete()
491 @SuppressWarnings({"JavaDoc"})
492 protected final void queueOperation(DelayedOperation operation
) {
493 if ( operationQueue
== null ) {
494 operationQueue
= new ArrayList
<DelayedOperation
>( 10 );
496 operationQueue
.add( operation
);
497 dirty
= true; //needed so that we remove this collection from the second-level cache
501 * After reading all existing elements from the database,
502 * add the queued elements to the underlying collection.
504 protected final void performQueuedOperations() {
505 for ( DelayedOperation operation
: operationQueue
) {
511 * After flushing, re-init snapshot state.
513 public void setSnapshot(Serializable key
, String role
, Serializable snapshot
) {
516 this.storedSnapshot
= snapshot
;
520 * After flushing, clear any "queued" additions, since the
521 * database state is now synchronized with the memory state.
523 public void postAction() {
524 operationQueue
= null;
530 * Not called by Hibernate, but used by non-JDK serialization,
531 * eg. SOAP libraries.
533 public AbstractPersistentCollection() {
536 protected AbstractPersistentCollection(SessionImplementor session
) {
537 this.session
= session
;
541 * return the user-visible collection (or array) instance
543 public Object
getValue() {
548 * Called just before reading any rows from the JDBC result set
550 public void beginRead() {
551 // override on some subclasses
556 * Called after reading all rows from the JDBC result set
558 public boolean endRead() {
559 //override on some subclasses
560 return afterInitialize();
563 public boolean afterInitialize() {
565 //do this bit after setting initialized to true or it will recurse
566 if ( operationQueue
!= null ) {
567 performQueuedOperations();
568 operationQueue
= null;
578 * Initialize the collection, if possible, wrapping any exceptions
579 * in a runtime exception
581 * @param writing currently obsolete
583 * @throws LazyInitializationException if we cannot initialize
585 protected final void initialize(final boolean writing
) {
586 // In remoting we are sure that session is null
587 // both when using property paths and switching off conversations
588 if(session
== null && remoting
) {
597 withTemporarySessionIfNeeded(
598 new LazyInitializationWork
<Object
>() {
600 public Object
doWork() {
601 session
.initializeCollection( AbstractPersistentCollection
.this, writing
);
608 private void throwLazyInitializationExceptionIfNotConnected() {
609 if ( !isConnectedToSession() ) {
610 throwLazyInitializationException( "no session or session was closed" );
612 if ( !session
.isConnected() ) {
613 throwLazyInitializationException( "session is disconnected" );
617 private void throwLazyInitializationException(String message
) {
618 throw new LazyInitializationException(
619 "failed to lazily initialize a collection" +
620 (role
== null ?
"" : " of role: " + role
) +
625 protected final void setInitialized() {
626 this.initializing
= false;
627 this.initialized
= true;
630 protected final void setDirectlyAccessible(boolean directlyAccessible
) {
631 this.directlyAccessible
= directlyAccessible
;
635 * Could the application possibly have a direct reference to
636 * the underlying collection implementation?
638 public boolean isDirectlyAccessible() {
639 return directlyAccessible
;
643 * Disassociate this collection from the given session.
645 * @return true if this was currently associated with the given session
647 public final boolean unsetSession(SessionImplementor currentSession
) {
648 prepareForPossibleSpecialSpecjInitialization();
649 if ( currentSession
== this.session
) {
658 protected void prepareForPossibleSpecialSpecjInitialization() {
659 if ( session
!= null ) {
660 specjLazyLoad
= session
.getFactory().getSettings().isInitializeLazyStateOutsideTransactionsEnabled();
662 if ( specjLazyLoad
&& sessionFactoryUuid
== null ) {
664 sessionFactoryUuid
= (String
) session
.getFactory().getReference().get( "uuid" ).getContent();
666 catch (NamingException e
) {
667 //not much we can do if this fails...
675 * Associate the collection with the given session.
677 * @return false if the collection was already associated with the session
679 * @throws HibernateException if the collection was already associated
680 * with another open session
682 public final boolean setCurrentSession(SessionImplementor session
) throws HibernateException
{
683 if ( session
== this.session
) {
687 if ( isConnectedToSession() ) {
688 CollectionEntry ce
= session
.getPersistenceContext().getCollectionEntry( this );
690 throw new HibernateException(
691 "Illegal attempt to associate a collection with two open sessions"
695 throw new HibernateException(
696 "Illegal attempt to associate a collection with two open sessions: " +
697 MessageHelper
.collectionInfoString(
698 ce
.getLoadedPersister(), this,
699 ce
.getLoadedKey(), session
705 this.session
= session
;
712 * Do we need to completely recreate this collection when it changes?
714 public boolean needsRecreate(CollectionPersister persister
) {
719 * To be called internally by the session, forcing
720 * immediate initialization.
722 public final void forceInitialization() throws HibernateException
{
723 if ( !initialized
) {
724 if ( initializing
) {
725 throw new AssertionFailure( "force initialize loading collection" );
727 if ( session
== null ) {
728 throw new HibernateException( "collection is not associated with any session" );
730 if ( !session
.isConnected() ) {
731 throw new HibernateException( "disconnected session" );
733 session
.initializeCollection( this, false );
739 * Get the current snapshot from the session
741 @SuppressWarnings({"JavaDoc"})
742 protected final Serializable
getSnapshot() {
743 return session
.getPersistenceContext().getSnapshot( this );
747 * Is this instance initialized?
749 public final boolean wasInitialized() {
753 public boolean isRowUpdatePossible() {
758 * Does this instance have any "queued" additions?
760 public final boolean hasQueuedOperations() {
761 return operationQueue
!= null;
765 * Iterate the "queued" additions
767 public final Iterator
queuedAdditionIterator() {
768 if ( hasQueuedOperations() ) {
769 return new Iterator() {
772 public Object
next() {
773 return operationQueue
.get( i
++ ).getAddedInstance();
776 public boolean hasNext() {
777 return i
< operationQueue
.size();
780 public void remove() {
781 throw new UnsupportedOperationException();
786 return EmptyIterator
.INSTANCE
;
791 * Iterate the "queued" additions
793 @SuppressWarnings({"unchecked"})
794 public final Collection
getQueuedOrphans(String entityName
) {
795 if ( hasQueuedOperations() ) {
796 Collection additions
= new ArrayList( operationQueue
.size() );
797 Collection removals
= new ArrayList( operationQueue
.size() );
798 for ( DelayedOperation operation
: operationQueue
) {
799 additions
.add( operation
.getAddedInstance() );
800 removals
.add( operation
.getOrphan() );
802 return getOrphans( removals
, additions
, entityName
, session
);
805 return Collections
.EMPTY_LIST
;
810 * Called before inserting rows, to ensure that any surrogate keys
811 * are fully generated
813 public void preInsert(CollectionPersister persister
) throws HibernateException
{
817 * Called after inserting a row, to fetch the natively generated id
819 public void afterRowInsert(CollectionPersister persister
, Object entry
, int i
) throws HibernateException
{
823 * get all "orphaned" elements
825 public abstract Collection
getOrphans(Serializable snapshot
, String entityName
) throws HibernateException
;
828 * Get the current session
830 @SuppressWarnings({"JavaDoc"})
831 public final SessionImplementor
getSession() {
835 protected final class IteratorProxy
implements Iterator
{
836 protected final Iterator itr
;
838 public IteratorProxy(Iterator itr
) {
842 public boolean hasNext() {
843 return itr
.hasNext();
846 public Object
next() {
850 public void remove() {
857 protected final class ListIteratorProxy
implements ListIterator
{
858 protected final ListIterator itr
;
860 public ListIteratorProxy(ListIterator itr
) {
864 @SuppressWarnings({"unchecked"})
865 public void add(Object o
) {
870 public boolean hasNext() {
871 return itr
.hasNext();
874 public boolean hasPrevious() {
875 return itr
.hasPrevious();
878 public Object
next() {
882 public int nextIndex() {
883 return itr
.nextIndex();
886 public Object
previous() {
887 return itr
.previous();
890 public int previousIndex() {
891 return itr
.previousIndex();
894 public void remove() {
899 @SuppressWarnings({"unchecked"})
900 public void set(Object o
) {
907 protected class SetProxy
implements java
.util
.Set
{
908 protected final Collection set
;
910 public SetProxy(Collection set
) {
914 @SuppressWarnings({"unchecked"})
915 public boolean add(Object o
) {
920 @SuppressWarnings({"unchecked"})
921 public boolean addAll(Collection c
) {
923 return set
.addAll( c
);
926 public void clear() {
931 public boolean contains(Object o
) {
932 return set
.contains( o
);
935 public boolean containsAll(Collection c
) {
936 return set
.containsAll( c
);
939 public boolean isEmpty() {
940 return set
.isEmpty();
943 public Iterator
iterator() {
944 return new IteratorProxy( set
.iterator() );
947 public boolean remove(Object o
) {
949 return set
.remove( o
);
952 public boolean removeAll(Collection c
) {
954 return set
.removeAll( c
);
957 public boolean retainAll(Collection c
) {
959 return set
.retainAll( c
);
966 public Object
[] toArray() {
967 return set
.toArray();
970 @SuppressWarnings({"unchecked"})
971 public Object
[] toArray(Object
[] array
) {
972 return set
.toArray( array
);
977 protected final class ListProxy
implements java
.util
.List
{
978 protected final List list
;
980 public ListProxy(List list
) {
985 @SuppressWarnings({"unchecked"})
986 public void add(int index
, Object value
) {
988 list
.add( index
, value
);
992 @SuppressWarnings({"unchecked"})
993 public boolean add(Object o
) {
995 return list
.add( o
);
999 @SuppressWarnings({"unchecked"})
1000 public boolean addAll(Collection c
) {
1002 return list
.addAll( c
);
1006 @SuppressWarnings({"unchecked"})
1007 public boolean addAll(int i
, Collection c
) {
1009 return list
.addAll( i
, c
);
1013 public void clear() {
1019 public boolean contains(Object o
) {
1020 return list
.contains( o
);
1024 public boolean containsAll(Collection c
) {
1025 return list
.containsAll( c
);
1029 public Object
get(int i
) {
1030 return list
.get( i
);
1034 public int indexOf(Object o
) {
1035 return list
.indexOf( o
);
1039 public boolean isEmpty() {
1040 return list
.isEmpty();
1044 public Iterator
iterator() {
1045 return new IteratorProxy( list
.iterator() );
1049 public int lastIndexOf(Object o
) {
1050 return list
.lastIndexOf( o
);
1054 public ListIterator
listIterator() {
1055 return new ListIteratorProxy( list
.listIterator() );
1059 public ListIterator
listIterator(int i
) {
1060 return new ListIteratorProxy( list
.listIterator( i
) );
1064 public Object
remove(int i
) {
1066 return list
.remove( i
);
1070 public boolean remove(Object o
) {
1072 return list
.remove( o
);
1076 public boolean removeAll(Collection c
) {
1078 return list
.removeAll( c
);
1082 public boolean retainAll(Collection c
) {
1084 return list
.retainAll( c
);
1088 @SuppressWarnings({"unchecked"})
1089 public Object
set(int i
, Object o
) {
1091 return list
.set( i
, o
);
1100 public List
subList(int i
, int j
) {
1101 return list
.subList( i
, j
);
1105 public Object
[] toArray() {
1106 return list
.toArray();
1110 @SuppressWarnings({"unchecked"})
1111 public Object
[] toArray(Object
[] array
) {
1112 return list
.toArray( array
);
1118 * Contract for operations which are part of a collection's operation queue.
1120 protected interface DelayedOperation
{
1121 public void operate();
1123 public Object
getAddedInstance();
1125 public Object
getOrphan();
1129 * Given a collection of entity instances that used to
1130 * belong to the collection, and a collection of instances
1131 * that currently belong, return a collection of orphans
1133 @SuppressWarnings({"JavaDoc", "unchecked"})
1134 protected static Collection
getOrphans(
1135 Collection oldElements
,
1136 Collection currentElements
,
1138 SessionImplementor session
) throws HibernateException
{
1141 if ( currentElements
.size() == 0 ) {
1142 return oldElements
; // no new elements, the old list contains only Orphans
1144 if ( oldElements
.size() == 0 ) {
1145 return oldElements
; // no old elements, so no Orphans neither
1148 final EntityPersister entityPersister
= session
.getFactory().getEntityPersister( entityName
);
1149 final Type idType
= entityPersister
.getIdentifierType();
1151 // create the collection holding the Orphans
1152 Collection res
= new ArrayList();
1154 // collect EntityIdentifier(s) of the *current* elements - add them into a HashSet for fast access
1155 java
.util
.Set currentIds
= new HashSet();
1156 java
.util
.Set currentSaving
= new IdentitySet();
1157 for ( Object current
: currentElements
) {
1158 if ( current
!= null && ForeignKeys
.isNotTransient( entityName
, current
, null, session
) ) {
1159 EntityEntry ee
= session
.getPersistenceContext().getEntry( current
);
1160 if ( ee
!= null && ee
.getStatus() == Status
.SAVING
) {
1161 currentSaving
.add( current
);
1164 Serializable currentId
= ForeignKeys
.getEntityIdentifierIfNotUnsaved(
1169 currentIds
.add( new TypedValue( idType
, currentId
, entityPersister
.getEntityMode() ) );
1174 // iterate over the *old* list
1175 for ( Object old
: oldElements
) {
1176 if ( !currentSaving
.contains( old
) ) {
1177 Serializable oldId
= ForeignKeys
.getEntityIdentifierIfNotUnsaved( entityName
, old
, session
);
1178 if ( !currentIds
.contains( new TypedValue( idType
, oldId
, entityPersister
.getEntityMode() ) ) ) {
1187 public static void identityRemove(
1191 SessionImplementor session
) throws HibernateException
{
1193 if ( object
!= null && ForeignKeys
.isNotTransient( entityName
, object
, null, session
) ) {
1194 final EntityPersister entityPersister
= session
.getFactory().getEntityPersister( entityName
);
1195 Type idType
= entityPersister
.getIdentifierType();
1197 Serializable idOfCurrent
= ForeignKeys
.getEntityIdentifierIfNotUnsaved( entityName
, object
, session
);
1198 Iterator itr
= list
.iterator();
1199 while ( itr
.hasNext() ) {
1200 Serializable idOfOld
= ForeignKeys
.getEntityIdentifierIfNotUnsaved( entityName
, itr
.next(), session
);
1201 if ( idType
.isEqual( idOfCurrent
, idOfOld
, session
.getFactory() ) ) {
1210 public Object
getIdentifier(Object entry
, int i
) {
1211 throw new UnsupportedOperationException();
1214 public Object
getOwner() {
1218 public void setOwner(Object owner
) {
1222 /** ------ Below is section of code which makes remote service calls ----- */
1223 // The affected methods are :
1224 // initialize(final boolean writing)
1226 // readIndexExistence(final Object index)
1227 // readElementExistence(final Object element)
1228 // readElementByIndex(final Object index)
1230 private static ICdmApplicationConfiguration configuration
;
1231 private static boolean remoting
= false;
1233 public static void setConfiguration(ICdmApplicationConfiguration conf
) {
1234 configuration
= conf
;
1236 if(conf
instanceof CdmApplicationRemoteController
) {
1244 private void remoteInitialize() {
1246 if (getOwner() != null && !initialized
) {
1249 String role
= getRole();
1250 String fieldName
= role
.substring(role
.lastIndexOf(".") + 1);
1251 log
.info("--> Remote Lazy Initializing " + getRole() + " , key : " + getKey() + " , field : " + fieldName
);
1252 Object owner
= getOwner();
1254 if(configuration
== null) {
1255 throw new HibernateException("CdmApplicationRemoteConfiguration not initialized (null)");
1257 ICommonService commonService
= configuration
.getCommonService();
1258 if(commonService
== null) {
1259 throw new HibernateException("commonService not initialized (null)");
1262 PersistentCollection col
= commonService
.initializeCollection(this);
1265 Class
<?
> clazz
= getClass();
1266 if (clazz
!= null) {
1267 CollectionField cf
= getCollectionField(col
);
1268 Field field
= clazz
.getDeclaredField(cf
.getFieldName());
1269 field
.setAccessible(true);
1270 field
.set(this, cf
.getCollection());
1272 } catch (Exception ex
) {
1273 log
.warn(ex
.getMessage());
1279 private CollectionField
getCollectionField(PersistentCollection pc
) {
1281 if(pc
instanceof PersistentSet
) {
1282 return new CollectionField(new HashSet((Set
)pc
), "set");
1284 if(pc
instanceof PersistentSortedSet
) {
1285 return new CollectionField(new TreeSet((Set
)pc
), "set");
1287 if(pc
instanceof PersistentList
) {
1288 return new CollectionField(new ArrayList((List
)pc
), "list");
1290 if(pc
instanceof PersistentMap
|| pc
instanceof PersistentMultiLanguageText
) {
1291 return new CollectionField(new HashMap((Map
)pc
), "map");
1293 if(pc
instanceof PersistentSortedMap
) {
1294 return new CollectionField(new TreeMap((Map
)pc
), "map");
1300 private String
getCollectionFieldName(PersistentCollection pc
) {
1302 if(pc
instanceof PersistentSet
|| pc
instanceof PersistentSortedSet
) {
1305 if(pc
instanceof PersistentList
) {
1308 if(pc
instanceof PersistentMap
|| pc
instanceof PersistentMultiLanguageText
) {
1315 private class CollectionField
{
1317 private String fieldName
;
1318 public CollectionField(Object col
, String fieldName
) {
1320 this.fieldName
= fieldName
;
1323 public Object
getCollection() {
1327 public String
getFieldName() {
1328 return this.fieldName
;
1332 public static boolean isInitialized(List list
) {
1333 return ((AbstractPersistentCollection
)list
).initialized
;
1336 public static boolean isInitialized(Map map
) {
1337 return ((AbstractPersistentCollection
)map
).initialized
;
1340 public static boolean isInitialized(Set set
) {
1341 return ((AbstractPersistentCollection
)set
).initialized
;
1344 //FIXME:Remoting These methods may no longer be required since we are
1345 // initialising collections as default behaviour
1346 private int remoteSize() {
1347 int size
= configuration
.getCommonService().size(this);
1348 log
.debug("--> Remote Lazy Initializing size of " + getRole() + " to " + size
);
1350 throw new HibernateException("size of " + getClass() + " could not be retrieved from remote service");
1355 private Object
remoteReadElementByIndex(int index
) {
1356 Object element
= configuration
.getCommonService().get(this,index
);
1357 log
.debug("--> Remote Lazy Initializing element from " + getRole() + " at index " + index
);
1361 private boolean remoteReadElementExistence(Object element
) {
1362 return configuration
.getCommonService().contains(this,element
);
1365 private boolean remoteReadIndexExistence(Object index
) {