Fix remoting code compilation errors
[taxeditor.git] / eu.etaxonomy.taxeditor.cdmlib / src / main / java / org / hibernate / collection / internal / AbstractPersistentCollection.java
1
2
3 /*
4 * Hibernate, Relational Persistence for Idiomatic Java
5 *
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.
10 *
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.
14 *
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
18 * for more details.
19 *
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
25 */
26 package org.hibernate.collection.internal;
27
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;
37 import java.util.Map;
38 import java.util.Set;
39 import java.util.TreeMap;
40 import java.util.TreeSet;
41
42 import javax.naming.NamingException;
43
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;
65
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;
70
71 /**
72 * Base class implementing {@link org.hibernate.collection.spi.PersistentCollection}
73 *
74 * @author Gavin King
75 */
76 public abstract class AbstractPersistentCollection implements Serializable, PersistentCollection {
77 private static final Logger log = Logger.getLogger( AbstractPersistentCollection.class );
78
79 private static final long serialVersionUID = -7238232378593030571L;
80
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;
86 private Object owner;
87 private int cachedSize = -1;
88
89 private String role;
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;
95
96 private String sessionFactoryUuid;
97 private boolean specjLazyLoad = false;
98
99 @Override
100 public final String getRole() {
101 return role;
102 }
103
104 @Override
105 public final Serializable getKey() {
106 return key;
107 }
108
109 @Override
110 public final boolean isUnreferenced() {
111 return role == null;
112 }
113
114 @Override
115 public final boolean isDirty() {
116 return dirty;
117 }
118
119 @Override
120 public final void clearDirty() {
121 dirty = false;
122 }
123
124 @Override
125 public final void dirty() {
126 dirty = true;
127 }
128
129 @Override
130 public final Serializable getStoredSnapshot() {
131 return storedSnapshot;
132 }
133
134 //Careful: these methods do not initialize the collection.
135
136 /**
137 * Is the initialized collection empty?
138 */
139 @Override
140 public abstract boolean empty();
141
142 /**
143 * Called by any read-only method of the collection interface
144 */
145 protected final void read() {
146 initialize( false );
147 }
148
149 /**
150 * Called by the {@link Collection#size} method
151 */
152 @SuppressWarnings({"JavaDoc"})
153 protected boolean readSize() {
154 if ( !initialized ) {
155 if ( cachedSize != -1 && !hasQueuedOperations() ) {
156 return true;
157 }
158 else {
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());
163 read();
164 } else {
165 boolean isExtraLazy = withTemporarySessionIfNeeded(
166 new LazyInitializationWork<Boolean>() {
167 @Override
168 public Boolean doWork() {
169 CollectionEntry entry = session.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection.this );
170
171 if ( entry != null ) {
172 CollectionPersister persister = entry.getLoadedPersister();
173 if ( persister.isExtraLazy() ) {
174 if ( hasQueuedOperations() ) {
175 session.flush();
176 }
177 cachedSize = persister.getSize( entry.getLoadedKey(), session );
178 return true;
179 }
180 else {
181 read();
182 }
183 }
184 else{
185 throwLazyInitializationExceptionIfNotConnected();
186 }
187 return false;
188 }
189 }
190 );
191 if ( isExtraLazy ) {
192 return true;
193 }
194 }
195 }
196 }
197 return false;
198 }
199
200 public static interface LazyInitializationWork<T> {
201 public T doWork();
202 }
203
204 private <T> T withTemporarySessionIfNeeded(LazyInitializationWork<T> lazyInitializationWork) {
205 SessionImplementor originalSession = null;
206 boolean isTempSession = false;
207 boolean isJTA = false;
208
209 if ( session == null ) {
210 if ( specjLazyLoad ) {
211 session = openTemporarySessionForLoading();
212 isTempSession = true;
213 }
214 else {
215 throwLazyInitializationException( "could not initialize proxy - no Session" );
216 }
217 }
218 else if ( !session.isOpen() ) {
219 if ( specjLazyLoad ) {
220 originalSession = session;
221 session = openTemporarySessionForLoading();
222 isTempSession = true;
223 }
224 else {
225 throwLazyInitializationException( "could not initialize proxy - the owning Session was closed" );
226 }
227 }
228 else if ( !session.isConnected() ) {
229 if ( specjLazyLoad ) {
230 originalSession = session;
231 session = openTemporarySessionForLoading();
232 isTempSession = true;
233 }
234 else {
235 throwLazyInitializationException( "could not initialize proxy - the owning Session is disconnected" );
236 }
237 }
238
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();
246
247 if ( !isJTA ) {
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();
254 }
255
256 session.getPersistenceContext().addUninitializedDetachedCollection(
257 session.getFactory().getCollectionPersister( getRole() ),
258 this
259 );
260 }
261
262 try {
263 return lazyInitializationWork.doWork();
264 }
265 finally {
266 if ( isTempSession ) {
267 // make sure the just opened temp session gets closed!
268 try {
269 if ( !isJTA ) {
270 ( ( Session) session ).getTransaction().commit();
271 }
272 ( (Session) session ).close();
273 }
274 catch (Exception e) {
275 log.warn( "Unable to close temporary session used to load lazy collection associated to no session" );
276 }
277 session = originalSession;
278 }
279 }
280 }
281
282 private SessionImplementor openTemporarySessionForLoading() {
283 if ( sessionFactoryUuid == null ) {
284 throwLazyInitializationException( "SessionFactory UUID not known to create temporary Session for loading" );
285 }
286
287 SessionFactoryImplementor sf = (SessionFactoryImplementor)
288 SessionFactoryRegistry.INSTANCE.getSessionFactory( sessionFactoryUuid );
289 return (SessionImplementor) sf.openSession();
290 }
291
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());
298 read();
299 } else {
300 Boolean extraLazyExistenceCheck = withTemporarySessionIfNeeded(
301 new LazyInitializationWork<Boolean>() {
302 @Override
303 public Boolean doWork() {
304 CollectionEntry entry = session.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection.this );
305 CollectionPersister persister = entry.getLoadedPersister();
306 if ( persister.isExtraLazy() ) {
307 if ( hasQueuedOperations() ) {
308 session.flush();
309 }
310 return persister.indexExists( entry.getLoadedKey(), index, session );
311 }
312 else {
313 read();
314 }
315 return null;
316 }
317 }
318 );
319 if ( extraLazyExistenceCheck != null ) {
320 return extraLazyExistenceCheck;
321 }
322 }
323 }
324 return null;
325 }
326
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());
333 read();
334
335 } else {
336 Boolean extraLazyExistenceCheck = withTemporarySessionIfNeeded(
337 new LazyInitializationWork<Boolean>() {
338 @Override
339 public Boolean doWork() {
340 CollectionEntry entry = session.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection.this );
341 CollectionPersister persister = entry.getLoadedPersister();
342 if ( persister.isExtraLazy() ) {
343 if ( hasQueuedOperations() ) {
344 session.flush();
345 }
346 return persister.elementExists( entry.getLoadedKey(), element, session );
347 }
348 else {
349 read();
350 }
351 return null;
352 }
353 }
354 );
355 if ( extraLazyExistenceCheck != null ) {
356 return extraLazyExistenceCheck;
357 }
358 }
359 }
360 return null;
361 }
362
363 protected static final Object UNKNOWN = new MarkerObject( "UNKNOWN" );
364
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());
371 read();
372
373 } else {
374 class ExtraLazyElementByIndexReader implements LazyInitializationWork {
375 private boolean isExtraLazy;
376 private Object element;
377
378 @Override
379 public Object doWork() {
380 CollectionEntry entry = session.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection.this );
381 CollectionPersister persister = entry.getLoadedPersister();
382 isExtraLazy = persister.isExtraLazy();
383 if ( isExtraLazy ) {
384 if ( hasQueuedOperations() ) {
385 session.flush();
386 }
387 element = persister.getElementByIndex( entry.getLoadedKey(), index, session, owner );
388 }
389 else {
390 read();
391 }
392 return null;
393 }
394 }
395
396 ExtraLazyElementByIndexReader reader = new ExtraLazyElementByIndexReader();
397 //noinspection unchecked
398 withTemporarySessionIfNeeded( reader );
399 if ( reader.isExtraLazy ) {
400 return reader.element;
401 }
402 }
403 }
404 return UNKNOWN;
405
406 }
407
408 protected int getCachedSize() {
409 return cachedSize;
410 }
411
412 private boolean isConnectedToSession() {
413 return session != null &&
414 session.isOpen() &&
415 session.getPersistenceContext().containsCollection( this );
416 }
417
418 /**
419 * Called by any writer method of the collection interface
420 */
421 protected final void write() {
422 initialize( true );
423 dirty();
424 }
425
426 /**
427 * Is this collection in a state that would allow us to
428 * "queue" operations?
429 */
430 @SuppressWarnings({"JavaDoc"})
431 protected boolean isOperationQueueEnabled() {
432 return !initialized &&
433 isConnectedToSession() &&
434 isInverseCollection();
435 }
436
437 /**
438 * Is this collection in a state that would allow us to
439 * "queue" puts? This is a special case, because of orphan
440 * delete.
441 */
442 @SuppressWarnings({"JavaDoc"})
443 protected boolean isPutQueueEnabled() {
444 return !initialized &&
445 isConnectedToSession() &&
446 isInverseOneToManyOrNoOrphanDelete();
447 }
448
449 /**
450 * Is this collection in a state that would allow us to
451 * "queue" clear? This is a special case, because of orphan
452 * delete.
453 */
454 @SuppressWarnings({"JavaDoc"})
455 protected boolean isClearQueueEnabled() {
456 return !initialized &&
457 isConnectedToSession() &&
458 isInverseCollectionNoOrphanDelete();
459 }
460
461 /**
462 * Is this the "inverse" end of a bidirectional association?
463 */
464 @SuppressWarnings({"JavaDoc"})
465 private boolean isInverseCollection() {
466 CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this );
467 return ce != null && ce.getLoadedPersister().isInverse();
468 }
469
470 /**
471 * Is this the "inverse" end of a bidirectional association with
472 * no orphan delete enabled?
473 */
474 @SuppressWarnings({"JavaDoc"})
475 private boolean isInverseCollectionNoOrphanDelete() {
476 CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this );
477 return ce != null &&
478 ce.getLoadedPersister().isInverse() &&
479 !ce.getLoadedPersister().hasOrphanDelete();
480 }
481
482 /**
483 * Is this the "inverse" end of a bidirectional one-to-many, or
484 * of a collection with no orphan delete?
485 */
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()
492 );
493 }
494
495 /**
496 * Queue an addition
497 */
498 @SuppressWarnings({"JavaDoc"})
499 protected final void queueOperation(DelayedOperation operation) {
500 if ( operationQueue == null ) {
501 operationQueue = new ArrayList<DelayedOperation>( 10 );
502 }
503 operationQueue.add( operation );
504 dirty = true; //needed so that we remove this collection from the second-level cache
505 }
506
507 /**
508 * After reading all existing elements from the database,
509 * add the queued elements to the underlying collection.
510 */
511 protected final void performQueuedOperations() {
512 for ( DelayedOperation operation : operationQueue ) {
513 operation.operate();
514 }
515 }
516
517 /**
518 * After flushing, re-init snapshot state.
519 */
520 @Override
521 public void setSnapshot(Serializable key, String role, Serializable snapshot) {
522 this.key = key;
523 this.role = role;
524 this.storedSnapshot = snapshot;
525 }
526
527 /**
528 * After flushing, clear any "queued" additions, since the
529 * database state is now synchronized with the memory state.
530 */
531 @Override
532 public void postAction() {
533 operationQueue = null;
534 cachedSize = -1;
535 clearDirty();
536 }
537
538 /**
539 * Not called by Hibernate, but used by non-JDK serialization,
540 * eg. SOAP libraries.
541 */
542 public AbstractPersistentCollection() {
543 }
544
545 protected AbstractPersistentCollection(SessionImplementor session) {
546 this.session = session;
547 }
548
549 /**
550 * return the user-visible collection (or array) instance
551 */
552 @Override
553 public Object getValue() {
554 return this;
555 }
556
557 /**
558 * Called just before reading any rows from the JDBC result set
559 */
560 @Override
561 public void beginRead() {
562 // override on some subclasses
563 initializing = true;
564 }
565
566 /**
567 * Called after reading all rows from the JDBC result set
568 */
569 @Override
570 public boolean endRead() {
571 //override on some subclasses
572 return afterInitialize();
573 }
574
575 @Override
576 public boolean afterInitialize() {
577 setInitialized();
578 //do this bit after setting initialized to true or it will recurse
579 if ( operationQueue != null ) {
580 performQueuedOperations();
581 operationQueue = null;
582 cachedSize = -1;
583 return false;
584 }
585 else {
586 return true;
587 }
588 }
589
590 /**
591 * Initialize the collection, if possible, wrapping any exceptions
592 * in a runtime exception
593 *
594 * @param writing currently obsolete
595 *
596 * @throws LazyInitializationException if we cannot initialize
597 */
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) {
602 remoteInitialize();
603 }
604
605 if ( initialized ) {
606 return;
607 }
608
609
610 withTemporarySessionIfNeeded(
611 new LazyInitializationWork<Object>() {
612 @Override
613 public Object doWork() {
614 session.initializeCollection( AbstractPersistentCollection.this, writing );
615 return null;
616 }
617 }
618 );
619 }
620
621 private void throwLazyInitializationExceptionIfNotConnected() {
622 if ( !isConnectedToSession() ) {
623 throwLazyInitializationException( "no session or session was closed" );
624 }
625 if ( !session.isConnected() ) {
626 throwLazyInitializationException( "session is disconnected" );
627 }
628 }
629
630 private void throwLazyInitializationException(String message) {
631 throw new LazyInitializationException(
632 "failed to lazily initialize a collection" +
633 (role == null ? "" : " of role: " + role) +
634 ", " + message
635 );
636 }
637
638 protected final void setInitialized() {
639 this.initializing = false;
640 this.initialized = true;
641 }
642
643 protected final void setDirectlyAccessible(boolean directlyAccessible) {
644 this.directlyAccessible = directlyAccessible;
645 }
646
647 /**
648 * Could the application possibly have a direct reference to
649 * the underlying collection implementation?
650 */
651 @Override
652 public boolean isDirectlyAccessible() {
653 return directlyAccessible;
654 }
655
656 /**
657 * Disassociate this collection from the given session.
658 *
659 * @return true if this was currently associated with the given session
660 */
661 @Override
662 public final boolean unsetSession(SessionImplementor currentSession) {
663 prepareForPossibleSpecialSpecjInitialization();
664 if ( currentSession == this.session ) {
665 this.session = null;
666 return true;
667 }
668 else {
669 return false;
670 }
671 }
672
673 protected void prepareForPossibleSpecialSpecjInitialization() {
674 if ( session != null ) {
675 specjLazyLoad = session.getFactory().getSettings().isInitializeLazyStateOutsideTransactionsEnabled();
676
677 if ( specjLazyLoad && sessionFactoryUuid == null ) {
678 try {
679 sessionFactoryUuid = (String) session.getFactory().getReference().get( "uuid" ).getContent();
680 }
681 catch (NamingException e) {
682 //not much we can do if this fails...
683 }
684 }
685 }
686 }
687
688
689 /**
690 * Associate the collection with the given session.
691 *
692 * @return false if the collection was already associated with the session
693 *
694 * @throws HibernateException if the collection was already associated
695 * with another open session
696 */
697 @Override
698 public final boolean setCurrentSession(SessionImplementor session) throws HibernateException {
699 if ( session == this.session ) {
700 return false;
701 }
702 else {
703 if ( isConnectedToSession() ) {
704 CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this );
705 if ( ce == null ) {
706 throw new HibernateException(
707 "Illegal attempt to associate a collection with two open sessions"
708 );
709 }
710 else {
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
716 )
717 );
718 }
719 }
720 else {
721 this.session = session;
722 return true;
723 }
724 }
725 }
726
727 /**
728 * Do we need to completely recreate this collection when it changes?
729 */
730 @Override
731 public boolean needsRecreate(CollectionPersister persister) {
732 return false;
733 }
734
735 /**
736 * To be called internally by the session, forcing
737 * immediate initialization.
738 */
739 @Override
740 public final void forceInitialization() throws HibernateException {
741 if ( !initialized ) {
742 if ( initializing ) {
743 throw new AssertionFailure( "force initialize loading collection" );
744 }
745 if ( session == null ) {
746 throw new HibernateException( "collection is not associated with any session" );
747 }
748 if ( !session.isConnected() ) {
749 throw new HibernateException( "disconnected session" );
750 }
751 session.initializeCollection( this, false );
752 }
753 }
754
755
756 /**
757 * Get the current snapshot from the session
758 */
759 @SuppressWarnings({"JavaDoc"})
760 protected final Serializable getSnapshot() {
761 return session.getPersistenceContext().getSnapshot( this );
762 }
763
764 /**
765 * Is this instance initialized?
766 */
767 @Override
768 public final boolean wasInitialized() {
769 return initialized;
770 }
771
772 @Override
773 public boolean isRowUpdatePossible() {
774 return true;
775 }
776
777 /**
778 * Does this instance have any "queued" additions?
779 */
780 @Override
781 public final boolean hasQueuedOperations() {
782 return operationQueue != null;
783 }
784
785 /**
786 * Iterate the "queued" additions
787 */
788 @Override
789 public final Iterator queuedAdditionIterator() {
790 if ( hasQueuedOperations() ) {
791 return new Iterator() {
792 int i = 0;
793
794 @Override
795 public Object next() {
796 return operationQueue.get( i++ ).getAddedInstance();
797 }
798
799 @Override
800 public boolean hasNext() {
801 return i < operationQueue.size();
802 }
803
804 @Override
805 public void remove() {
806 throw new UnsupportedOperationException();
807 }
808 };
809 }
810 else {
811 return EmptyIterator.INSTANCE;
812 }
813 }
814
815 /**
816 * Iterate the "queued" additions
817 */
818 @Override
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() );
827 }
828 return getOrphans( removals, additions, entityName, session );
829 }
830 else {
831 return Collections.EMPTY_LIST;
832 }
833 }
834
835 /**
836 * Called before inserting rows, to ensure that any surrogate keys
837 * are fully generated
838 */
839 @Override
840 public void preInsert(CollectionPersister persister) throws HibernateException {
841 }
842
843 /**
844 * Called after inserting a row, to fetch the natively generated id
845 */
846 @Override
847 public void afterRowInsert(CollectionPersister persister, Object entry, int i) throws HibernateException {
848 }
849
850 /**
851 * get all "orphaned" elements
852 */
853 @Override
854 public abstract Collection getOrphans(Serializable snapshot, String entityName) throws HibernateException;
855
856 /**
857 * Get the current session
858 */
859 @SuppressWarnings({"JavaDoc"})
860 public final SessionImplementor getSession() {
861 return session;
862 }
863
864 protected final class IteratorProxy implements Iterator {
865 protected final Iterator itr;
866
867 public IteratorProxy(Iterator itr) {
868 this.itr = itr;
869 }
870
871 @Override
872 public boolean hasNext() {
873 return itr.hasNext();
874 }
875
876 @Override
877 public Object next() {
878 return itr.next();
879 }
880
881 @Override
882 public void remove() {
883 write();
884 itr.remove();
885 }
886
887 }
888
889 protected final class ListIteratorProxy implements ListIterator {
890 protected final ListIterator itr;
891
892 public ListIteratorProxy(ListIterator itr) {
893 this.itr = itr;
894 }
895
896 @Override
897 @SuppressWarnings({"unchecked"})
898 public void add(Object o) {
899 write();
900 itr.add( o );
901 }
902
903 @Override
904 public boolean hasNext() {
905 return itr.hasNext();
906 }
907
908 @Override
909 public boolean hasPrevious() {
910 return itr.hasPrevious();
911 }
912
913 @Override
914 public Object next() {
915 return itr.next();
916 }
917
918 @Override
919 public int nextIndex() {
920 return itr.nextIndex();
921 }
922
923 @Override
924 public Object previous() {
925 return itr.previous();
926 }
927
928 @Override
929 public int previousIndex() {
930 return itr.previousIndex();
931 }
932
933 @Override
934 public void remove() {
935 write();
936 itr.remove();
937 }
938
939 @Override
940 @SuppressWarnings({"unchecked"})
941 public void set(Object o) {
942 write();
943 itr.set( o );
944 }
945
946 }
947
948 protected class SetProxy implements java.util.Set {
949 protected final Collection set;
950
951 public SetProxy(Collection set) {
952 this.set = set;
953 }
954
955 @Override
956 @SuppressWarnings({"unchecked"})
957 public boolean add(Object o) {
958 write();
959 return set.add( o );
960 }
961
962 @Override
963 @SuppressWarnings({"unchecked"})
964 public boolean addAll(Collection c) {
965 write();
966 return set.addAll( c );
967 }
968
969 @Override
970 public void clear() {
971 write();
972 set.clear();
973 }
974
975 @Override
976 public boolean contains(Object o) {
977 return set.contains( o );
978 }
979
980 @Override
981 public boolean containsAll(Collection c) {
982 return set.containsAll( c );
983 }
984
985 @Override
986 public boolean isEmpty() {
987 return set.isEmpty();
988 }
989
990 @Override
991 public Iterator iterator() {
992 return new IteratorProxy( set.iterator() );
993 }
994
995 @Override
996 public boolean remove(Object o) {
997 write();
998 return set.remove( o );
999 }
1000
1001 @Override
1002 public boolean removeAll(Collection c) {
1003 write();
1004 return set.removeAll( c );
1005 }
1006
1007 @Override
1008 public boolean retainAll(Collection c) {
1009 write();
1010 return set.retainAll( c );
1011 }
1012
1013 @Override
1014 public int size() {
1015 return set.size();
1016 }
1017
1018 @Override
1019 public Object[] toArray() {
1020 return set.toArray();
1021 }
1022
1023 @Override
1024 @SuppressWarnings({"unchecked"})
1025 public Object[] toArray(Object[] array) {
1026 return set.toArray( array );
1027 }
1028
1029 }
1030
1031 protected final class ListProxy implements java.util.List {
1032 protected final List list;
1033
1034 public ListProxy(List list) {
1035 this.list = list;
1036 }
1037
1038 @Override
1039 @SuppressWarnings({"unchecked"})
1040 public void add(int index, Object value) {
1041 write();
1042 list.add( index, value );
1043 }
1044
1045 @Override
1046 @SuppressWarnings({"unchecked"})
1047 public boolean add(Object o) {
1048 write();
1049 return list.add( o );
1050 }
1051
1052 @Override
1053 @SuppressWarnings({"unchecked"})
1054 public boolean addAll(Collection c) {
1055 write();
1056 return list.addAll( c );
1057 }
1058
1059 @Override
1060 @SuppressWarnings({"unchecked"})
1061 public boolean addAll(int i, Collection c) {
1062 write();
1063 return list.addAll( i, c );
1064 }
1065
1066 @Override
1067 public void clear() {
1068 write();
1069 list.clear();
1070 }
1071
1072 @Override
1073 public boolean contains(Object o) {
1074 return list.contains( o );
1075 }
1076
1077 @Override
1078 public boolean containsAll(Collection c) {
1079 return list.containsAll( c );
1080 }
1081
1082 @Override
1083 public Object get(int i) {
1084 return list.get( i );
1085 }
1086
1087 @Override
1088 public int indexOf(Object o) {
1089 return list.indexOf( o );
1090 }
1091
1092 @Override
1093 public boolean isEmpty() {
1094 return list.isEmpty();
1095 }
1096
1097 @Override
1098 public Iterator iterator() {
1099 return new IteratorProxy( list.iterator() );
1100 }
1101
1102 @Override
1103 public int lastIndexOf(Object o) {
1104 return list.lastIndexOf( o );
1105 }
1106
1107 @Override
1108 public ListIterator listIterator() {
1109 return new ListIteratorProxy( list.listIterator() );
1110 }
1111
1112 @Override
1113 public ListIterator listIterator(int i) {
1114 return new ListIteratorProxy( list.listIterator( i ) );
1115 }
1116
1117 @Override
1118 public Object remove(int i) {
1119 write();
1120 return list.remove( i );
1121 }
1122
1123 @Override
1124 public boolean remove(Object o) {
1125 write();
1126 return list.remove( o );
1127 }
1128
1129 @Override
1130 public boolean removeAll(Collection c) {
1131 write();
1132 return list.removeAll( c );
1133 }
1134
1135 @Override
1136 public boolean retainAll(Collection c) {
1137 write();
1138 return list.retainAll( c );
1139 }
1140
1141 @Override
1142 @SuppressWarnings({"unchecked"})
1143 public Object set(int i, Object o) {
1144 write();
1145 return list.set( i, o );
1146 }
1147
1148 @Override
1149 public int size() {
1150 return list.size();
1151 }
1152
1153 @Override
1154 public List subList(int i, int j) {
1155 return list.subList( i, j );
1156 }
1157
1158 @Override
1159 public Object[] toArray() {
1160 return list.toArray();
1161 }
1162
1163 @Override
1164 @SuppressWarnings({"unchecked"})
1165 public Object[] toArray(Object[] array) {
1166 return list.toArray( array );
1167 }
1168
1169 }
1170
1171 /**
1172 * Contract for operations which are part of a collection's operation queue.
1173 */
1174 protected interface DelayedOperation {
1175 public void operate();
1176
1177 public Object getAddedInstance();
1178
1179 public Object getOrphan();
1180 }
1181
1182 /**
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
1186 */
1187 @SuppressWarnings({"JavaDoc", "unchecked"})
1188 protected static Collection getOrphans(
1189 Collection oldElements,
1190 Collection currentElements,
1191 String entityName,
1192 SessionImplementor session) throws HibernateException {
1193
1194 // short-circuit(s)
1195 if ( currentElements.size() == 0 ) {
1196 return oldElements; // no new elements, the old list contains only Orphans
1197 }
1198 if ( oldElements.size() == 0 ) {
1199 return oldElements; // no old elements, so no Orphans neither
1200 }
1201
1202 final EntityPersister entityPersister = session.getFactory().getEntityPersister( entityName );
1203 final Type idType = entityPersister.getIdentifierType();
1204
1205 // create the collection holding the Orphans
1206 Collection res = new ArrayList();
1207
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 );
1216 }
1217 else {
1218 Serializable currentId = ForeignKeys.getEntityIdentifierIfNotUnsaved(
1219 entityName,
1220 current,
1221 session
1222 );
1223 currentIds.add( new TypedValue( idType, currentId, entityPersister.getEntityMode() ) );
1224 }
1225 }
1226 }
1227
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() ) ) ) {
1233 res.add( old );
1234 }
1235 }
1236 }
1237
1238 return res;
1239 }
1240
1241 public static void identityRemove(
1242 Collection list,
1243 Object object,
1244 String entityName,
1245 SessionImplementor session) throws HibernateException {
1246
1247 if ( object != null && ForeignKeys.isNotTransient( entityName, object, null, session ) ) {
1248 final EntityPersister entityPersister = session.getFactory().getEntityPersister( entityName );
1249 Type idType = entityPersister.getIdentifierType();
1250
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() ) ) {
1256 itr.remove();
1257 break;
1258 }
1259 }
1260
1261 }
1262 }
1263
1264 @Override
1265 public Object getIdentifier(Object entry, int i) {
1266 throw new UnsupportedOperationException();
1267 }
1268
1269 @Override
1270 public Object getOwner() {
1271 return owner;
1272 }
1273
1274 @Override
1275 public void setOwner(Object owner) {
1276 this.owner = owner;
1277 }
1278
1279 /** ------ Below is section of code which makes remote service calls ----- */
1280 // The affected methods are :
1281 // initialize(final boolean writing)
1282 // readSize()
1283 // readIndexExistence(final Object index)
1284 // readElementExistence(final Object element)
1285 // readElementByIndex(final Object index)
1286
1287 private static ICdmApplicationConfiguration configuration;
1288 private static boolean remoting = false;
1289
1290 public static void setConfiguration(ICdmApplicationConfiguration conf) {
1291 configuration = conf;
1292
1293 if(conf instanceof CdmApplicationRemoteController) {
1294 remoting = true;
1295 } else {
1296 remoting = false;
1297 }
1298 }
1299
1300
1301 private void remoteInitialize() {
1302
1303 if (getOwner() != null && !initialized) {
1304
1305 try {
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();
1310
1311 if(configuration == null) {
1312 throw new HibernateException("CdmApplicationRemoteConfiguration not initialized (null)");
1313 }
1314 ICommonService commonService = configuration.getCommonService();
1315 if(commonService == null) {
1316 throw new HibernateException("commonService not initialized (null)");
1317 }
1318
1319 // PersistentCollection col = commonService.initializeCollection(this);
1320 // afterInitialize();
1321 //
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());
1328 // }
1329 } catch (Exception ex) {
1330 log.warn(ex.getMessage());
1331 }
1332 log.warn("This code is invalid");
1333 }
1334 }
1335
1336
1337 private CollectionField getCollectionField(PersistentCollection pc) {
1338 if(pc != null) {
1339 if(pc instanceof PersistentSet) {
1340 return new CollectionField(new HashSet((Set)pc), "set");
1341 }
1342 if(pc instanceof PersistentSortedSet) {
1343 return new CollectionField(new TreeSet((Set)pc), "set");
1344 }
1345 if(pc instanceof PersistentList) {
1346 return new CollectionField(new ArrayList((List)pc), "list");
1347 }
1348 if(pc instanceof PersistentMap || pc instanceof PersistentMultiLanguageText) {
1349 return new CollectionField(new HashMap((Map)pc), "map");
1350 }
1351 if(pc instanceof PersistentSortedMap) {
1352 return new CollectionField(new TreeMap((Map)pc), "map");
1353 }
1354 }
1355 return null;
1356 }
1357
1358 private String getCollectionFieldName(PersistentCollection pc) {
1359 if(pc != null) {
1360 if(pc instanceof PersistentSet || pc instanceof PersistentSortedSet) {
1361 return "set";
1362 }
1363 if(pc instanceof PersistentList) {
1364 return "list";
1365 }
1366 if(pc instanceof PersistentMap || pc instanceof PersistentMultiLanguageText) {
1367 return "map";
1368 }
1369 }
1370 return null;
1371 }
1372
1373 private class CollectionField {
1374 private final Object col;
1375 private final String fieldName;
1376 public CollectionField(Object col, String fieldName) {
1377 this.col = col;
1378 this.fieldName = fieldName;
1379 }
1380
1381 public Object getCollection() {
1382 return this.col;
1383 }
1384
1385 public String getFieldName() {
1386 return this.fieldName;
1387 }
1388 }
1389
1390 public static boolean isInitialized(List list) {
1391 return ((AbstractPersistentCollection)list).initialized;
1392 }
1393
1394 public static boolean isInitialized(Map map) {
1395 return ((AbstractPersistentCollection)map).initialized;
1396 }
1397
1398 public static boolean isInitialized(Set set) {
1399 return ((AbstractPersistentCollection)set).initialized;
1400 }
1401
1402
1403 }
1404