![JAR search and dependency download from the Maven repository](/logo.png)
org.hibernate.collection.PersistentBag Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of hibernate Show documentation
Show all versions of hibernate Show documentation
Relational Persistence for Java
//$Id: PersistentBag.java 10739 2006-11-06 22:00:41Z [email protected] $
package org.hibernate.collection;
import java.io.Serializable;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.loader.CollectionAliases;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.type.Type;
/**
* An unordered, unkeyed collection that can contain the same element
* multiple times. The Java collections API, curiously, has no Bag.
* Most developers seem to use Lists to represent bag semantics,
* so Hibernate follows this practice.
*
* @author Gavin King
*/
public class PersistentBag extends AbstractPersistentCollection implements List {
protected List bag;
public PersistentBag(SessionImplementor session) {
super(session);
}
public PersistentBag(SessionImplementor session, Collection coll) {
super(session);
if (coll instanceof List) {
bag = (List) coll;
}
else {
bag = new ArrayList();
Iterator iter = coll.iterator();
while ( iter.hasNext() ) {
bag.add( iter.next() );
}
}
setInitialized();
setDirectlyAccessible(true);
}
public PersistentBag() {} //needed for SOAP libraries, etc
public boolean isWrapper(Object collection) {
return bag==collection;
}
public boolean empty() {
return bag.isEmpty();
}
public Iterator entries(CollectionPersister persister) {
return bag.iterator();
}
public Object readFrom(ResultSet rs, CollectionPersister persister, CollectionAliases descriptor, Object owner)
throws HibernateException, SQLException {
// note that if we load this collection from a cartesian product
// the multiplicity would be broken ... so use an idbag instead
Object element = persister.readElement( rs, owner, descriptor.getSuffixedElementAliases(), getSession() ) ;
if (element!=null) bag.add(element);
return element;
}
public void beforeInitialize(CollectionPersister persister, int anticipatedSize) {
this.bag = ( List ) persister.getCollectionType().instantiate( anticipatedSize );
}
public boolean equalsSnapshot(CollectionPersister persister) throws HibernateException {
Type elementType = persister.getElementType();
EntityMode entityMode = getSession().getEntityMode();
List sn = (List) getSnapshot();
if ( sn.size()!=bag.size() ) return false;
Iterator iter = bag.iterator();
while ( iter.hasNext() ) {
Object elt = iter.next();
final boolean unequal = countOccurrences(elt, bag, elementType, entityMode) !=
countOccurrences(elt, sn, elementType, entityMode);
if ( unequal ) return false;
}
return true;
}
public boolean isSnapshotEmpty(Serializable snapshot) {
return ( (Collection) snapshot ).isEmpty();
}
private int countOccurrences(Object element, List list, Type elementType, EntityMode entityMode)
throws HibernateException {
Iterator iter = list.iterator();
int result=0;
while ( iter.hasNext() ) {
if ( elementType.isSame( element, iter.next(), entityMode ) ) result++;
}
return result;
}
public Serializable getSnapshot(CollectionPersister persister)
throws HibernateException {
EntityMode entityMode = getSession().getEntityMode();
ArrayList clonedList = new ArrayList( bag.size() );
Iterator iter = bag.iterator();
while ( iter.hasNext() ) {
clonedList.add( persister.getElementType().deepCopy( iter.next(), entityMode, persister.getFactory() ) );
}
return clonedList;
}
public Collection getOrphans(Serializable snapshot, String entityName) throws HibernateException {
List sn = (List) snapshot;
return getOrphans( sn, bag, entityName, getSession() );
}
public Serializable disassemble(CollectionPersister persister)
throws HibernateException {
int length = bag.size();
Serializable[] result = new Serializable[length];
for ( int i=0; i is not really a bag;
// it is *really* a set, since it can't contain the
// same element twice. It could be considered a bug
// in the mapping dtd that allows .
// Anyway, here we implement semantics for a
// !
public Iterator getDeletes(CollectionPersister persister, boolean indexIsFormula) throws HibernateException {
//if ( !persister.isOneToMany() ) throw new AssertionFailure("Not implemented for Bags");
Type elementType = persister.getElementType();
EntityMode entityMode = getSession().getEntityMode();
ArrayList deletes = new ArrayList();
List sn = (List) getSnapshot();
Iterator olditer = sn.iterator();
int i=0;
while ( olditer.hasNext() ) {
Object old = olditer.next();
Iterator newiter = bag.iterator();
boolean found = false;
if ( bag.size()>i && elementType.isSame( old, bag.get(i++), entityMode ) ) {
//a shortcut if its location didn't change!
found = true;
}
else {
//search for it
//note that this code is incorrect for other than one-to-many
while ( newiter.hasNext() ) {
if ( elementType.isSame( old, newiter.next(), entityMode ) ) {
found = true;
break;
}
}
}
if (!found) deletes.add(old);
}
return deletes.iterator();
}
public boolean needsInserting(Object entry, int i, Type elemType) throws HibernateException {
//if ( !persister.isOneToMany() ) throw new AssertionFailure("Not implemented for Bags");
List sn = (List) getSnapshot();
final EntityMode entityMode = getSession().getEntityMode();
if ( sn.size()>i && elemType.isSame( sn.get(i), entry, entityMode ) ) {
//a shortcut if its location didn't change!
return false;
}
else {
//search for it
//note that this code is incorrect for other than one-to-many
Iterator olditer = sn.iterator();
while ( olditer.hasNext() ) {
Object old = olditer.next();
if ( elemType.isSame( old, entry, entityMode ) ) return false;
}
return true;
}
}
public boolean isRowUpdatePossible() {
return false;
}
public boolean needsUpdating(Object entry, int i, Type elemType) {
//if ( !persister.isOneToMany() ) throw new AssertionFailure("Not implemented for Bags");
return false;
}
/**
* @see java.util.Collection#size()
*/
public int size() {
return readSize() ? getCachedSize() : bag.size();
}
/**
* @see java.util.Collection#isEmpty()
*/
public boolean isEmpty() {
return readSize() ? getCachedSize()==0 : bag.isEmpty();
}
/**
* @see java.util.Collection#contains(Object)
*/
public boolean contains(Object object) {
Boolean exists = readElementExistence(object);
return exists==null ?
bag.contains(object) :
exists.booleanValue();
}
/**
* @see java.util.Collection#iterator()
*/
public Iterator iterator() {
read();
return new IteratorProxy( bag.iterator() );
}
/**
* @see java.util.Collection#toArray()
*/
public Object[] toArray() {
read();
return bag.toArray();
}
/**
* @see java.util.Collection#toArray(Object[])
*/
public Object[] toArray(Object[] a) {
read();
return bag.toArray(a);
}
/**
* @see java.util.Collection#add(Object)
*/
public boolean add(Object object) {
if ( !isOperationQueueEnabled() ) {
write();
return bag.add(object);
}
else {
queueOperation( new SimpleAdd(object) );
return true;
}
}
/**
* @see java.util.Collection#remove(Object)
*/
public boolean remove(Object o) {
initialize( true );
if ( bag.remove( o ) ) {
dirty();
return true;
}
else {
return false;
}
}
/**
* @see java.util.Collection#containsAll(Collection)
*/
public boolean containsAll(Collection c) {
read();
return bag.containsAll(c);
}
/**
* @see java.util.Collection#addAll(Collection)
*/
public boolean addAll(Collection values) {
if ( values.size()==0 ) return false;
if ( !isOperationQueueEnabled() ) {
write();
return bag.addAll(values);
}
else {
Iterator iter = values.iterator();
while ( iter.hasNext() ) {
queueOperation( new SimpleAdd( iter.next() ) );
}
return values.size()>0;
}
}
/**
* @see java.util.Collection#removeAll(Collection)
*/
public boolean removeAll(Collection c) {
if ( c.size()>0 ) {
initialize( true );
if ( bag.removeAll( c ) ) {
dirty();
return true;
}
else {
return false;
}
}
else {
return false;
}
}
/**
* @see java.util.Collection#retainAll(Collection)
*/
public boolean retainAll(Collection c) {
initialize( true );
if ( bag.retainAll( c ) ) {
dirty();
return true;
}
else {
return false;
}
}
/**
* @see java.util.Collection#clear()
*/
public void clear() {
if ( isClearQueueEnabled() ) {
queueOperation( new Clear() );
}
else {
initialize( true );
if ( ! bag.isEmpty() ) {
bag.clear();
dirty();
}
}
}
public Object getIndex(Object entry, int i, CollectionPersister persister) {
throw new UnsupportedOperationException("Bags don't have indexes");
}
public Object getElement(Object entry) {
return entry;
}
public Object getSnapshotElement(Object entry, int i) {
List sn = (List) getSnapshot();
return sn.get(i);
}
public int occurrences(Object o) {
read();
Iterator iter = bag.iterator();
int result=0;
while ( iter.hasNext() ) {
if ( o.equals( iter.next() ) ) result++;
}
return result;
}
// List OPERATIONS:
/**
* @see java.util.List#add(int, Object)
*/
public void add(int i, Object o) {
write();
bag.add(i, o);
}
/**
* @see java.util.List#addAll(int, Collection)
*/
public boolean addAll(int i, Collection c) {
if ( c.size()>0 ) {
write();
return bag.addAll(i, c);
}
else {
return false;
}
}
/**
* @see java.util.List#get(int)
*/
public Object get(int i) {
read();
return bag.get(i);
}
/**
* @see java.util.List#indexOf(Object)
*/
public int indexOf(Object o) {
read();
return bag.indexOf(o);
}
/**
* @see java.util.List#lastIndexOf(Object)
*/
public int lastIndexOf(Object o) {
read();
return bag.lastIndexOf(o);
}
/**
* @see java.util.List#listIterator()
*/
public ListIterator listIterator() {
read();
return new ListIteratorProxy( bag.listIterator() );
}
/**
* @see java.util.List#listIterator(int)
*/
public ListIterator listIterator(int i) {
read();
return new ListIteratorProxy( bag.listIterator(i) );
}
/**
* @see java.util.List#remove(int)
*/
public Object remove(int i) {
write();
return bag.remove(i);
}
/**
* @see java.util.List#set(int, Object)
*/
public Object set(int i, Object o) {
write();
return bag.set(i, o);
}
/**
* @see java.util.List#subList(int, int)
*/
public List subList(int start, int end) {
read();
return new ListProxy( bag.subList(start, end) );
}
public String toString() {
read();
return bag.toString();
}
/*public boolean equals(Object other) {
read();
return bag.equals(other);
}
public int hashCode(Object other) {
read();
return bag.hashCode();
}*/
public boolean entryExists(Object entry, int i) {
return entry!=null;
}
/**
* Bag does not respect the collection API and do an
* JVM instance comparison to do the equals.
* The semantic is broken not to have to initialize a
* collection for a simple equals() operation.
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object obj) {
return super.equals(obj);
}
/**
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
return super.hashCode();
}
final class Clear implements DelayedOperation {
public void operate() {
bag.clear();
}
public Object getAddedInstance() {
return null;
}
public Object getOrphan() {
throw new UnsupportedOperationException("queued clear cannot be used with orphan delete");
}
}
final class SimpleAdd implements DelayedOperation {
private Object value;
public SimpleAdd(Object value) {
this.value = value;
}
public void operate() {
bag.add(value);
}
public Object getAddedInstance() {
return value;
}
public Object getOrphan() {
return null;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy