org.hibernate.collection.PersistentIdentifierBag Maven / Gradle / Ivy
The newest version!
//$Id: PersistentIdentifierBag.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.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.loader.CollectionAliases;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.type.Type;
/**
* An IdentifierBag implements "bag" semantics more efficiently than
* a regular Bag by adding a synthetic identifier column to the
* table. This identifier is unique for all rows in the table, allowing very
* efficient updates and deletes. The value of the identifier is never exposed
* to the application.
*
* IdentifierBags may not be used for a many-to-one association.
* Furthermore, there is no reason to use inverse="true".
*
* @author Gavin King
*/
public class PersistentIdentifierBag extends AbstractPersistentCollection implements List {
protected List values; //element
protected Map identifiers; //index -> id
public PersistentIdentifierBag(SessionImplementor session) {
super(session);
}
public PersistentIdentifierBag() {} //needed for SOAP libraries, etc
public PersistentIdentifierBag(SessionImplementor session, Collection coll) {
super(session);
if (coll instanceof List) {
values = (List) coll;
}
else {
values = new ArrayList();
Iterator iter = coll.iterator();
while ( iter.hasNext() ) {
values.add( iter.next() );
}
}
setInitialized();
setDirectlyAccessible(true);
identifiers = new HashMap();
}
public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner)
throws HibernateException {
Serializable[] array = (Serializable[]) disassembled;
int size = array.length;
beforeInitialize( persister, size );
for ( int i = 0; i < size; i+=2 ) {
identifiers.put(
new Integer(i/2),
persister.getIdentifierType().assemble( array[i], getSession(), owner )
);
values.add( persister.getElementType().assemble( array[i+1], getSession(), owner ) );
}
}
public Object getIdentifier(Object entry, int i) {
return identifiers.get( new Integer(i) );
}
public boolean isWrapper(Object collection) {
return values==collection;
}
public boolean add(Object o) {
write();
values.add(o);
return true;
}
public void clear() {
initialize( true );
if ( ! values.isEmpty() || ! identifiers.isEmpty() ) {
values.clear();
identifiers.clear();
dirty();
}
}
public boolean contains(Object o) {
read();
return values.contains(o);
}
public boolean containsAll(Collection c) {
read();
return values.containsAll(c);
}
public boolean isEmpty() {
return readSize() ? getCachedSize()==0 : values.isEmpty();
}
public Iterator iterator() {
read();
return new IteratorProxy( values.iterator() );
}
public boolean remove(Object o) {
initialize( true );
int index = values.indexOf(o);
if (index>=0) {
beforeRemove(index);
values.remove(index);
dirty();
return true;
}
else {
return false;
}
}
public boolean removeAll(Collection c) {
if ( c.size() > 0 ) {
boolean result = false;
Iterator iter = c.iterator();
while ( iter.hasNext() ) {
if ( remove( iter.next() ) ) result=true;
}
return result;
}
else {
return false;
}
}
public boolean retainAll(Collection c) {
initialize( true );
if ( values.retainAll( c ) ) {
dirty();
return true;
}
else {
return false;
}
}
public int size() {
return readSize() ? getCachedSize() : values.size();
}
public Object[] toArray() {
read();
return values.toArray();
}
public Object[] toArray(Object[] a) {
read();
return values.toArray(a);
}
public void beforeInitialize(CollectionPersister persister, int anticipatedSize) {
identifiers = anticipatedSize <= 0 ? new HashMap() : new HashMap( anticipatedSize + 1 + (int)( anticipatedSize * .75f ), .75f );
values = anticipatedSize <= 0 ? new ArrayList() : new ArrayList( anticipatedSize );
}
public Serializable disassemble(CollectionPersister persister)
throws HibernateException {
Serializable[] result = new Serializable[ values.size() * 2 ];
int i=0;
for (int j=0; j< values.size(); j++) {
Object value = values.get(j);
result[i++] = persister.getIdentifierType().disassemble( identifiers.get( new Integer(j) ), getSession(), null );
result[i++] = persister.getElementType().disassemble( value, getSession(), null );
}
return result;
}
public boolean empty() {
return values.isEmpty();
}
public Iterator entries(CollectionPersister persister) {
return values.iterator();
}
public boolean entryExists(Object entry, int i) {
return entry!=null;
}
public boolean equalsSnapshot(CollectionPersister persister) throws HibernateException {
Type elementType = persister.getElementType();
Map snap = (Map) getSnapshot();
if ( snap.size()!= values.size() ) return false;
for ( int i=0; i 0 ) {
Iterator iter = c.iterator();
while ( iter.hasNext() ) {
add( index++, iter.next() );
}
return true;
}
else {
return false;
}
}
public Object get(int index) {
read();
return values.get(index);
}
public int indexOf(Object o) {
read();
return values.indexOf(o);
}
public int lastIndexOf(Object o) {
read();
return values.lastIndexOf(o);
}
public ListIterator listIterator() {
read();
return new ListIteratorProxy( values.listIterator() );
}
public ListIterator listIterator(int index) {
read();
return new ListIteratorProxy( values.listIterator(index) );
}
private void beforeRemove(int index) {
Object removedId = identifiers.get( new Integer(index) );
int last = values.size()-1;
for ( int i=index; i 0 ) {
write();
return values.addAll(c);
}
else {
return false;
}
}
public void afterRowInsert(
CollectionPersister persister,
Object entry,
int i)
throws HibernateException {
//TODO: if we are using identity columns, fetch the identifier
}
}