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
.util
.ArrayList
;
30 import java
.util
.Collection
;
31 import java
.util
.Collections
;
32 import java
.util
.HashMap
;
33 import java
.util
.HashSet
;
34 import java
.util
.Iterator
;
35 import java
.util
.List
;
36 import java
.util
.ListIterator
;
39 import java
.util
.TreeMap
;
40 import java
.util
.TreeSet
;
42 import javax
.naming
.NamingException
;
44 import org
.hibernate
.AssertionFailure
;
45 import org
.hibernate
.HibernateException
;
46 import org
.hibernate
.LazyInitializationException
;
47 import org
.hibernate
.Session
;
48 import org
.hibernate
.collection
.spi
.PersistentCollection
;
49 import org
.hibernate
.engine
.internal
.ForeignKeys
;
50 import org
.hibernate
.engine
.spi
.CollectionEntry
;
51 import org
.hibernate
.engine
.spi
.EntityEntry
;
52 import org
.hibernate
.engine
.spi
.SessionFactoryImplementor
;
53 import org
.hibernate
.engine
.spi
.SessionImplementor
;
54 import org
.hibernate
.engine
.spi
.Status
;
55 import org
.hibernate
.engine
.spi
.TypedValue
;
56 import org
.hibernate
.internal
.SessionFactoryRegistry
;
57 import org
.hibernate
.internal
.util
.MarkerObject
;
58 import org
.hibernate
.internal
.util
.collections
.EmptyIterator
;
59 import org
.hibernate
.internal
.util
.collections
.IdentitySet
;
60 import org
.hibernate
.persister
.collection
.CollectionPersister
;
61 import org
.hibernate
.persister
.entity
.EntityPersister
;
62 import org
.hibernate
.pretty
.MessageHelper
;
63 import org
.hibernate
.type
.Type
;
64 import org
.jboss
.logging
.Logger
;
66 import eu
.etaxonomy
.cdm
.api
.application
.CdmApplicationRemoteController
;
67 import eu
.etaxonomy
.cdm
.api
.application
.ICdmApplicationConfiguration
;
68 import eu
.etaxonomy
.cdm
.api
.service
.ICommonService
;
69 import eu
.etaxonomy
.cdm
.model
.common
.PersistentMultiLanguageText
;
72 * Base class implementing {@link org.hibernate.collection.spi.PersistentCollection}
76 public abstract class AbstractPersistentCollection
implements Serializable
, PersistentCollection
{
77 private static final Logger log
= Logger
.getLogger( AbstractPersistentCollection
.class );
79 private static final long serialVersionUID
= -7238232378593030571L;
81 private transient SessionImplementor session
;
82 private boolean initialized
;
83 private transient List
<DelayedOperation
> operationQueue
;
84 private transient boolean directlyAccessible
;
85 private transient boolean initializing
;
87 private int cachedSize
= -1;
90 private Serializable key
;
91 // collections detect changes made via their public interface and mark
92 // themselves as dirty as a performance optimization
93 private boolean dirty
;
94 private Serializable storedSnapshot
;
96 private String sessionFactoryUuid
;
97 private boolean specjLazyLoad
= false;
100 public final String
getRole() {
105 public final Serializable
getKey() {
110 public final boolean isUnreferenced() {
115 public final boolean isDirty() {
120 public final void clearDirty() {
125 public final void dirty() {
130 public final Serializable
getStoredSnapshot() {
131 return storedSnapshot
;
134 //Careful: these methods do not initialize the collection.
137 * Is the initialized collection empty?
140 public abstract boolean empty();
143 * Called by any read-only method of the collection interface
145 protected final void read() {
150 * Called by the {@link Collection#size} method
152 @SuppressWarnings({"JavaDoc"})
153 protected boolean readSize() {
154 if ( !initialized
) {
155 if ( cachedSize
!= -1 && !hasQueuedOperations() ) {
159 // In remoting we are sure that session is null
160 // both when using property paths and switching off conversations
161 if(session
== null && remoting
) {
162 log
.info("--> readSize, of " + getRole() + " with key " + getKey());
165 boolean isExtraLazy
= withTemporarySessionIfNeeded(
166 new LazyInitializationWork
<Boolean
>() {
168 public Boolean
doWork() {
169 CollectionEntry entry
= session
.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection
.this );
171 if ( entry
!= null ) {
172 CollectionPersister persister
= entry
.getLoadedPersister();
173 if ( persister
.isExtraLazy() ) {
174 if ( hasQueuedOperations() ) {
177 cachedSize
= persister
.getSize( entry
.getLoadedKey(), session
);
185 throwLazyInitializationExceptionIfNotConnected();
200 public static interface LazyInitializationWork
<T
> {
204 private <T
> T
withTemporarySessionIfNeeded(LazyInitializationWork
<T
> lazyInitializationWork
) {
205 SessionImplementor originalSession
= null;
206 boolean isTempSession
= false;
207 boolean isJTA
= false;
209 if ( session
== null ) {
210 if ( specjLazyLoad
) {
211 session
= openTemporarySessionForLoading();
212 isTempSession
= true;
215 throwLazyInitializationException( "could not initialize proxy - no Session" );
218 else if ( !session
.isOpen() ) {
219 if ( specjLazyLoad
) {
220 originalSession
= session
;
221 session
= openTemporarySessionForLoading();
222 isTempSession
= true;
225 throwLazyInitializationException( "could not initialize proxy - the owning Session was closed" );
228 else if ( !session
.isConnected() ) {
229 if ( specjLazyLoad
) {
230 originalSession
= session
;
231 session
= openTemporarySessionForLoading();
232 isTempSession
= true;
235 throwLazyInitializationException( "could not initialize proxy - the owning Session is disconnected" );
239 if ( isTempSession
) {
240 // TODO: On the next major release, add an
241 // 'isJTA' or 'getTransactionFactory' method to Session.
242 isJTA
= session
.getTransactionCoordinator()
243 .getTransactionContext().getTransactionEnvironment()
244 .getTransactionFactory()
245 .compatibleWithJtaSynchronization();
248 // Explicitly handle the transactions only if we're not in
249 // a JTA environment. A lazy loading temporary session can
250 // be created even if a current session and transaction are
251 // open (ex: session.clear() was used). We must prevent
252 // multiple transactions.
253 ( ( Session
) session
).beginTransaction();
256 session
.getPersistenceContext().addUninitializedDetachedCollection(
257 session
.getFactory().getCollectionPersister( getRole() ),
263 return lazyInitializationWork
.doWork();
266 if ( isTempSession
) {
267 // make sure the just opened temp session gets closed!
270 ( ( Session
) session
).getTransaction().commit();
272 ( (Session
) session
).close();
274 catch (Exception e
) {
275 log
.warn( "Unable to close temporary session used to load lazy collection associated to no session" );
277 session
= originalSession
;
282 private SessionImplementor
openTemporarySessionForLoading() {
283 if ( sessionFactoryUuid
== null ) {
284 throwLazyInitializationException( "SessionFactory UUID not known to create temporary Session for loading" );
287 SessionFactoryImplementor sf
= (SessionFactoryImplementor
)
288 SessionFactoryRegistry
.INSTANCE
.getSessionFactory( sessionFactoryUuid
);
289 return (SessionImplementor
) sf
.openSession();
292 protected Boolean
readIndexExistence(final Object index
) {
293 if ( !initialized
) {
294 // In remoting we are sure that session is null
295 // both when using property paths and switching off conversations
296 if(session
== null && remoting
) {
297 log
.info("--> readIndexExistence, of " + getRole() + " with key " + getKey());
300 Boolean extraLazyExistenceCheck
= withTemporarySessionIfNeeded(
301 new LazyInitializationWork
<Boolean
>() {
303 public Boolean
doWork() {
304 CollectionEntry entry
= session
.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection
.this );
305 CollectionPersister persister
= entry
.getLoadedPersister();
306 if ( persister
.isExtraLazy() ) {
307 if ( hasQueuedOperations() ) {
310 return persister
.indexExists( entry
.getLoadedKey(), index
, session
);
319 if ( extraLazyExistenceCheck
!= null ) {
320 return extraLazyExistenceCheck
;
327 protected Boolean
readElementExistence(final Object element
) {
328 if ( !initialized
) {
329 // In remoting we are sure that session is null
330 // both when using property paths and switching off conversations
331 if(session
== null && remoting
) {
332 log
.info("--> readElementExistence, of " + getRole() + " with key " + getKey());
336 Boolean extraLazyExistenceCheck
= withTemporarySessionIfNeeded(
337 new LazyInitializationWork
<Boolean
>() {
339 public Boolean
doWork() {
340 CollectionEntry entry
= session
.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection
.this );
341 CollectionPersister persister
= entry
.getLoadedPersister();
342 if ( persister
.isExtraLazy() ) {
343 if ( hasQueuedOperations() ) {
346 return persister
.elementExists( entry
.getLoadedKey(), element
, session
);
355 if ( extraLazyExistenceCheck
!= null ) {
356 return extraLazyExistenceCheck
;
363 protected static final Object UNKNOWN
= new MarkerObject( "UNKNOWN" );
365 protected Object
readElementByIndex(final Object index
) {
366 if ( !initialized
) {
367 // In remoting we are sure that session is null
368 // both when using property paths and switching off conversations
369 if(session
== null && remoting
) {
370 log
.info("--> readElementByIndex, of " + getRole() + " with key " + getKey());
374 class ExtraLazyElementByIndexReader
implements LazyInitializationWork
{
375 private boolean isExtraLazy
;
376 private Object element
;
379 public Object
doWork() {
380 CollectionEntry entry
= session
.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection
.this );
381 CollectionPersister persister
= entry
.getLoadedPersister();
382 isExtraLazy
= persister
.isExtraLazy();
384 if ( hasQueuedOperations() ) {
387 element
= persister
.getElementByIndex( entry
.getLoadedKey(), index
, session
, owner
);
396 ExtraLazyElementByIndexReader reader
= new ExtraLazyElementByIndexReader();
397 //noinspection unchecked
398 withTemporarySessionIfNeeded( reader
);
399 if ( reader
.isExtraLazy
) {
400 return reader
.element
;
408 protected int getCachedSize() {
412 private boolean isConnectedToSession() {
413 return session
!= null &&
415 session
.getPersistenceContext().containsCollection( this );
419 * Called by any writer method of the collection interface
421 protected final void write() {
427 * Is this collection in a state that would allow us to
428 * "queue" operations?
430 @SuppressWarnings({"JavaDoc"})
431 protected boolean isOperationQueueEnabled() {
432 return !initialized
&&
433 isConnectedToSession() &&
434 isInverseCollection();
438 * Is this collection in a state that would allow us to
439 * "queue" puts? This is a special case, because of orphan
442 @SuppressWarnings({"JavaDoc"})
443 protected boolean isPutQueueEnabled() {
444 return !initialized
&&
445 isConnectedToSession() &&
446 isInverseOneToManyOrNoOrphanDelete();
450 * Is this collection in a state that would allow us to
451 * "queue" clear? This is a special case, because of orphan
454 @SuppressWarnings({"JavaDoc"})
455 protected boolean isClearQueueEnabled() {
456 return !initialized
&&
457 isConnectedToSession() &&
458 isInverseCollectionNoOrphanDelete();
462 * Is this the "inverse" end of a bidirectional association?
464 @SuppressWarnings({"JavaDoc"})
465 private boolean isInverseCollection() {
466 CollectionEntry ce
= session
.getPersistenceContext().getCollectionEntry( this );
467 return ce
!= null && ce
.getLoadedPersister().isInverse();
471 * Is this the "inverse" end of a bidirectional association with
472 * no orphan delete enabled?
474 @SuppressWarnings({"JavaDoc"})
475 private boolean isInverseCollectionNoOrphanDelete() {
476 CollectionEntry ce
= session
.getPersistenceContext().getCollectionEntry( this );
478 ce
.getLoadedPersister().isInverse() &&
479 !ce
.getLoadedPersister().hasOrphanDelete();
483 * Is this the "inverse" end of a bidirectional one-to-many, or
484 * of a collection with no orphan delete?
486 @SuppressWarnings({"JavaDoc"})
487 private boolean isInverseOneToManyOrNoOrphanDelete() {
488 CollectionEntry ce
= session
.getPersistenceContext().getCollectionEntry( this );
489 return ce
!= null && ce
.getLoadedPersister().isInverse() && (
490 ce
.getLoadedPersister().isOneToMany() ||
491 !ce
.getLoadedPersister().hasOrphanDelete()
498 @SuppressWarnings({"JavaDoc"})
499 protected final void queueOperation(DelayedOperation operation
) {
500 if ( operationQueue
== null ) {
501 operationQueue
= new ArrayList
<DelayedOperation
>( 10 );
503 operationQueue
.add( operation
);
504 dirty
= true; //needed so that we remove this collection from the second-level cache
508 * After reading all existing elements from the database,
509 * add the queued elements to the underlying collection.
511 protected final void performQueuedOperations() {
512 for ( DelayedOperation operation
: operationQueue
) {
518 * After flushing, re-init snapshot state.
521 public void setSnapshot(Serializable key
, String role
, Serializable snapshot
) {
524 this.storedSnapshot
= snapshot
;
528 * After flushing, clear any "queued" additions, since the
529 * database state is now synchronized with the memory state.
532 public void postAction() {
533 operationQueue
= null;
539 * Not called by Hibernate, but used by non-JDK serialization,
540 * eg. SOAP libraries.
542 public AbstractPersistentCollection() {
545 protected AbstractPersistentCollection(SessionImplementor session
) {
546 this.session
= session
;
550 * return the user-visible collection (or array) instance
553 public Object
getValue() {
558 * Called just before reading any rows from the JDBC result set
561 public void beginRead() {
562 // override on some subclasses
567 * Called after reading all rows from the JDBC result set
570 public boolean endRead() {
571 //override on some subclasses
572 return afterInitialize();
576 public boolean afterInitialize() {
578 //do this bit after setting initialized to true or it will recurse
579 if ( operationQueue
!= null ) {
580 performQueuedOperations();
581 operationQueue
= null;
591 * Initialize the collection, if possible, wrapping any exceptions
592 * in a runtime exception
594 * @param writing currently obsolete
596 * @throws LazyInitializationException if we cannot initialize
598 protected final void initialize(final boolean writing
) {
599 // In remoting we are sure that session is null
600 // both when using property paths and switching off conversations
601 if(session
== null && remoting
) {
610 withTemporarySessionIfNeeded(
611 new LazyInitializationWork
<Object
>() {
613 public Object
doWork() {
614 session
.initializeCollection( AbstractPersistentCollection
.this, writing
);
621 private void throwLazyInitializationExceptionIfNotConnected() {
622 if ( !isConnectedToSession() ) {
623 throwLazyInitializationException( "no session or session was closed" );
625 if ( !session
.isConnected() ) {
626 throwLazyInitializationException( "session is disconnected" );
630 private void throwLazyInitializationException(String message
) {
631 throw new LazyInitializationException(
632 "failed to lazily initialize a collection" +
633 (role
== null ?
"" : " of role: " + role
) +
638 protected final void setInitialized() {
639 this.initializing
= false;
640 this.initialized
= true;
643 protected final void setDirectlyAccessible(boolean directlyAccessible
) {
644 this.directlyAccessible
= directlyAccessible
;
648 * Could the application possibly have a direct reference to
649 * the underlying collection implementation?
652 public boolean isDirectlyAccessible() {
653 return directlyAccessible
;
657 * Disassociate this collection from the given session.
659 * @return true if this was currently associated with the given session
662 public final boolean unsetSession(SessionImplementor currentSession
) {
663 prepareForPossibleSpecialSpecjInitialization();
664 if ( currentSession
== this.session
) {
673 protected void prepareForPossibleSpecialSpecjInitialization() {
674 if ( session
!= null ) {
675 specjLazyLoad
= session
.getFactory().getSettings().isInitializeLazyStateOutsideTransactionsEnabled();
677 if ( specjLazyLoad
&& sessionFactoryUuid
== null ) {
679 sessionFactoryUuid
= (String
) session
.getFactory().getReference().get( "uuid" ).getContent();
681 catch (NamingException e
) {
682 //not much we can do if this fails...
690 * Associate the collection with the given session.
692 * @return false if the collection was already associated with the session
694 * @throws HibernateException if the collection was already associated
695 * with another open session
698 public final boolean setCurrentSession(SessionImplementor session
) throws HibernateException
{
699 if ( session
== this.session
) {
703 if ( isConnectedToSession() ) {
704 CollectionEntry ce
= session
.getPersistenceContext().getCollectionEntry( this );
706 throw new HibernateException(
707 "Illegal attempt to associate a collection with two open sessions"
711 throw new HibernateException(
712 "Illegal attempt to associate a collection with two open sessions: " +
713 MessageHelper
.collectionInfoString(
714 ce
.getLoadedPersister(), this,
715 ce
.getLoadedKey(), session
721 this.session
= session
;
728 * Do we need to completely recreate this collection when it changes?
731 public boolean needsRecreate(CollectionPersister persister
) {
736 * To be called internally by the session, forcing
737 * immediate initialization.
740 public final void forceInitialization() throws HibernateException
{
741 if ( !initialized
) {
742 if ( initializing
) {
743 throw new AssertionFailure( "force initialize loading collection" );
745 if ( session
== null ) {
746 throw new HibernateException( "collection is not associated with any session" );
748 if ( !session
.isConnected() ) {
749 throw new HibernateException( "disconnected session" );
751 session
.initializeCollection( this, false );
757 * Get the current snapshot from the session
759 @SuppressWarnings({"JavaDoc"})
760 protected final Serializable
getSnapshot() {
761 return session
.getPersistenceContext().getSnapshot( this );
765 * Is this instance initialized?
768 public final boolean wasInitialized() {
773 public boolean isRowUpdatePossible() {
778 * Does this instance have any "queued" additions?
781 public final boolean hasQueuedOperations() {
782 return operationQueue
!= null;
786 * Iterate the "queued" additions
789 public final Iterator
queuedAdditionIterator() {
790 if ( hasQueuedOperations() ) {
791 return new Iterator() {
795 public Object
next() {
796 return operationQueue
.get( i
++ ).getAddedInstance();
800 public boolean hasNext() {
801 return i
< operationQueue
.size();
805 public void remove() {
806 throw new UnsupportedOperationException();
811 return EmptyIterator
.INSTANCE
;
816 * Iterate the "queued" additions
819 @SuppressWarnings({"unchecked"})
820 public final Collection
getQueuedOrphans(String entityName
) {
821 if ( hasQueuedOperations() ) {
822 Collection additions
= new ArrayList( operationQueue
.size() );
823 Collection removals
= new ArrayList( operationQueue
.size() );
824 for ( DelayedOperation operation
: operationQueue
) {
825 additions
.add( operation
.getAddedInstance() );
826 removals
.add( operation
.getOrphan() );
828 return getOrphans( removals
, additions
, entityName
, session
);
831 return Collections
.EMPTY_LIST
;
836 * Called before inserting rows, to ensure that any surrogate keys
837 * are fully generated
840 public void preInsert(CollectionPersister persister
) throws HibernateException
{
844 * Called after inserting a row, to fetch the natively generated id
847 public void afterRowInsert(CollectionPersister persister
, Object entry
, int i
) throws HibernateException
{
851 * get all "orphaned" elements
854 public abstract Collection
getOrphans(Serializable snapshot
, String entityName
) throws HibernateException
;
857 * Get the current session
859 @SuppressWarnings({"JavaDoc"})
860 public final SessionImplementor
getSession() {
864 protected final class IteratorProxy
implements Iterator
{
865 protected final Iterator itr
;
867 public IteratorProxy(Iterator itr
) {
872 public boolean hasNext() {
873 return itr
.hasNext();
877 public Object
next() {
882 public void remove() {
889 protected final class ListIteratorProxy
implements ListIterator
{
890 protected final ListIterator itr
;
892 public ListIteratorProxy(ListIterator itr
) {
897 @SuppressWarnings({"unchecked"})
898 public void add(Object o
) {
904 public boolean hasNext() {
905 return itr
.hasNext();
909 public boolean hasPrevious() {
910 return itr
.hasPrevious();
914 public Object
next() {
919 public int nextIndex() {
920 return itr
.nextIndex();
924 public Object
previous() {
925 return itr
.previous();
929 public int previousIndex() {
930 return itr
.previousIndex();
934 public void remove() {
940 @SuppressWarnings({"unchecked"})
941 public void set(Object o
) {
948 protected class SetProxy
implements java
.util
.Set
{
949 protected final Collection set
;
951 public SetProxy(Collection set
) {
956 @SuppressWarnings({"unchecked"})
957 public boolean add(Object o
) {
963 @SuppressWarnings({"unchecked"})
964 public boolean addAll(Collection c
) {
966 return set
.addAll( c
);
970 public void clear() {
976 public boolean contains(Object o
) {
977 return set
.contains( o
);
981 public boolean containsAll(Collection c
) {
982 return set
.containsAll( c
);
986 public boolean isEmpty() {
987 return set
.isEmpty();
991 public Iterator
iterator() {
992 return new IteratorProxy( set
.iterator() );
996 public boolean remove(Object o
) {
998 return set
.remove( o
);
1002 public boolean removeAll(Collection c
) {
1004 return set
.removeAll( c
);
1008 public boolean retainAll(Collection c
) {
1010 return set
.retainAll( c
);
1019 public Object
[] toArray() {
1020 return set
.toArray();
1024 @SuppressWarnings({"unchecked"})
1025 public Object
[] toArray(Object
[] array
) {
1026 return set
.toArray( array
);
1031 protected final class ListProxy
implements java
.util
.List
{
1032 protected final List list
;
1034 public ListProxy(List list
) {
1039 @SuppressWarnings({"unchecked"})
1040 public void add(int index
, Object value
) {
1042 list
.add( index
, value
);
1046 @SuppressWarnings({"unchecked"})
1047 public boolean add(Object o
) {
1049 return list
.add( o
);
1053 @SuppressWarnings({"unchecked"})
1054 public boolean addAll(Collection c
) {
1056 return list
.addAll( c
);
1060 @SuppressWarnings({"unchecked"})
1061 public boolean addAll(int i
, Collection c
) {
1063 return list
.addAll( i
, c
);
1067 public void clear() {
1073 public boolean contains(Object o
) {
1074 return list
.contains( o
);
1078 public boolean containsAll(Collection c
) {
1079 return list
.containsAll( c
);
1083 public Object
get(int i
) {
1084 return list
.get( i
);
1088 public int indexOf(Object o
) {
1089 return list
.indexOf( o
);
1093 public boolean isEmpty() {
1094 return list
.isEmpty();
1098 public Iterator
iterator() {
1099 return new IteratorProxy( list
.iterator() );
1103 public int lastIndexOf(Object o
) {
1104 return list
.lastIndexOf( o
);
1108 public ListIterator
listIterator() {
1109 return new ListIteratorProxy( list
.listIterator() );
1113 public ListIterator
listIterator(int i
) {
1114 return new ListIteratorProxy( list
.listIterator( i
) );
1118 public Object
remove(int i
) {
1120 return list
.remove( i
);
1124 public boolean remove(Object o
) {
1126 return list
.remove( o
);
1130 public boolean removeAll(Collection c
) {
1132 return list
.removeAll( c
);
1136 public boolean retainAll(Collection c
) {
1138 return list
.retainAll( c
);
1142 @SuppressWarnings({"unchecked"})
1143 public Object
set(int i
, Object o
) {
1145 return list
.set( i
, o
);
1154 public List
subList(int i
, int j
) {
1155 return list
.subList( i
, j
);
1159 public Object
[] toArray() {
1160 return list
.toArray();
1164 @SuppressWarnings({"unchecked"})
1165 public Object
[] toArray(Object
[] array
) {
1166 return list
.toArray( array
);
1172 * Contract for operations which are part of a collection's operation queue.
1174 protected interface DelayedOperation
{
1175 public void operate();
1177 public Object
getAddedInstance();
1179 public Object
getOrphan();
1183 * Given a collection of entity instances that used to
1184 * belong to the collection, and a collection of instances
1185 * that currently belong, return a collection of orphans
1187 @SuppressWarnings({"JavaDoc", "unchecked"})
1188 protected static Collection
getOrphans(
1189 Collection oldElements
,
1190 Collection currentElements
,
1192 SessionImplementor session
) throws HibernateException
{
1195 if ( currentElements
.size() == 0 ) {
1196 return oldElements
; // no new elements, the old list contains only Orphans
1198 if ( oldElements
.size() == 0 ) {
1199 return oldElements
; // no old elements, so no Orphans neither
1202 final EntityPersister entityPersister
= session
.getFactory().getEntityPersister( entityName
);
1203 final Type idType
= entityPersister
.getIdentifierType();
1205 // create the collection holding the Orphans
1206 Collection res
= new ArrayList();
1208 // collect EntityIdentifier(s) of the *current* elements - add them into a HashSet for fast access
1209 java
.util
.Set currentIds
= new HashSet();
1210 java
.util
.Set currentSaving
= new IdentitySet();
1211 for ( Object current
: currentElements
) {
1212 if ( current
!= null && ForeignKeys
.isNotTransient( entityName
, current
, null, session
) ) {
1213 EntityEntry ee
= session
.getPersistenceContext().getEntry( current
);
1214 if ( ee
!= null && ee
.getStatus() == Status
.SAVING
) {
1215 currentSaving
.add( current
);
1218 Serializable currentId
= ForeignKeys
.getEntityIdentifierIfNotUnsaved(
1223 currentIds
.add( new TypedValue( idType
, currentId
, entityPersister
.getEntityMode() ) );
1228 // iterate over the *old* list
1229 for ( Object old
: oldElements
) {
1230 if ( !currentSaving
.contains( old
) ) {
1231 Serializable oldId
= ForeignKeys
.getEntityIdentifierIfNotUnsaved( entityName
, old
, session
);
1232 if ( !currentIds
.contains( new TypedValue( idType
, oldId
, entityPersister
.getEntityMode() ) ) ) {
1241 public static void identityRemove(
1245 SessionImplementor session
) throws HibernateException
{
1247 if ( object
!= null && ForeignKeys
.isNotTransient( entityName
, object
, null, session
) ) {
1248 final EntityPersister entityPersister
= session
.getFactory().getEntityPersister( entityName
);
1249 Type idType
= entityPersister
.getIdentifierType();
1251 Serializable idOfCurrent
= ForeignKeys
.getEntityIdentifierIfNotUnsaved( entityName
, object
, session
);
1252 Iterator itr
= list
.iterator();
1253 while ( itr
.hasNext() ) {
1254 Serializable idOfOld
= ForeignKeys
.getEntityIdentifierIfNotUnsaved( entityName
, itr
.next(), session
);
1255 if ( idType
.isEqual( idOfCurrent
, idOfOld
, session
.getFactory() ) ) {
1265 public Object
getIdentifier(Object entry
, int i
) {
1266 throw new UnsupportedOperationException();
1270 public Object
getOwner() {
1275 public void setOwner(Object owner
) {
1279 /** ------ Below is section of code which makes remote service calls ----- */
1280 // The affected methods are :
1281 // initialize(final boolean writing)
1283 // readIndexExistence(final Object index)
1284 // readElementExistence(final Object element)
1285 // readElementByIndex(final Object index)
1287 private static ICdmApplicationConfiguration configuration
;
1288 private static boolean remoting
= false;
1290 public static void setConfiguration(ICdmApplicationConfiguration conf
) {
1291 configuration
= conf
;
1293 if(conf
instanceof CdmApplicationRemoteController
) {
1301 private void remoteInitialize() {
1303 if (getOwner() != null && !initialized
) {
1306 String role
= getRole();
1307 String fieldName
= role
.substring(role
.lastIndexOf(".") + 1);
1308 log
.info("--> Remote Lazy Initializing " + getRole() + " , key : " + getKey() + " , field : " + fieldName
);
1309 Object owner
= getOwner();
1311 if(configuration
== null) {
1312 throw new HibernateException("CdmApplicationRemoteConfiguration not initialized (null)");
1314 ICommonService commonService
= configuration
.getCommonService();
1315 if(commonService
== null) {
1316 throw new HibernateException("commonService not initialized (null)");
1319 // PersistentCollection col = commonService.initializeCollection(this);
1320 // afterInitialize();
1322 // Class<?> clazz = getClass();
1323 // if (clazz != null) {
1324 // CollectionField cf = getCollectionField(col);
1325 // Field field = clazz.getDeclaredField(cf.getFieldName());
1326 // field.setAccessible(true);
1327 // field.set(this, cf.getCollection());
1329 } catch (Exception ex
) {
1330 log
.warn(ex
.getMessage());
1332 log
.warn("This code is invalid");
1337 private CollectionField
getCollectionField(PersistentCollection pc
) {
1339 if(pc
instanceof PersistentSet
) {
1340 return new CollectionField(new HashSet((Set
)pc
), "set");
1342 if(pc
instanceof PersistentSortedSet
) {
1343 return new CollectionField(new TreeSet((Set
)pc
), "set");
1345 if(pc
instanceof PersistentList
) {
1346 return new CollectionField(new ArrayList((List
)pc
), "list");
1348 if(pc
instanceof PersistentMap
|| pc
instanceof PersistentMultiLanguageText
) {
1349 return new CollectionField(new HashMap((Map
)pc
), "map");
1351 if(pc
instanceof PersistentSortedMap
) {
1352 return new CollectionField(new TreeMap((Map
)pc
), "map");
1358 private String
getCollectionFieldName(PersistentCollection pc
) {
1360 if(pc
instanceof PersistentSet
|| pc
instanceof PersistentSortedSet
) {
1363 if(pc
instanceof PersistentList
) {
1366 if(pc
instanceof PersistentMap
|| pc
instanceof PersistentMultiLanguageText
) {
1373 private class CollectionField
{
1374 private final Object col
;
1375 private final String fieldName
;
1376 public CollectionField(Object col
, String fieldName
) {
1378 this.fieldName
= fieldName
;
1381 public Object
getCollection() {
1385 public String
getFieldName() {
1386 return this.fieldName
;
1390 public static boolean isInitialized(List list
) {
1391 return ((AbstractPersistentCollection
)list
).initialized
;
1394 public static boolean isInitialized(Map map
) {
1395 return ((AbstractPersistentCollection
)map
).initialized
;
1398 public static boolean isInitialized(Set set
) {
1399 return ((AbstractPersistentCollection
)set
).initialized
;