Save This Page
Home » hibernate-distribution-3.3.1.GA-dist » org.hibernate » collection » [javadoc | source]
    1   /*
    2    * Hibernate, Relational Persistence for Idiomatic Java
    3    *
    4    * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
    5    * indicated by the @author tags or express copyright attribution
    6    * statements applied by the authors.  All third-party contributions are
    7    * distributed under license by Red Hat Middleware LLC.
    8    *
    9    * This copyrighted material is made available to anyone wishing to use, modify,
   10    * copy, or redistribute it subject to the terms and conditions of the GNU
   11    * Lesser General Public License, as published by the Free Software Foundation.
   12    *
   13    * This program is distributed in the hope that it will be useful,
   14    * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   15    * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
   16    * for more details.
   17    *
   18    * You should have received a copy of the GNU Lesser General Public License
   19    * along with this distribution; if not, write to:
   20    * Free Software Foundation, Inc.
   21    * 51 Franklin Street, Fifth Floor
   22    * Boston, MA  02110-1301  USA
   23    *
   24    */
   25   package org.hibernate.collection;
   26   
   27   import java.io.Serializable;
   28   import java.sql.ResultSet;
   29   import java.sql.SQLException;
   30   import java.util.ArrayList;
   31   import java.util.Collection;
   32   import java.util.HashMap;
   33   import java.util.Iterator;
   34   import java.util.List;
   35   import java.util.Set;
   36   
   37   import org.hibernate.EntityMode;
   38   import org.hibernate.HibernateException;
   39   import org.hibernate.engine.SessionImplementor;
   40   import org.hibernate.loader.CollectionAliases;
   41   import org.hibernate.persister.collection.CollectionPersister;
   42   import org.hibernate.type.Type;
   43   
   44   
   45   /**
   46    * A persistent wrapper for a <tt>java.util.Set</tt>. The underlying
   47    * collection is a <tt>HashSet</tt>.
   48    *
   49    * @see java.util.HashSet
   50    * @author Gavin King
   51    */
   52   public class PersistentSet extends AbstractPersistentCollection implements java.util.Set {
   53   
   54   	protected Set set;
   55   	protected transient List tempList;
   56   
   57   	/**
   58   	 * Empty constructor.
   59   	 * <p/>
   60   	 * Note: this form is not ever ever ever used by Hibernate; it is, however,
   61   	 * needed for SOAP libraries and other such marshalling code.
   62   	 */
   63   	public PersistentSet() {
   64   		// intentionally empty
   65   	}
   66   
   67   	/**
   68   	 * Constructor matching super.  Instantiates a lazy set (the underlying
   69   	 * set is un-initialized).
   70   	 *
   71   	 * @param session The session to which this set will belong.
   72   	 */
   73   	public PersistentSet(SessionImplementor session) {
   74   		super( session );
   75   	}
   76   
   77   	/**
   78   	 * Instantiates a non-lazy set (the underlying set is constructed
   79   	 * from the incoming set reference).
   80   	 *
   81   	 * @param session The session to which this set will belong.
   82   	 * @param set The underlying set data.
   83   	 */
   84   	public PersistentSet(SessionImplementor session, java.util.Set set) {
   85   		super(session);
   86   		// Sets can be just a view of a part of another collection.
   87   		// do we need to copy it to be sure it won't be changing
   88   		// underneath us?
   89   		// ie. this.set.addAll(set);
   90   		this.set = set;
   91   		setInitialized();
   92   		setDirectlyAccessible(true);
   93   	}
   94   
   95   
   96   	public Serializable getSnapshot(CollectionPersister persister) 
   97   	throws HibernateException {
   98   		EntityMode entityMode = getSession().getEntityMode();
   99   		
  100   		//if (set==null) return new Set(session);
  101   		HashMap clonedSet = new HashMap( set.size() );
  102   		Iterator iter = set.iterator();
  103   		while ( iter.hasNext() ) {
  104   			Object copied = persister.getElementType()
  105   					.deepCopy( iter.next(), entityMode, persister.getFactory() );
  106   			clonedSet.put(copied, copied);
  107   		}
  108   		return clonedSet;
  109   	}
  110   
  111   	public Collection getOrphans(Serializable snapshot, String entityName) throws HibernateException {
  112   		java.util.Map sn = (java.util.Map) snapshot;
  113   		return getOrphans( sn.keySet(), set, entityName, getSession() );
  114   	}
  115   
  116   	public boolean equalsSnapshot(CollectionPersister persister) throws HibernateException {
  117   		Type elementType = persister.getElementType();
  118   		java.util.Map sn = (java.util.Map) getSnapshot();
  119   		if ( sn.size()!=set.size() ) {
  120   			return false;
  121   		}
  122   		else {
  123   			Iterator iter = set.iterator();
  124   			while ( iter.hasNext() ) {
  125   				Object test = iter.next();
  126   				Object oldValue = sn.get(test);
  127   				if ( oldValue==null || elementType.isDirty( oldValue, test, getSession() ) ) return false;
  128   			}
  129   			return true;
  130   		}
  131   	}
  132   
  133   	public boolean isSnapshotEmpty(Serializable snapshot) {
  134   		return ( (java.util.Map) snapshot ).isEmpty();
  135   	}
  136   
  137   	public void beforeInitialize(CollectionPersister persister, int anticipatedSize) {
  138   		this.set = ( Set ) persister.getCollectionType().instantiate( anticipatedSize );
  139   	}
  140   
  141   	public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner)
  142   	throws HibernateException {
  143   		Serializable[] array = ( Serializable[] ) disassembled;
  144   		int size = array.length;
  145   		beforeInitialize( persister, size );
  146   		for (int i = 0; i < size; i++ ) {
  147   			Object element = persister.getElementType().assemble( array[i], getSession(), owner );
  148   			if ( element != null ) {
  149   				set.add( element );
  150   			}
  151   		}
  152   	}
  153   
  154   	public boolean empty() {
  155   		return set.isEmpty();
  156   	}
  157   
  158   	/**
  159   	 * @see java.util.Set#size()
  160   	 */
  161   	public int size() {
  162   		return readSize() ? getCachedSize() : set.size();
  163   	}
  164   
  165   	/**
  166   	 * @see java.util.Set#isEmpty()
  167   	 */
  168   	public boolean isEmpty() {
  169   		return readSize() ? getCachedSize()==0 : set.isEmpty();
  170   	}
  171   
  172   	/**
  173   	 * @see java.util.Set#contains(Object)
  174   	 */
  175   	public boolean contains(Object object) {
  176   		Boolean exists = readElementExistence(object);
  177   		return exists==null ? 
  178   				set.contains(object) : 
  179   				exists.booleanValue();
  180   	}
  181   
  182   	/**
  183   	 * @see java.util.Set#iterator()
  184   	 */
  185   	public Iterator iterator() {
  186   		read();
  187   		return new IteratorProxy( set.iterator() );
  188   	}
  189   
  190   	/**
  191   	 * @see java.util.Set#toArray()
  192   	 */
  193   	public Object[] toArray() {
  194   		read();
  195   		return set.toArray();
  196   	}
  197   
  198   	/**
  199   	 * @see java.util.Set#toArray(Object[])
  200   	 */
  201   	public Object[] toArray(Object[] array) {
  202   		read();
  203   		return set.toArray(array);
  204   	}
  205   
  206   	/**
  207   	 * @see java.util.Set#add(Object)
  208   	 */
  209   	public boolean add(Object value) {
  210   		Boolean exists = isOperationQueueEnabled() ? readElementExistence( value ) : null;
  211   		if ( exists == null ) {
  212   			initialize( true );
  213   			if ( set.add( value ) ) {
  214   				dirty();
  215   				return true;
  216   			}
  217   			else {
  218   				return false;
  219   			}
  220   		}
  221   		else if ( exists.booleanValue() ) {
  222   			return false;
  223   		}
  224   		else {
  225   			queueOperation( new SimpleAdd(value) );
  226   			return true;
  227   		}
  228   	}
  229   
  230   	/**
  231   	 * @see java.util.Set#remove(Object)
  232   	 */
  233   	public boolean remove(Object value) {
  234   		Boolean exists = isPutQueueEnabled() ? readElementExistence( value ) : null;
  235   		if ( exists==null ) {
  236   			initialize( true );
  237   			if ( set.remove( value ) ) {
  238   				dirty();
  239   				return true;
  240   			}
  241   			else {
  242   				return false;
  243   			}
  244   		}
  245   		else if ( exists.booleanValue() ) {
  246   			queueOperation( new SimpleRemove(value) );
  247   			return true;
  248   		}
  249   		else {
  250   			return false;
  251   		}
  252   	}
  253   
  254   	/**
  255   	 * @see java.util.Set#containsAll(Collection)
  256   	 */
  257   	public boolean containsAll(Collection coll) {
  258   		read();
  259   		return set.containsAll(coll);
  260   	}
  261   
  262   	/**
  263   	 * @see java.util.Set#addAll(Collection)
  264   	 */
  265   	public boolean addAll(Collection coll) {
  266   		if ( coll.size() > 0 ) {
  267   			initialize( true );
  268   			if ( set.addAll( coll ) ) {
  269   				dirty();
  270   				return true;
  271   			}
  272   			else {
  273   				return false;
  274   			}
  275   		}
  276   		else {
  277   			return false;
  278   		}
  279   	}
  280   
  281   	/**
  282   	 * @see java.util.Set#retainAll(Collection)
  283   	 */
  284   	public boolean retainAll(Collection coll) {
  285   		initialize( true );
  286   		if ( set.retainAll( coll ) ) {
  287   			dirty();
  288   			return true;
  289   		}
  290   		else {
  291   			return false;
  292   		}
  293   	}
  294   
  295   	/**
  296   	 * @see java.util.Set#removeAll(Collection)
  297   	 */
  298   	public boolean removeAll(Collection coll) {
  299   		if ( coll.size() > 0 ) {
  300   			initialize( true );
  301   			if ( set.removeAll( coll ) ) {
  302   				dirty();
  303   				return true;
  304   			}
  305   			else {
  306   				return false;
  307   			}
  308   		}
  309   		else {
  310   			return false;
  311   		}
  312   	}
  313   
  314   	/**
  315   	 * @see java.util.Set#clear()
  316   	 */
  317   	public void clear() {
  318   		if ( isClearQueueEnabled() ) {
  319   			queueOperation( new Clear() );
  320   		}
  321   		else {
  322   			initialize( true );
  323   			if ( !set.isEmpty() ) {
  324   				set.clear();
  325   				dirty();
  326   			}
  327   		}
  328   	}
  329   
  330   	public String toString() {
  331   		//if (needLoading) return "asleep";
  332   		read();
  333   		return set.toString();
  334   	}
  335   
  336   	public Object readFrom(
  337   	        ResultSet rs,
  338   	        CollectionPersister persister,
  339   	        CollectionAliases descriptor,
  340   	        Object owner) throws HibernateException, SQLException {
  341   		Object element = persister.readElement( rs, owner, descriptor.getSuffixedElementAliases(), getSession() );
  342   		if (element!=null) tempList.add(element);
  343   		return element;
  344   	}
  345   
  346   	public void beginRead() {
  347   		super.beginRead();
  348   		tempList = new ArrayList();
  349   	}
  350   
  351   	public boolean endRead() {
  352   		set.addAll(tempList);
  353   		tempList = null;
  354   		setInitialized();
  355   		return true;
  356   	}
  357   
  358   	public Iterator entries(CollectionPersister persister) {
  359   		return set.iterator();
  360   	}
  361   
  362   	public Serializable disassemble(CollectionPersister persister)
  363   	throws HibernateException {
  364   
  365   		Serializable[] result = new Serializable[ set.size() ];
  366   		Iterator iter = set.iterator();
  367   		int i=0;
  368   		while ( iter.hasNext() ) {
  369   			result[i++] = persister.getElementType().disassemble( iter.next(), getSession(), null );
  370   		}
  371   		return result;
  372   
  373   	}
  374   
  375   	public Iterator getDeletes(CollectionPersister persister, boolean indexIsFormula) throws HibernateException {
  376   		Type elementType = persister.getElementType();
  377   		final java.util.Map sn = (java.util.Map) getSnapshot();
  378   		ArrayList deletes = new ArrayList( sn.size() );
  379   		Iterator iter = sn.keySet().iterator();
  380   		while ( iter.hasNext() ) {
  381   			Object test = iter.next();
  382   			if ( !set.contains(test) ) {
  383   				// the element has been removed from the set
  384   				deletes.add(test);
  385   			}
  386   		}
  387   		iter = set.iterator();
  388   		while ( iter.hasNext() ) {
  389   			Object test = iter.next();
  390   			Object oldValue = sn.get(test);
  391   			if ( oldValue!=null && elementType.isDirty( test, oldValue, getSession() ) ) {
  392   				// the element has changed
  393   				deletes.add(oldValue);
  394   			}
  395   		}
  396   		return deletes.iterator();
  397   	}
  398   
  399   	public boolean needsInserting(Object entry, int i, Type elemType) throws HibernateException {
  400   		final java.util.Map sn = (java.util.Map) getSnapshot();
  401   		Object oldValue = sn.get(entry);
  402   		// note that it might be better to iterate the snapshot but this is safe,
  403   		// assuming the user implements equals() properly, as required by the Set
  404   		// contract!
  405   		return oldValue==null || elemType.isDirty( oldValue, entry, getSession() );
  406   	}
  407   
  408   	public boolean needsUpdating(Object entry, int i, Type elemType) {
  409   		return false;
  410   	}
  411   
  412   	public boolean isRowUpdatePossible() {
  413   		return false;
  414   	}
  415   
  416   	public Object getIndex(Object entry, int i, CollectionPersister persister) {
  417   		throw new UnsupportedOperationException("Sets don't have indexes");
  418   	}
  419   
  420   	public Object getElement(Object entry) {
  421   		return entry;
  422   	}
  423   
  424   	public Object getSnapshotElement(Object entry, int i) {
  425   		throw new UnsupportedOperationException("Sets don't support updating by element");
  426   	}
  427   
  428   	public boolean equals(Object other) {
  429   		read();
  430   		return set.equals(other);
  431   	}
  432   
  433   	public int hashCode() {
  434   		read();
  435   		return set.hashCode();
  436   	}
  437   
  438   	public boolean entryExists(Object key, int i) {
  439   		return true;
  440   	}
  441   
  442   	public boolean isWrapper(Object collection) {
  443   		return set==collection;
  444   	}
  445   
  446   	final class Clear implements DelayedOperation {
  447   		public void operate() {
  448   			set.clear();
  449   		}
  450   		public Object getAddedInstance() {
  451   			return null;
  452   		}
  453   		public Object getOrphan() {
  454   			throw new UnsupportedOperationException("queued clear cannot be used with orphan delete");
  455   		}
  456   	}
  457   
  458   	final class SimpleAdd implements DelayedOperation {
  459   		private Object value;
  460   		
  461   		public SimpleAdd(Object value) {
  462   			this.value = value;
  463   		}
  464   		public void operate() {
  465   			set.add(value);
  466   		}
  467   		public Object getAddedInstance() {
  468   			return value;
  469   		}
  470   		public Object getOrphan() {
  471   			return null;
  472   		}
  473   	}
  474   
  475   	final class SimpleRemove implements DelayedOperation {
  476   		private Object value;
  477   		
  478   		public SimpleRemove(Object value) {
  479   			this.value = value;
  480   		}
  481   		public void operate() {
  482   			set.remove(value);
  483   		}
  484   		public Object getAddedInstance() {
  485   			return null;
  486   		}
  487   		public Object getOrphan() {
  488   			return value;
  489   		}
  490   	}
  491   }

Save This Page
Home » hibernate-distribution-3.3.1.GA-dist » org.hibernate » collection » [javadoc | source]