Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/hibernate/collection/PersistentBag.java


1   //$Id: PersistentBag.java,v 1.14 2005/04/03 02:53:05 oneovthafew Exp $
2   package org.hibernate.collection;
3   
4   import java.io.Serializable;
5   import java.sql.ResultSet;
6   import java.sql.SQLException;
7   import java.util.ArrayList;
8   import java.util.Collection;
9   import java.util.Iterator;
10  import java.util.List;
11  import java.util.ListIterator;
12  
13  import org.hibernate.EntityMode;
14  import org.hibernate.HibernateException;
15  import org.hibernate.engine.SessionImplementor;
16  import org.hibernate.persister.collection.CollectionPersister;
17  import org.hibernate.type.Type;
18  
19  /**
20   * An unordered, unkeyed collection that can contain the same element
21   * multiple times. The Java collections API, curiously, has no <tt>Bag</tt>.
22   * Most developers seem to use <tt>List</tt>s to represent bag semantics,
23   * so Hibernate follows this practice.
24   *
25   * @author Gavin King
26   */
27  public class PersistentBag extends AbstractPersistentCollection implements java.util.List {
28  
29    private java.util.List bag;
30  
31    public PersistentBag(SessionImplementor session) {
32      super(session);
33    }
34  
35    public PersistentBag(SessionImplementor session, java.util.Collection coll) {
36      super(session);
37      if (coll instanceof java.util.List) {
38        bag = (java.util.List) coll;
39      }
40      else {
41        bag = new ArrayList();
42        Iterator iter = coll.iterator();
43        while ( iter.hasNext() ) {
44          bag.add( iter.next() );
45        }
46      }
47      setInitialized();
48      setDirectlyAccessible(true);
49    }
50  
51    public PersistentBag() {} //needed for SOAP libraries, etc
52  
53    public boolean isWrapper(Object collection) {
54      return bag==collection;
55    }
56    public boolean empty() {
57      return bag.isEmpty();
58    }
59    
60    public Iterator entries(CollectionPersister persister) {
61      return bag.iterator();
62    }
63  
64    public Object readFrom(ResultSet rs, CollectionPersister persister, Object owner) 
65    throws HibernateException, SQLException {
66      // note that if we load this collection from a cartesian product
67      // the multiplicity would be broken ... so use an idbag instead
68      Object element = persister.readElement( rs, owner, getSession() ) ;
69      if (element!=null) bag.add(element);
70      return element;
71    }
72  
73    public void beforeInitialize(CollectionPersister persister) {
74      this.bag = new ArrayList();
75    }
76  
77    public boolean equalsSnapshot(CollectionPersister persister) throws HibernateException {
78      Type elementType = persister.getElementType();
79      EntityMode entityMode = getSession().getEntityMode();
80      java.util.List sn = (java.util.List) getSnapshot();
81      if ( sn.size()!=bag.size() ) return false;
82      Iterator iter = bag.iterator();
83      while ( iter.hasNext() ) {
84        Object elt = iter.next();
85        final boolean unequal = countOccurrences(elt, bag, elementType, entityMode) !=
86          countOccurrences(elt, sn, elementType, entityMode);
87        if ( unequal ) return false;
88      }
89      return true;
90    }
91  
92    private int countOccurrences(Object element, java.util.List list, Type elementType, EntityMode entityMode) 
93    throws HibernateException {
94      Iterator iter = list.iterator();
95      int result=0;
96      while ( iter.hasNext() ) {
97        if ( elementType.isSame( element, iter.next(), entityMode ) ) result++;
98      }
99      return result;
100   }
101 
102   protected Serializable snapshot(CollectionPersister persister)
103   throws HibernateException {
104     EntityMode entityMode = getSession().getEntityMode();
105     ArrayList clonedList = new ArrayList( bag.size() );
106     Iterator iter = bag.iterator();
107     while ( iter.hasNext() ) {
108       clonedList.add( persister.getElementType().deepCopy( iter.next(), entityMode, persister.getFactory() ) );
109     }
110     return clonedList;
111   }
112 
113   public Collection getOrphans(Serializable snapshot, String entityName) throws HibernateException {
114       java.util.List sn = (java.util.List) snapshot;
115       return getOrphans( sn, bag, entityName, getSession() );
116   }
117 
118 
119   public Serializable disassemble(CollectionPersister persister)
120   throws HibernateException {
121 
122     int length = bag.size();
123     Serializable[] result = new Serializable[length];
124     for ( int i=0; i<length; i++ ) {
125       result[i] = persister.getElementType().disassemble( bag.get(i), getSession(), null );
126     }
127     return result;
128   }
129 
130   public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner)
131   throws HibernateException {
132     beforeInitialize(persister);
133     Serializable[] array = (Serializable[]) disassembled;
134     for ( int i=0; i<array.length; i++ ) {
135       Object element = persister.getElementType().assemble( array[i], getSession(), owner );
136       if ( element!=null ) bag.add( element );
137     }
138     setInitialized();
139   }
140 
141   public boolean needsRecreate(CollectionPersister persister) {
142     return !persister.isOneToMany();
143   }
144 
145 
146   // For a one-to-many, a <bag> is not really a bag;
147   // it is *really* a set, since it can't contain the
148   // same element twice. It could be considered a bug
149   // in the mapping dtd that <bag> allows <one-to-many>.
150 
151   // Anyway, here we implement <set> semantics for a
152   // <one-to-many> <bag>!
153 
154   public Iterator getDeletes(CollectionPersister persister, boolean indexIsFormula) throws HibernateException {
155     //if ( !persister.isOneToMany() ) throw new AssertionFailure("Not implemented for Bags");
156     Type elementType = persister.getElementType();
157     EntityMode entityMode = getSession().getEntityMode();
158     ArrayList deletes = new ArrayList();
159     java.util.List sn = (java.util.List) getSnapshot();
160     Iterator olditer = sn.iterator();
161     int i=0;
162     while ( olditer.hasNext() ) {
163       Object old = olditer.next();
164       Iterator newiter = bag.iterator();
165       boolean found = false;
166       if ( bag.size()>i && elementType.isSame( old, bag.get(i++), entityMode ) ) {
167       //a shortcut if its location didn't change!
168         found = true;
169       }
170       else {
171         //search for it
172         //note that this code is incorrect for other than one-to-many
173         while ( newiter.hasNext() ) {
174           if ( elementType.isSame( old, newiter.next(), entityMode ) ) {
175             found = true;
176             break;
177           }
178         }
179       }
180       if (!found) deletes.add(old);
181     }
182     return deletes.iterator();
183   }
184 
185   public boolean needsInserting(Object entry, int i, Type elemType) throws HibernateException {
186     //if ( !persister.isOneToMany() ) throw new AssertionFailure("Not implemented for Bags");
187     java.util.List sn = (java.util.List) getSnapshot();
188     final EntityMode entityMode = getSession().getEntityMode();
189     if ( sn.size()>i && elemType.isSame( sn.get(i), entry, entityMode ) ) {
190     //a shortcut if its location didn't change!
191       return false;
192     }
193     else {
194       //search for it
195       //note that this code is incorrect for other than one-to-many
196       Iterator olditer = sn.iterator();
197       while ( olditer.hasNext() ) {
198         Object old = olditer.next();
199         if ( elemType.isSame( old, entry, entityMode ) ) return false;
200       }
201       return true;
202     }
203   }
204   
205   public boolean isRowUpdatePossible() {
206     return false;
207   }
208 
209   public boolean needsUpdating(Object entry, int i, Type elemType) {
210     //if ( !persister.isOneToMany() ) throw new AssertionFailure("Not implemented for Bags");
211     return false;
212   }
213 
214   /**
215    * @see java.util.Collection#size()
216    */
217   public int size() {
218     read();
219     return bag.size();
220   }
221 
222   /**
223    * @see java.util.Collection#isEmpty()
224    */
225   public boolean isEmpty() {
226     read();
227     return bag.isEmpty();
228   }
229 
230   /**
231    * @see java.util.Collection#contains(Object)
232    */
233   public boolean contains(Object o) {
234     read();
235     return bag.contains(o);
236   }
237 
238   /**
239    * @see java.util.Collection#iterator()
240    */
241   public Iterator iterator() {
242     read();
243     return new IteratorProxy( bag.iterator() );
244   }
245 
246   /**
247    * @see java.util.Collection#toArray()
248    */
249   public Object[] toArray() {
250     read();
251     return bag.toArray();
252   }
253 
254   /**
255    * @see java.util.Collection#toArray(Object[])
256    */
257   public Object[] toArray(Object[] a) {
258     read();
259     return bag.toArray(a);
260   }
261 
262   /**
263    * @see java.util.Collection#add(Object)
264    */
265   public boolean add(Object o) {
266     if ( !queueAdd(o) ) {
267       write();
268       return bag.add(o);
269     }
270     else {
271       return true;
272     }
273   }
274 
275   /**
276    * @see java.util.Collection#remove(Object)
277    */
278   public boolean remove(Object o) {
279     write();
280     return bag.remove(o);
281   }
282 
283   /**
284    * @see java.util.Collection#containsAll(Collection)
285    */
286   public boolean containsAll(Collection c) {
287     read();
288     return bag.containsAll(c);
289   }
290 
291   /**
292    * @see java.util.Collection#addAll(Collection)
293    */
294   public boolean addAll(Collection c) {
295     if ( c.size()==0 ) return false;
296     if ( !queueAddAll(c) ) {
297       write();
298       return bag.addAll(c);
299     }
300     else {
301       return c.size()>0;
302     }
303   }
304 
305   public void delayedAddAll(Collection c) {
306     bag.addAll(c);
307   }
308 
309   /**
310    * @see java.util.Collection#removeAll(Collection)
311    */
312   public boolean removeAll(Collection c) {
313     if ( c.size()>0 ) {
314       write();
315       return bag.removeAll(c);
316     }
317     else {
318       return false;
319     }
320   }
321 
322   /**
323    * @see java.util.Collection#retainAll(Collection)
324    */
325   public boolean retainAll(Collection c) {
326     write();
327     return bag.retainAll(c);
328   }
329 
330   /**
331    * @see java.util.Collection#clear()
332    */
333   public void clear() {
334     write();
335     bag.clear();
336   }
337 
338   public Object getIndex(Object entry, int i, CollectionPersister persister) {
339     throw new UnsupportedOperationException("Bags don't have indexes");
340   }
341 
342   public Object getElement(Object entry) {
343     return entry;
344   }
345 
346   public Object getSnapshotElement(Object entry, int i) {
347     java.util.List sn = (java.util.List) getSnapshot();
348     return sn.get(i);
349   }
350 
351   public int occurrences(Object o) {
352     read();
353     Iterator iter = bag.iterator();
354     int result=0;
355     while ( iter.hasNext() ) {
356       if ( o.equals( iter.next() ) ) result++;
357     }
358     return result;
359   }
360 
361   // List OPERATIONS:
362 
363   /**
364    * @see java.util.List#add(int, Object)
365    */
366   public void add(int i, Object o) {
367     write();
368     bag.add(i, o);
369   }
370 
371   /**
372    * @see java.util.List#addAll(int, Collection)
373    */
374   public boolean addAll(int i, Collection c) {
375     if ( c.size()>0 ) {
376       write();
377       return bag.addAll(i, c);
378     }
379     else {
380       return false;
381     }
382   }
383 
384   /**
385    * @see java.util.List#get(int)
386    */
387   public Object get(int i) {
388     read();
389     return bag.get(i);
390   }
391 
392   /**
393    * @see java.util.List#indexOf(Object)
394    */
395   public int indexOf(Object o) {
396     read();
397     return bag.indexOf(o);
398   }
399 
400   /**
401    * @see java.util.List#lastIndexOf(Object)
402    */
403   public int lastIndexOf(Object o) {
404     read();
405     return bag.lastIndexOf(o);
406   }
407 
408   /**
409    * @see java.util.List#listIterator()
410    */
411   public ListIterator listIterator() {
412     read();
413     return new ListIteratorProxy( bag.listIterator() );
414   }
415 
416   /**
417    * @see java.util.List#listIterator(int)
418    */
419   public ListIterator listIterator(int i) {
420     read();
421     return new ListIteratorProxy( bag.listIterator(i) );
422   }
423 
424   /**
425    * @see java.util.List#remove(int)
426    */
427   public Object remove(int i) {
428     write();
429     return bag.remove(i);
430   }
431 
432   /**
433    * @see java.util.List#set(int, Object)
434    */
435   public Object set(int i, Object o) {
436     write();
437     return bag.set(i, o);
438   }
439 
440   /**
441    * @see java.util.List#subList(int, int)
442    */
443   public List subList(int start, int end) {
444     read();
445     return new ListProxy( bag.subList(start, end) );
446   }
447 
448   public String toString() {
449     read();
450     return bag.toString();
451   }
452 
453   /*public boolean equals(Object other) {
454     read();
455     return bag.equals(other);
456   }
457 
458   public int hashCode(Object other) {
459     read();
460     return bag.hashCode();
461   }*/
462 
463   public boolean entryExists(Object entry, int i) {
464     return entry!=null;
465   }
466 
467   /**
468    * Bag does not respect the collection API and do an
469    * JVM instance comparison to do the equals.
470    * The semantic is broken not to have to initialize a
471    * collection for a simple equals() operation.
472    * @see java.lang.Object#equals(java.lang.Object)
473    */
474   public boolean equals(Object obj) {
475     return super.equals(obj);
476   }
477 
478   /**
479    * @see java.lang.Object#hashCode()
480    */
481   public int hashCode() {
482     return super.hashCode();
483   }
484 
485 }