import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
+import java.util.Map;
import javax.naming.NamingException;
import org.hibernate.HibernateException;
import org.hibernate.LazyInitializationException;
import org.hibernate.Session;
+import org.hibernate.collection.internal.AbstractPersistentCollection.DelayedOperation;
+import org.hibernate.collection.internal.AbstractPersistentCollection.IteratorProxy;
+import org.hibernate.collection.internal.AbstractPersistentCollection.ListIteratorProxy;
+import org.hibernate.collection.internal.AbstractPersistentCollection.ValueDelayedOperation;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.internal.ForeignKeys;
import org.hibernate.engine.spi.CollectionEntry;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.pretty.MessageHelper;
+import org.hibernate.type.IntegerType;
+import org.hibernate.type.LongType;
+import org.hibernate.type.PostgresUUIDType;
+import org.hibernate.type.StringType;
import org.hibernate.type.Type;
+import org.hibernate.type.UUIDBinaryType;
+import org.hibernate.type.UUIDCharType;
import org.jboss.logging.Logger;
import eu.etaxonomy.cdm.api.application.CdmApplicationRemoteConfiguration;
private String sessionFactoryUuid;
private boolean specjLazyLoad = false;
+ /**
+ * Not called by Hibernate, but used by non-JDK serialization,
+ * eg. SOAP libraries.
+ */
+ public AbstractPersistentCollection() {
+ }
+
+ protected AbstractPersistentCollection(SessionImplementor session) {
+ this.session = session;
+ }
+
@Override
- public final String getRole() {
+ public final String getRole() {
return role;
}
@Override
- public final Serializable getKey() {
+ public final Serializable getKey() {
return key;
}
@Override
- public final boolean isUnreferenced() {
+ public final boolean isUnreferenced() {
return role == null;
}
@Override
- public final boolean isDirty() {
+ public final boolean isDirty() {
return dirty;
}
@Override
- public final void clearDirty() {
+ public final void clearDirty() {
dirty = false;
}
@Override
- public final void dirty() {
+ public final void dirty() {
dirty = true;
}
@Override
- public final Serializable getStoredSnapshot() {
+ public final Serializable getStoredSnapshot() {
return storedSnapshot;
}
//Careful: these methods do not initialize the collection.
- /**
- * Is the initialized collection empty?
- */
@Override
- public abstract boolean empty();
+ public abstract boolean empty();
/**
* Called by any read-only method of the collection interface
return false;
}
+ /**
+ * TBH not sure why this is public
+ *
+ * @param <T> The java type of the return for this LazyInitializationWork
+ */
public static interface LazyInitializationWork<T> {
+ /**
+ * Do the represented work and return the result.
+ *
+ * @return The result
+ */
public T doWork();
}
return cachedSize;
}
- private boolean isConnectedToSession() {
- return session != null &&
- session.isOpen() &&
- session.getPersistenceContext().containsCollection( this );
+ protected boolean isConnectedToSession() {
+ return session != null
+ && session.isOpen()
+ && session.getPersistenceContext().containsCollection( this );
+ }
+
+ protected boolean isInitialized() {
+ return initialized;
}
/**
*/
@SuppressWarnings({"JavaDoc"})
protected boolean isOperationQueueEnabled() {
- return !initialized &&
- isConnectedToSession() &&
- isInverseCollection();
+ return !initialized
+ && isConnectedToSession()
+ && isInverseCollection();
}
/**
*/
@SuppressWarnings({"JavaDoc"})
protected boolean isPutQueueEnabled() {
- return !initialized &&
- isConnectedToSession() &&
- isInverseOneToManyOrNoOrphanDelete();
+ return !initialized
+ && isConnectedToSession()
+ && isInverseOneToManyOrNoOrphanDelete();
}
/**
*/
@SuppressWarnings({"JavaDoc"})
protected boolean isClearQueueEnabled() {
- return !initialized &&
- isConnectedToSession() &&
- isInverseCollectionNoOrphanDelete();
+ return !initialized
+ && isConnectedToSession()
+ && isInverseCollectionNoOrphanDelete();
}
/**
* Is this the "inverse" end of a bidirectional association?
*/
@SuppressWarnings({"JavaDoc"})
- private boolean isInverseCollection() {
- CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this );
+ protected boolean isInverseCollection() {
+ final CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this );
return ce != null && ce.getLoadedPersister().isInverse();
}
* no orphan delete enabled?
*/
@SuppressWarnings({"JavaDoc"})
- private boolean isInverseCollectionNoOrphanDelete() {
- CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this );
- return ce != null &&
+ protected boolean isInverseCollectionNoOrphanDelete() {
+ final CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this );
+ return ce != null
+ &&
ce.getLoadedPersister().isInverse() &&
!ce.getLoadedPersister().hasOrphanDelete();
}
* of a collection with no orphan delete?
*/
@SuppressWarnings({"JavaDoc"})
- private boolean isInverseOneToManyOrNoOrphanDelete() {
- CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this );
- return ce != null && ce.getLoadedPersister().isInverse() && (
- ce.getLoadedPersister().isOneToMany() ||
- !ce.getLoadedPersister().hasOrphanDelete()
- );
+ protected boolean isInverseOneToManyOrNoOrphanDelete() {
+ final CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this );
+ return ce != null
+ && ce.getLoadedPersister().isInverse()
+ && ( ce.getLoadedPersister().isOneToMany() || !ce.getLoadedPersister().hasOrphanDelete() );
}
/**
operationQueue = new ArrayList<DelayedOperation>( 10 );
}
operationQueue.add( operation );
- dirty = true; //needed so that we remove this collection from the second-level cache
+ //needed so that we remove this collection from the second-level cache
+ dirty = true;
+ }
+
+ /**
+ * Replace entity instances with copy in {@code copyCache}/.
+ *
+ * @param copyCache - mapping from entity in the process of being
+ * merged to managed copy.
+ */
+ public final void replaceQueuedOperationValues(CollectionPersister persister, Map copyCache) {
+ for ( DelayedOperation operation : operationQueue ) {
+ if ( ValueDelayedOperation.class.isInstance( operation ) ) {
+ ( (ValueDelayedOperation) operation ).replace( persister, copyCache );
+ }
+ }
}
/**
}
}
- /**
- * After flushing, re-init snapshot state.
- */
@Override
- public void setSnapshot(Serializable key, String role, Serializable snapshot) {
+ public void setSnapshot(Serializable key, String role, Serializable snapshot) {
this.key = key;
this.role = role;
this.storedSnapshot = snapshot;
}
- /**
- * After flushing, clear any "queued" additions, since the
- * database state is now synchronized with the memory state.
- */
@Override
- public void postAction() {
+ public void postAction() {
operationQueue = null;
cachedSize = -1;
clearDirty();
}
- /**
- * Not called by Hibernate, but used by non-JDK serialization,
- * eg. SOAP libraries.
- */
- public AbstractPersistentCollection() {
- }
-
- protected AbstractPersistentCollection(SessionImplementor session) {
- this.session = session;
- }
-
- /**
- * return the user-visible collection (or array) instance
- */
@Override
- public Object getValue() {
+ public Object getValue() {
return this;
}
- /**
- * Called just before reading any rows from the JDBC result set
- */
@Override
- public void beginRead() {
+ public void beginRead() {
// override on some subclasses
initializing = true;
}
- /**
- * Called after reading all rows from the JDBC result set
- */
@Override
- public boolean endRead() {
+ public boolean endRead() {
//override on some subclasses
return afterInitialize();
}
@Override
- public boolean afterInitialize() {
+ public boolean afterInitialize() {
setInitialized();
//do this bit after setting initialized to true or it will recurse
if ( operationQueue != null ) {
this.directlyAccessible = directlyAccessible;
}
- /**
- * Could the application possibly have a direct reference to
- * the underlying collection implementation?
- */
@Override
- public boolean isDirectlyAccessible() {
+ public boolean isDirectlyAccessible() {
return directlyAccessible;
}
return session.getPersistenceContext().getSnapshot( this );
}
- /**
- * Is this instance initialized?
- */
@Override
- public final boolean wasInitialized() {
+ public final boolean wasInitialized() {
return initialized;
}
@Override
- public boolean isRowUpdatePossible() {
+ public boolean isRowUpdatePossible() {
return true;
}
- /**
- * Does this instance have any "queued" additions?
- */
@Override
- public final boolean hasQueuedOperations() {
+ public final boolean hasQueuedOperations() {
return operationQueue != null;
}
- /**
- * Iterate the "queued" additions
- */
@Override
- public final Iterator queuedAdditionIterator() {
+ public final Iterator queuedAdditionIterator() {
if ( hasQueuedOperations() ) {
return new Iterator() {
- int i = 0;
+ private int index;
@Override
- public Object next() {
- return operationQueue.get( i++ ).getAddedInstance();
+ public Object next() {
+ return operationQueue.get( index++ ).getAddedInstance();
}
@Override
- public boolean hasNext() {
- return i < operationQueue.size();
+ public boolean hasNext() {
+ return index < operationQueue.size();
}
@Override
- public void remove() {
+ public void remove() {
throw new UnsupportedOperationException();
}
};
}
}
- /**
- * Iterate the "queued" additions
- */
@Override
- @SuppressWarnings({"unchecked"})
+ @SuppressWarnings({"unchecked"})
public final Collection getQueuedOrphans(String entityName) {
if ( hasQueuedOperations() ) {
- Collection additions = new ArrayList( operationQueue.size() );
- Collection removals = new ArrayList( operationQueue.size() );
+ final Collection additions = new ArrayList( operationQueue.size() );
+ final Collection removals = new ArrayList( operationQueue.size() );
for ( DelayedOperation operation : operationQueue ) {
additions.add( operation.getAddedInstance() );
removals.add( operation.getOrphan() );
}
}
- /**
- * Called before inserting rows, to ensure that any surrogate keys
- * are fully generated
- */
@Override
- public void preInsert(CollectionPersister persister) throws HibernateException {
+ public void preInsert(CollectionPersister persister) throws HibernateException {
}
- /**
- * Called after inserting a row, to fetch the natively generated id
- */
@Override
- public void afterRowInsert(CollectionPersister persister, Object entry, int i) throws HibernateException {
+ public void afterRowInsert(CollectionPersister persister, Object entry, int i) throws HibernateException {
}
- /**
- * get all "orphaned" elements
- */
@Override
- public abstract Collection getOrphans(Serializable snapshot, String entityName) throws HibernateException;
+ public abstract Collection getOrphans(Serializable snapshot, String entityName) throws HibernateException;
/**
- * Get the current session
+ * Get the session currently associated with this collection.
+ *
+ * @return The session
*/
- @SuppressWarnings({"JavaDoc"})
public final SessionImplementor getSession() {
return session;
}
}
@Override
- public boolean hasNext() {
+ public boolean hasNext() {
return itr.hasNext();
}
@Override
- public Object next() {
+ public Object next() {
return itr.next();
}
@Override
- public void remove() {
+ public void remove() {
write();
itr.remove();
}
-
}
-
+
protected final class ListIteratorProxy implements ListIterator {
protected final ListIterator itr;
}
@Override
- @SuppressWarnings({"unchecked"})
+ @SuppressWarnings({"unchecked"})
public void add(Object o) {
write();
itr.add( o );
}
@Override
- public boolean hasNext() {
+ public boolean hasNext() {
return itr.hasNext();
}
@Override
- public boolean hasPrevious() {
+ public boolean hasPrevious() {
return itr.hasPrevious();
}
@Override
- public Object next() {
+ public Object next() {
return itr.next();
}
@Override
- public int nextIndex() {
+ public int nextIndex() {
return itr.nextIndex();
}
@Override
- public Object previous() {
+ public Object previous() {
return itr.previous();
}
@Override
- public int previousIndex() {
+ public int previousIndex() {
return itr.previousIndex();
}
@Override
- public void remove() {
+ public void remove() {
write();
itr.remove();
}
@Override
- @SuppressWarnings({"unchecked"})
+ @SuppressWarnings({"unchecked"})
public void set(Object o) {
write();
itr.set( o );
}
-
}
protected class SetProxy implements java.util.Set {
}
@Override
- @SuppressWarnings({"unchecked"})
+ @SuppressWarnings({"unchecked"})
public boolean add(Object o) {
write();
return set.add( o );
}
@Override
- @SuppressWarnings({"unchecked"})
+ @SuppressWarnings({"unchecked"})
public boolean addAll(Collection c) {
write();
return set.addAll( c );
}
@Override
- public void clear() {
+ public void clear() {
write();
set.clear();
}
@Override
- public boolean contains(Object o) {
+ public boolean contains(Object o) {
return set.contains( o );
}
@Override
- public boolean containsAll(Collection c) {
+ @SuppressWarnings("unchecked")
+ public boolean containsAll(Collection c) {
return set.containsAll( c );
}
@Override
- public boolean isEmpty() {
+ public boolean isEmpty() {
return set.isEmpty();
}
@Override
- public Iterator iterator() {
+ public Iterator iterator() {
return new IteratorProxy( set.iterator() );
}
@Override
- public boolean remove(Object o) {
+ public boolean remove(Object o) {
write();
return set.remove( o );
}
@Override
- public boolean removeAll(Collection c) {
+ @SuppressWarnings("unchecked")
+ public boolean removeAll(Collection c) {
write();
return set.removeAll( c );
}
@Override
- public boolean retainAll(Collection c) {
+ @SuppressWarnings("unchecked")
+ public boolean retainAll(Collection c) {
write();
return set.retainAll( c );
}
@Override
- public int size() {
+ public int size() {
return set.size();
}
@Override
- public Object[] toArray() {
+ public Object[] toArray() {
return set.toArray();
}
@Override
- @SuppressWarnings({"unchecked"})
+ @SuppressWarnings({"unchecked"})
public Object[] toArray(Object[] array) {
return set.toArray( array );
}
-
}
protected final class ListProxy implements java.util.List {
}
@Override
+ @SuppressWarnings("unchecked")
public boolean containsAll(Collection c) {
return list.containsAll( c );
}
}
@Override
+ @SuppressWarnings("unchecked")
public boolean removeAll(Collection c) {
write();
return list.removeAll( c );
}
@Override
+ @SuppressWarnings("unchecked")
public boolean retainAll(Collection c) {
write();
return list.retainAll( c );
public Object getOrphan();
}
+
+ protected interface ValueDelayedOperation extends DelayedOperation {
+ void replace(CollectionPersister collectionPersister, Map copyCache);
+ }
+
+ protected abstract class AbstractValueDelayedOperation implements ValueDelayedOperation {
+ private Object addedValue;
+ private Object orphan;
+
+ protected AbstractValueDelayedOperation(Object addedValue, Object orphan) {
+ this.addedValue = addedValue;
+ this.orphan = orphan;
+ }
+
+ public void replace(CollectionPersister persister, Map copyCache) {
+ if ( addedValue != null ) {
+ addedValue = getReplacement( persister.getElementType(), addedValue, copyCache );
+ }
+ }
+
+ protected final Object getReplacement(Type type, Object current, Map copyCache) {
+ return type.replace( current, null, session, owner, copyCache );
+ }
+
+ @Override
+ public final Object getAddedInstance() {
+ return addedValue;
+ }
+
+ @Override
+ public final Object getOrphan() {
+ return orphan;
+ }
+ }
/**
* Given a collection of entity instances that used to
return res;
}
+ private static boolean mayUseIdDirect(Type idType) {
+ return idType == StringType.INSTANCE
+ || idType == IntegerType.INSTANCE
+ || idType == LongType.INSTANCE
+ || idType == UUIDBinaryType.INSTANCE
+ || idType == UUIDCharType.INSTANCE
+ || idType == PostgresUUIDType.INSTANCE;
+ }
+
public static void identityRemove(
Collection list,
Object object,
}
@Override
- public Object getIdentifier(Object entry, int i) {
+ public Object getIdentifier(Object entry, int i) {
throw new UnsupportedOperationException();
}
@Override
- public Object getOwner() {
+ public Object getOwner() {
return owner;
}
@Override
- public void setOwner(Object owner) {
+ public void setOwner(Object owner) {
this.owner = owner;
}