KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > jdo > spi > persistence > support > sqlstore > sco > HashSet


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23
24 /*
25  * sco.HashSet.java
26  */

27
28 package com.sun.jdo.spi.persistence.support.sqlstore.sco;
29
30 import java.util.ArrayList JavaDoc;
31 import java.util.Collection JavaDoc;
32 import java.util.Iterator JavaDoc;
33 import java.util.ResourceBundle JavaDoc;
34
35 import com.sun.jdo.api.persistence.support.JDOUserException;
36 import com.sun.jdo.spi.persistence.support.sqlstore.PersistenceCapable;
37 import com.sun.jdo.spi.persistence.support.sqlstore.StateManager;
38 import com.sun.jdo.spi.persistence.support.sqlstore.SCOCollection;
39 import com.sun.jdo.spi.persistence.utility.I18NHelper;
40 import com.sun.jdo.spi.persistence.support.sqlstore.PersistenceManager;
41
42
43 /**
44  * A mutable 2nd class object date.
45  * @author Marina Vatkina
46  * @version 1.0
47  * @see java.util.HashSet
48  */

49 public class HashSet
50     extends java.util.HashSet JavaDoc
51     implements SCOCollection
52 {
53
54     private transient PersistenceCapable owner;
55
56     private transient String JavaDoc fieldName;
57
58     private transient Class JavaDoc elementType;
59
60     private transient boolean allowNulls;
61
62     private transient java.util.HashSet JavaDoc added = new java.util.HashSet JavaDoc();
63
64     private transient java.util.HashSet JavaDoc removed = new java.util.HashSet JavaDoc();
65
66     private transient boolean isDeferred;
67
68     /**
69      * I18N message handlers
70      */

71     private final static ResourceBundle JavaDoc messages = I18NHelper.loadBundle(
72                              "com.sun.jdo.spi.persistence.support.sqlstore.impl.Bundle", // NOI18N
73
HashSet.class.getClassLoader());
74
75     private final static ResourceBundle JavaDoc messages1 = I18NHelper.loadBundle(
76                              "com.sun.jdo.spi.persistence.support.sqlstore.Bundle", // NOI18N
77
HashSet.class.getClassLoader());
78
79
80     /**
81      * Creates a new empty <code>HashSet</code> object.
82      * Assigns owning object and field name.
83      *
84      * @param owner the owning object
85      * @param fieldName the owning field name
86      * @param elementType the element types allowed
87      * @param allowNulls true if nulls are allowed
88      */

89     public HashSet(Object JavaDoc owner, String JavaDoc fieldName, Class JavaDoc elementType, boolean allowNulls)
90     {
91         super();
92     if (owner instanceof PersistenceCapable)
93         {
94                 this.owner = (PersistenceCapable)owner;
95             this.fieldName = fieldName;
96         }
97     this.elementType = elementType;
98         this.allowNulls = allowNulls;
99     }
100
101     /**
102      * Creates a new empty <code>HashSet</code> object that has
103      * the specified initial capacity.Assigns owning object and field name.
104      *
105      * @param owner the owning object
106      * @param fieldName the owning field name
107      * @param elementType the element types allowed
108      * @param allowNulls true if nulls are allowed
109      * @param initialCapacity the initial capacity of the hash map.
110      * @throws IllegalArgumentException if the initial capacity is less
111      * than zero.
112      * @see java.util.HashSet
113      */

114     public HashSet(Object JavaDoc owner, String JavaDoc fieldName,
115                                 Class JavaDoc elementType, boolean allowNulls,
116                                 int initialCapacity)
117     {
118     super(initialCapacity);
119     if (owner instanceof PersistenceCapable)
120         {
121                 this.owner = (PersistenceCapable)owner;
122             this.fieldName = fieldName;
123         }
124     this.elementType = elementType;
125         this.allowNulls = allowNulls;
126     }
127
128     // -------------------------Public Methods------------------
129

130     /**
131      * Adds the specified element to this set if it is not already
132      * present.
133      *
134      * @param o element to be added to this set.
135      * @return <tt>true</tt> if the set did not already contain the specified
136      * element.
137      * @see java.util.HashSet
138      */

139     public boolean add(Object JavaDoc o)
140     {
141         if (allowNulls == false && o == null)
142         {
143             throw new JDOUserException(I18NHelper.getMessage(messages,
144                         "sco.nulls_not_allowed")); // NOI18N
145
}
146
147         if (elementType != null && !elementType.isAssignableFrom(o.getClass()))
148         {
149             throw new JDOUserException(I18NHelper.getMessage(messages,
150                                      "sco.classcastexception", elementType.getName()), // NOI18N
151
new ClassCastException JavaDoc(), new Object JavaDoc[] {o});
152         }
153
154         if (owner != null)
155         {
156             StateManager stateManager = owner.jdoGetStateManager();
157
158             if (stateManager != null)
159             {
160                 PersistenceManager pm = (PersistenceManager) stateManager.getPersistenceManagerInternal();
161
162                 pm.acquireShareLock();
163
164                 boolean modified = false;
165
166                 try
167                 {
168                     pm.acquireFieldUpdateLock();
169                     try
170                     {
171                        // Mark the field as dirty
172
stateManager.makeDirty(fieldName);
173
174                        modified = super.add(o);
175
176                        if (modified)
177                        {
178                            if (removed.remove(o) == false)
179                            {
180                                added.add(o);
181                            }
182                            stateManager.applyUpdates(fieldName, this);
183                        }
184                        return modified;
185                     }
186                     finally
187                     {
188                         pm.releaseFieldUpdateLock();
189                     }
190
191                 }
192                 catch (JDOUserException e)
193                 {
194                     Object JavaDoc[] failedObjects = e.getFailedObjectArray();
195
196                     if (modified && (failedObjects != null))
197                     {
198                         //
199
// The failedObjects array may contain objects other
200
// than the one added. We iterate through it to find
201
// the one added and remove it from the collection.
202
//
203
for (int i = 0; i < failedObjects.length; i++)
204                         {
205                             Object JavaDoc failedObject = failedObjects[i];
206
207                             if (failedObject == o)
208                             {
209                                 super.remove(failedObject);
210                                 break;
211                             }
212                         }
213                     }
214
215                     throw e;
216                 }
217                 finally
218                 {
219                     pm.releaseShareLock();
220                 }
221             }
222         }
223
224         return super.add(o);
225     }
226
227     /**
228      * Adds all of the elements in the specified collection to this collection
229      *
230      * @param c collection whose elements are to be added to this collection.
231      * @return <tt>true</tt> if this collection changed as a result of the
232      * call.
233      * @throws UnsupportedOperationException if the <tt>addAll</tt> method is
234      * not supported by this collection.
235      *
236      * @see java.util.AbstractCollection
237      * @see java.util.HashSet
238      */

239     public boolean addAll(Collection JavaDoc c)
240     {
241         if (allowNulls == false && c.contains(null))
242         {
243             throw new JDOUserException(I18NHelper.getMessage(messages,
244                         "sco.nulls_not_allowed")); // NOI18N
245
}
246
247         ArrayList errc = new ArrayList();
248
249         if (elementType != null)
250         {
251             // iterate the collection and make a list of wrong elements.
252
Iterator JavaDoc i = c.iterator();
253             while (i.hasNext())
254             {
255                 Object JavaDoc o = i.next();
256                 if (!elementType.isAssignableFrom(o.getClass()))
257                     errc.add(o);
258             }
259         }
260
261         if (errc != null && errc.size() > 0)
262         {
263             throw new JDOUserException(I18NHelper.getMessage(messages,
264                                      "sco.classcastexception", elementType.getName()), // NOI18N
265
new ClassCastException JavaDoc(), errc.toArray());
266         }
267
268         boolean modified = false;
269
270         if (owner != null)
271         {
272             StateManager stateManager = owner.jdoGetStateManager();
273
274             if (stateManager != null)
275             {
276                 PersistenceManager pm = (PersistenceManager) stateManager.getPersistenceManagerInternal();
277
278                 pm.acquireShareLock();
279
280                 try
281                 {
282                     pm.acquireFieldUpdateLock();
283                     try
284                     {
285                         // Mark the field as dirty
286
stateManager.makeDirty(fieldName);
287
288                         for (Iterator JavaDoc iter = c.iterator(); iter.hasNext();)
289                         {
290                             Object JavaDoc o = iter.next();
291                             if (!super.contains(o))
292                             {
293                                 if (removed.remove(o) == false)
294                                 {
295                                     added.add(o);
296                                 }
297
298                                 super.add(o);
299                                 modified = true;
300                             }
301                         }
302
303                         // Apply updates
304
if (modified)
305                         {
306                             stateManager.applyUpdates(fieldName, this);
307                         }
308                         return modified;
309                     }
310                     finally
311                     {
312                         pm.releaseFieldUpdateLock();
313                     }
314                 }
315                 catch (JDOUserException e)
316                 {
317                     Object JavaDoc[] failedObjects = e.getFailedObjectArray();
318
319                     if (modified && (failedObjects != null))
320                     {
321                         for (int i = 0; i < failedObjects.length; i++)
322                         {
323                             super.remove(failedObjects[i]);
324                         }
325                     }
326
327                     throw e;
328                 }
329                 finally
330                 {
331                     pm.releaseShareLock();
332                 }
333             }
334         }
335
336         return super.addAll(c);
337     }
338
339     /**
340      * Removes the given element from this set if it is present.
341      *
342      * @param o object to be removed from this set, if present.
343      * @return <tt>true</tt> if the set contained the specified element.
344      * @see java.util.HashSet
345      */

346     public boolean remove(Object JavaDoc o)
347     {
348     // Mark the field as dirty
349

350         if (owner != null)
351         {
352             StateManager stateManager = owner.jdoGetStateManager();
353
354             if (stateManager != null)
355             {
356                 PersistenceManager pm = (PersistenceManager) stateManager.getPersistenceManagerInternal();
357
358                 pm.acquireShareLock();
359
360                 try
361                 {
362                     pm.acquireFieldUpdateLock();
363                     try
364                     {
365                         stateManager.makeDirty(fieldName);
366
367                         boolean modified = super.remove(o);
368
369                         if (modified)
370                         {
371                             if (added.remove(o) == false)
372                             {
373                                 removed.add(o);
374                             }
375
376                             stateManager.applyUpdates(fieldName, this);
377                         }
378
379                         return modified;
380                     }
381                     finally
382                     {
383                         pm.releaseFieldUpdateLock();
384                     }
385                 }
386                 finally
387                 {
388                     pm.releaseShareLock();
389                 }
390             }
391         }
392
393         return super.remove(o);
394     }
395
396
397     /**
398      * Removes from this collection all of its elements that are contained in
399      * the specified collection (optional operation). <p>
400      *
401      *
402      * @param c elements to be removed from this collection.
403      * @return <tt>true</tt> if this collection changed as a result of the
404      * call.
405      *
406      * @throws UnsupportedOperationException removeAll is not supported
407      * by this collection.
408      *
409      * @see java.util.HashSet
410      * @see java.util.AbstractCollection
411      */

412     public boolean removeAll(Collection JavaDoc c)
413     {
414         // Mark the field as dirty
415

416         if (owner != null)
417         {
418             StateManager stateManager = owner.jdoGetStateManager();
419
420             if (stateManager != null)
421             {
422                 PersistenceManager pm = (PersistenceManager) stateManager.getPersistenceManagerInternal();
423
424                 pm.acquireShareLock();
425
426                 try
427                 {
428                     pm.acquireFieldUpdateLock();
429                     try
430                     {
431                         stateManager.makeDirty(fieldName);
432
433                         for (Iterator JavaDoc iter = c.iterator(); iter.hasNext();)
434                         {
435                             Object JavaDoc o = iter.next();
436                             if (super.contains(o))
437                             {
438                                 if (added.remove(o) == false)
439                                 {
440                                     removed.add(o);
441                                 }
442                             }
443                         }
444
445                         boolean modified = super.removeAll(c);
446
447                         // Apply updates
448
if (modified)
449                         {
450                             stateManager.applyUpdates(fieldName, this);
451                         }
452
453                         return modified;
454                     }
455                     finally
456                     {
457                         pm.releaseFieldUpdateLock();
458                     }
459                 }
460                 finally
461                 {
462                     pm.releaseShareLock();
463                 }
464             }
465         }
466
467         return super.removeAll(c);
468     }
469
470     /**
471      * Retains only the elements in this collection that are contained in the
472      * specified collection (optional operation).
473      *
474      * @return <tt>true</tt> if this collection changed as a result of the
475      * call.
476      *
477      * @throws UnsupportedOperationException if the <tt>retainAll</tt> method
478      * is not supported by this collection.
479      *
480      * @see java.util.HashSet
481      * @see java.util.AbstractCollection
482      */

483     public boolean retainAll(Collection JavaDoc c)
484     {
485         if (owner != null)
486         {
487             StateManager stateManager = owner.jdoGetStateManager();
488
489             if (stateManager != null)
490             {
491                 PersistenceManager pm = (PersistenceManager) stateManager.getPersistenceManagerInternal();
492
493                 pm.acquireShareLock();
494
495                 try
496                 {
497                     pm.acquireFieldUpdateLock();
498                     try
499                     {
500                         // Mark the field as dirty
501
stateManager.makeDirty(fieldName);
502
503                         for (Iterator JavaDoc iter = super.iterator(); iter.hasNext();)
504                         {
505                             Object JavaDoc o = iter.next();
506                             if (!c.contains(o))
507                             {
508                                 if (added.remove(o) == false)
509                                 {
510                                     removed.add(o);
511                                 }
512                             }
513                         }
514
515                         boolean modified = super.retainAll(c);
516
517                         // Apply updates
518

519                         if (modified)
520                         {
521                             stateManager.applyUpdates(fieldName, this);
522                         }
523
524                         return modified;
525                     }
526                     finally
527                     {
528                         pm.releaseFieldUpdateLock();
529                     }
530                 }
531                 finally
532                 {
533                     pm.releaseShareLock();
534                 }
535             }
536         }
537
538         return super.retainAll(c);
539     }
540
541     /**
542      * Removes all of the elements from this set.
543      * @see java.util.HashSet
544      */

545     public void clear()
546     {
547         if (owner != null)
548         {
549             StateManager stateManager = owner.jdoGetStateManager();
550
551             if (stateManager != null)
552             {
553                 PersistenceManager pm = (PersistenceManager) stateManager.getPersistenceManagerInternal();
554
555                 pm.acquireShareLock();
556
557                 try
558                 {
559                     pm.acquireFieldUpdateLock();
560                     try
561                     {
562                         // Mark the field as dirty
563
stateManager.makeDirty(fieldName);
564
565                         removed.clear();
566                         added.clear();
567
568                         for (Iterator JavaDoc iter = super.iterator(); iter.hasNext();)
569                         {
570                             removed.add(iter.next());
571                         }
572
573                         super.clear();
574
575                         // Apply updates
576
stateManager.applyUpdates(fieldName, this);
577                         return;
578                     }
579                     finally
580                     {
581                         pm.releaseFieldUpdateLock();
582                     }
583                 }
584                 finally
585                 {
586                     pm.releaseShareLock();
587                 }
588             }
589         }
590
591         super.clear();
592     }
593
594     /**
595      * Creates and returns a copy of this object.
596      *
597      * <P>Mutable Second Class Objects are required to provide a public
598      * clone method in order to allow for copying PersistenceCapable
599      * objects. In contrast to Object.clone(), this method must not throw a
600      * CloneNotSupportedException.
601      */

602     public Object JavaDoc clone()
603     {
604         HashSet obj = (HashSet) super.clone();
605
606         // RESOLVE: check if added/removed should not be cleared
607
// for a deferred collection, but applyDeferredUpdates logic
608
// be used?
609
obj.unsetOwner();
610
611         return obj;
612     }
613
614     /**
615      * Returns an iterator over the elements in this set. The elements
616      * are returned in no particular order.
617      *
618      * @return an Iterator over the elements in this set.
619      * @see java.util.ConcurrentModificationException
620      */

621     public Iterator JavaDoc iterator() {
622         return new SCOHashIterator(super.iterator(), this);
623     }
624
625     private class SCOHashIterator implements Iterator JavaDoc {
626         Iterator JavaDoc _iterator = null;
627         HashSet _caller = null;
628         Object JavaDoc lastReturned = null;
629
630         SCOHashIterator(Iterator JavaDoc it, HashSet cl) {
631             _iterator = it;
632             _caller = cl;
633         }
634
635         public boolean hasNext() {
636             return _iterator.hasNext();
637         }
638
639         public Object JavaDoc next() {
640             lastReturned = _iterator.next();
641             return lastReturned;
642         }
643
644         public void remove() {
645             // Check if called twice.
646
if (lastReturned == null)
647                 throw new IllegalStateException JavaDoc();
648
649             if (_caller.owner != null) {
650                 // Mark the field as dirty
651
StateManager stateManager = _caller.owner.jdoGetStateManager();
652
653                 if (stateManager != null) {
654                     PersistenceManager pm = (PersistenceManager) stateManager.getPersistenceManagerInternal();
655
656                     pm.acquireShareLock();
657
658                     try {
659                         pm.acquireFieldUpdateLock();
660                         try
661                         {
662                             stateManager.makeDirty(_caller.fieldName);
663
664                             _iterator.remove();
665
666                             if (added.remove(lastReturned) == false) {
667                                 removed.add(lastReturned);
668                             }
669
670                             stateManager.applyUpdates(_caller.fieldName, _caller);
671
672                         } finally {
673                             pm.releaseFieldUpdateLock();
674                         }
675                     }
676                     finally
677                     {
678                         pm.releaseShareLock();
679                     }
680                 }
681             } else {
682                 // No owner - regular HashSet operation.
683
_iterator.remove();
684             }
685             lastReturned = null;
686         }
687     }
688
689     //
690
// The following internal methods should be called under an outer lock such
691
// as fieldUpdateLock. There is no need to synchronize them.
692
//
693

694     /**
695      * Creates and returns a copy of this object without resetting the owner and field value.
696      *
697      */

698     public Object JavaDoc cloneInternal()
699     {
700         return super.clone();
701     }
702
703     /**
704      * Cleans removed and added lists
705      */

706     public void reset()
707     {
708         // RESOLVE: do we need to synchronize this??
709
if (added != null)
710             added.clear();
711
712         if (removed != null)
713             removed.clear();
714     }
715
716     /**
717      * Mark this HashSet as deferred.
718      */

719     public void markDeferred()
720     {
721         isDeferred = true;
722     }
723
724     /**
725      * Return true is this HashSet is deferred, false otherwise.
726      */

727     public boolean isDeferred()
728     {
729         return isDeferred;
730     }
731
732     /**
733      * If the HashSet is deferred, we first initialize the internal collection
734      * with c and they apply any deferred updates specified by the added and
735      * removed lists.
736      */

737     public void applyDeferredUpdates(Collection JavaDoc c)
738     {
739         if (!isDeferred)
740         {
741             // should throw an exception??
742
return;
743         }
744
745         isDeferred = false;
746         addAllInternal(c);
747
748         addAllInternal(added);
749         removeAllInternal(removed);
750         added.clear();
751         removed.clear();
752     }
753
754     /**
755       * Adds an object to the list without recording changes if the HashSet is
756       * not deferred. Otherwise, add o to the added list.
757      */

758     public void addInternal(Object JavaDoc o)
759     {
760         if (isDeferred)
761         {
762             if (removed.remove(o) == false)
763             {
764                 added.add(o);
765             }
766         }
767         else
768         {
769             super.add(o);
770         }
771     }
772
773
774     /**
775      * Adds a Collection to the list without recording changes if the HashSet is
776      * not deferred. Otherwise, add o to the removed list.
777      */

778     public void addAllInternal(Collection JavaDoc c)
779     {
780         if (c == null)
781         {
782             return;
783         }
784
785         Iterator JavaDoc iter = c.iterator();
786
787         while (iter.hasNext())
788         {
789             addInternal(iter.next());
790         }
791     }
792
793     /**
794      * @inheritDoc
795      */

796     public void addToBaseCollection(Object JavaDoc o)
797     {
798         super.add(o);
799     }
800
801     /*
802      * Remove c from the list if the HashSet is not deferred.
803      * Otherwise, add c to the removed list.
804      */

805     public void removeAllInternal(Collection JavaDoc c)
806     {
807         if (c == null)
808         {
809             return;
810         }
811
812         Iterator JavaDoc iter = c.iterator();
813
814         while (iter.hasNext())
815         {
816             removeInternal(iter.next());
817         }
818     }
819
820     /**
821      * Returns added collection
822      *
823      * @return added collection of added elements
824      */

825     public Collection JavaDoc getAdded()
826     {
827         return (Collection JavaDoc)added;
828     }
829
830     /**
831      * Returns removed collection
832      *
833      * @return removed collection of removed elements
834      */

835     public Collection JavaDoc getRemoved()
836     {
837         return (Collection JavaDoc)removed;
838     }
839
840
841     /**
842      * Clears Collection without notifing the owner
843      */

844     public void clearInternal()
845     {
846         super.clear();
847         this.reset();
848     }
849
850     /**
851      * Removes an element without notifing the owner
852      */

853     public void removeInternal(Object JavaDoc o)
854     {
855         if (isDeferred)
856         {
857             if (added.remove(o) == false)
858             {
859                 removed.add(o);
860             }
861
862         }
863         else
864         {
865             super.remove(o);
866         }
867     }
868
869     /**
870      * Nullifies references to the owner Object and Field
871      */

872     public void unsetOwner()
873     {
874         this.owner = null;
875         this.fieldName = null;
876         this.elementType = null;
877                 added.clear();
878                 removed.clear();
879     }
880
881     /**
882      * Returns the owner object of the SCO instance
883      *
884      * @return owner object
885      */

886     public Object JavaDoc getOwner()
887     {
888         return this.owner;
889     }
890
891     /**
892      * Returns the field name
893      *
894      * @return field name as java.lang.String
895      */

896     public String JavaDoc getFieldName()
897     {
898         return this.fieldName;
899     }
900
901     /**
902      * Marks object dirty
903      */

904     public StateManager makeDirty()
905     {
906         StateManager stateManager = owner.jdoGetStateManager();
907
908         if (stateManager != null)
909         {
910             stateManager.makeDirty(fieldName);
911         }
912
913         return stateManager;
914     }
915
916
917     /**
918      * Apply changes (can be a no-op)
919      */

920     public void applyUpdates(StateManager sm, boolean modified)
921     {
922          if (modified && sm != null)
923         {
924             sm.applyUpdates(fieldName, this);
925         }
926     }
927
928     /**
929      * Set the owner if this instance is not owned.
930      * @see SCOCollection#setOwner
931      * @param owner the new owner.
932      * @param fieldName the new field name.
933      * @param elementType the new element type as Class, or null if type
934      * is not checked or not supported.
935      */

936     public void setOwner(Object JavaDoc owner, String JavaDoc fieldName, Class JavaDoc elementType) {
937
938         if (this.owner != null) {
939             throw new JDOUserException(I18NHelper.getMessage(
940                 messages1, "core.statemanager.anotherowner"), // NOI18N
941
new Object JavaDoc[]{this.owner, this.fieldName});
942         }
943         if (owner instanceof PersistenceCapable) {
944                 this.owner = (PersistenceCapable)owner;
945                 this.fieldName = fieldName;
946                 this.elementType = elementType;
947         }
948     }
949     }
950
951
952
953
954
Popular Tags