KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > mdr > storagemodel > transientimpl > TransientMultivaluedIndex


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.mdr.storagemodel.transientimpl;
21
22 import java.util.ArrayList JavaDoc;
23 import java.util.Collection JavaDoc;
24 import java.util.Iterator JavaDoc;
25 import java.util.HashMap JavaDoc;
26 import org.netbeans.mdr.persistence.StorageException;
27 import org.netbeans.mdr.persistence.StorageBadRequestException;
28 import org.netbeans.mdr.persistence.SinglevaluedIndex;
29 import org.netbeans.mdr.persistence.MultivaluedIndex;
30 import org.netbeans.mdr.persistence.Storage;
31 import org.netbeans.mdr.storagemodel.MdrStorage;
32 import org.netbeans.mdr.util.DebugException;
33 import org.netbeans.mdr.util.MapEntryImpl;
34 /**
35  *
36  * @author Tomas Zezula
37  */

38 public class TransientMultivaluedIndex extends TransientIndex implements MultivaluedIndex {
39     
40     protected boolean unique;
41     
42     protected class SlotCollection implements Collection JavaDoc {
43         
44         protected Object JavaDoc key;
45         protected Collection JavaDoc st;
46         protected SinglevaluedIndex repos;
47         
48         public SlotCollection(Object JavaDoc key, Collection JavaDoc st) {
49             this(key, st, null);
50         }
51         
52         public SlotCollection(Object JavaDoc key, Collection JavaDoc st, SinglevaluedIndex repos) {
53             this.key = key;
54             this.st = st;
55             this.repos = repos;
56         }
57         
58         public boolean add (Object JavaDoc obj) {
59             if (this.repos != null)
60                 throw new UnsupportedOperationException JavaDoc();
61             try {
62                 addToCollection(st, key, obj);
63                 handleAdd(key, obj);
64                 return true;
65             }catch (StorageException se) {
66                 throw new DebugException(se.toString());
67             }
68         }
69         
70         public boolean addAll(java.util.Collection JavaDoc collection) {
71             boolean result = false;
72             for (Iterator JavaDoc it = collection.iterator(); it.hasNext();) {
73                 result |= this.add(it.next());
74             }
75             return result;
76         }
77         
78         public void clear() {
79             for (Iterator JavaDoc it = this.st.iterator(); it.hasNext();) {
80                 Entry e = (Entry) it.next();
81                 it.remove();
82                 e.dispose();
83                 txlog.push( new CompensatingTransaction.RemoveCTx(e.getKey(),e.getValue()));
84             }
85         }
86         
87         public boolean contains(Object JavaDoc obj) {
88             if (this.repos != null)
89                 throw new UnsupportedOperationException JavaDoc();
90             expungeStaleEntries();
91             for (Iterator JavaDoc it = this.st.iterator(); it.hasNext();) {
92                 Entry e = (Entry) it.next();
93                 if (obj.equals(e.getValue()))
94                     return true;
95             }
96             return false;
97         }
98         
99         public boolean containsAll(java.util.Collection JavaDoc collection) {
100             boolean result = true;
101             for (Iterator JavaDoc it = collection.iterator(); it.hasNext();) {
102                 result &= contains(it.next());
103             }
104             return result;
105         }
106         
107         public boolean isEmpty() {
108             expungeStaleEntries();
109             return this.st.size() == 0;
110         }
111         
112         public java.util.Iterator JavaDoc iterator() {
113             return new SlotIterator(this.key, this.st, this.repos);
114         }
115         
116         public boolean remove(Object JavaDoc obj) {
117             if (this.repos != null)
118                 throw new UnsupportedOperationException JavaDoc();
119             expungeStaleEntries();
120             for (Iterator JavaDoc it = this.st.iterator(); it.hasNext();) {
121                 Entry entry = (Entry) it.next();
122                 if (obj.equals(entry.getValue())) {
123                     it.remove();
124                     txlog.push( new CompensatingTransaction.RemoveCTx(entry.getKey(),entry.getValue()));
125                     entry.dispose();
126                     return true;
127                 }
128             }
129             return false;
130         }
131         
132         public boolean removeAll(java.util.Collection JavaDoc collection) {
133             boolean result = false;
134             for (Iterator JavaDoc it = collection.iterator(); it.hasNext(); ) {
135                 result |= remove(it.next());
136             }
137             return result;
138         }
139         
140         public boolean retainAll(java.util.Collection JavaDoc collection) {
141             if (this.repos != null)
142                 throw new UnsupportedOperationException JavaDoc();
143             boolean result = false;
144             for (Iterator JavaDoc it = this.st.iterator(); it.hasNext();) {
145                 Entry entry = (Entry) it.next();
146                 if (!entry.isValid()) {
147                     it.remove();
148                     entry.dispose();
149                 }
150                 else if (!collection.contains( entry.getValue())) {
151                     it.remove();
152                     entry.dispose();
153                     txlog.push( new CompensatingTransaction.RemoveCTx(entry.getKey(),entry.getValue()));
154                     result = true;
155                 }
156             }
157             return result;
158         }
159         
160         public int size() {
161             expungeStaleEntries();
162             return this.st.size();
163         }
164         
165         public Object JavaDoc[] toArray() {
166             ArrayList JavaDoc result = this.collectValues();
167             return result.toArray();
168         }
169         
170         public Object JavaDoc[] toArray(Object JavaDoc[] obj) {
171             ArrayList JavaDoc result = this.collectValues();
172             return result.toArray(obj);
173         }
174         
175         private ArrayList JavaDoc collectValues() {
176             ArrayList JavaDoc result = new ArrayList JavaDoc();
177             for (Iterator JavaDoc it = this.st.iterator(); it.hasNext();) {
178                 Entry entry = (Entry) it.next();
179                 if (!entry.isValid()) {
180                     it.remove();
181                     entry.dispose();
182                 }
183                 else {
184                     try {
185                         result.add(map(this.key, entry.getValue(), this.repos));
186                     }catch (StorageException se) {
187                         throw new DebugException(se.toString());
188                     }
189                 }
190             }
191             return result;
192         }
193         
194     }
195     
196     protected class MultivaluedEntryKeySet extends EntryKeySet {
197         
198         protected ArrayList JavaDoc collectKeys() {
199             ArrayList JavaDoc result = new ArrayList JavaDoc();
200             for (Iterator JavaDoc it = map.values().iterator(); it.hasNext(); ) {
201                 Collection JavaDoc c = (Collection JavaDoc) it.next();
202                 if (isValidCollection(c)) {
203                     result.add(((Entry)c.iterator().next()).getKey());
204                 }
205             }
206             return result;
207         }
208         
209         public java.util.Iterator JavaDoc iterator() {
210             return new MultivaluedEntryKeyIterator();
211         }
212         
213     }
214     
215     protected class SlotIterator implements Iterator JavaDoc {
216         
217         protected Object JavaDoc key;
218         protected SinglevaluedIndex repos;
219         protected Collection JavaDoc collection;
220         protected Iterator JavaDoc innerIt;
221         protected Entry top;
222         protected Entry last;
223         
224         public SlotIterator(Collection JavaDoc c) {
225             this(c, null, null);
226         }
227         
228         public SlotIterator(Object JavaDoc key, Collection JavaDoc c, SinglevaluedIndex repos) {
229             this(key, c, repos, c.iterator());
230         }
231         
232         protected SlotIterator(Object JavaDoc key, Collection JavaDoc c, SinglevaluedIndex repos, Iterator JavaDoc it) {
233             this.key = key;
234             this.collection = c;
235             this.repos = repos;
236             this.innerIt = it;
237         }
238         
239         public boolean hasNext() {
240             while (this.top == null) {
241                 if (!this.innerIt.hasNext())
242                     return false;
243                 this.top = (Entry) this.innerIt.next();
244                 if (! this.top.isValid()) {
245                     this.innerIt.remove();
246                     this.top.dispose();
247                     this.top = null;
248                 }
249             }
250             return true;
251         }
252         
253         public Object JavaDoc next() {
254             while (this.top == null) {
255                 this.top = (Entry) this.innerIt.next();
256                 if (! this.top.isValid()) {
257                     this.innerIt.remove();
258                     this.top.dispose();
259                     this.top = null;
260                 }
261             }
262             this.last = this.top;
263             this.top = null;
264             try {
265                 return map(this.key, this.last.getValue(), this.repos);
266             }catch (StorageException se) {
267                 throw new DebugException(se.toString());
268             }
269         }
270         
271         public void remove() {
272             if (this.last == null)
273                 throw new IllegalStateException JavaDoc();
274             this.innerIt.remove();
275             this.last.dispose();
276             txlog.push( new CompensatingTransaction.RemoveCTx(this.key, last.getValue()));
277             this.last = null;
278         }
279     }
280     
281     
282     protected class MultivaluedEntryKeyIterator implements Iterator JavaDoc {
283         
284         private Iterator JavaDoc innerIt;
285         private Collection JavaDoc top;
286         private Collection JavaDoc last;
287         
288         public MultivaluedEntryKeyIterator() {
289             this.innerIt = map.values().iterator();
290         }
291         
292         public boolean hasNext() {
293             while (top == null) {
294                 if (!this.innerIt.hasNext())
295                     return false;
296                 top = (Collection JavaDoc) this.innerIt.next();
297                 if (! isValidCollection(top))
298                     top = null;
299             }
300             return true;
301         }
302         
303         public Object JavaDoc next() {
304             while (top == null) {
305                 top = (Collection JavaDoc) this.innerIt.next();
306                 if (! isValidCollection(top))
307                     top = null;
308             }
309             last = top;
310             top = null;
311             return ((Entry)last.iterator(). next()).getKey();
312         }
313         
314         public void remove() {
315             if (last == null)
316                 throw new IllegalStateException JavaDoc();
317             innerIt.remove();
318             try {
319                 handleRemove(((Entry)last.iterator().next()).getKey(), last);
320             }catch (StorageException se) {
321                 throw new DebugException(se.toString());
322             }
323         }
324     }
325     
326     /** Creates a new instance of TransientMultivaluedIndex */
327     public TransientMultivaluedIndex(MdrStorage storage, String JavaDoc name, Storage.EntryType keyType, Storage.EntryType valueType, boolean unique) {
328         super(storage, name, keyType, valueType);
329         this.unique = unique;
330     }
331     
332     /** Adds the specified value to values associated in this index with the
333      * specified key. If the index puts limit on number of values associated
334      * with one key and adding value would break this limit, it throws
335      * StorageBadRequestException.
336      * @param key
337      * @param value
338      * @throws StorageException
339      */

340     public void add(Object JavaDoc key, Object JavaDoc value) throws StorageException {
341         this.addNoTx(key, value);
342         this.handleAdd(key, value);
343     }
344     
345     
346     
347     protected void expungeStaleEntries() {
348         KeyedReference ref = null;
349         while ((ref = (KeyedReference) refQueue.poll()) != null) {
350             ArrayList JavaDoc clearedSlots = new ArrayList JavaDoc();
351             org.netbeans.mdr.persistence.MOFID key = ref.getLookupKey();
352             if (!clearedSlots.contains(key)) {
353                 // Slot was not cleared but is dirty
354
Collection JavaDoc c = (Collection JavaDoc) this.map.get(key);
355                 this.expungeCollection(c);
356                 clearedSlots.add(key);
357             }
358         }
359     }
360     
361     protected SlotCollection createSlotCollection (Object JavaDoc key, Collection JavaDoc c) {
362         return new SlotCollection (key, c);
363     }
364     
365     protected SlotCollection createSlotCollection (Object JavaDoc key, Collection JavaDoc c, SinglevaluedIndex repos) {
366         return new SlotCollection (key, c, repos);
367     }
368     
369     /** Returns a collection view of the values associated in the index with specified key.
370      * Returned collection is read only and may not be modified.
371      * If there are no values associated with the key empty collection is returned.
372      * @return
373      * @param key
374      * @throws StorageException
375      */

376     public java.util.Collection JavaDoc getItems(Object JavaDoc key) throws StorageException {
377         if (this.map == null)
378             this.map = new HashMap JavaDoc();
379         else
380             expungeStaleEntries();
381         Collection JavaDoc c = (Collection JavaDoc) this.map.get(key);
382         if (c == null) {
383             c = new ArrayList JavaDoc();
384             this.map.put(key,c);
385         }
386         return createSlotCollection(key, c);
387     }
388     
389     /** Like getItems, but if the index contains keys, this returns the objects
390      * corresponding to the key
391      * @return
392      * @param key
393      * @throws StorageException
394      */

395     public java.util.Collection JavaDoc getObjects(Object JavaDoc key, SinglevaluedIndex repos) throws StorageException {
396         if (this.map == null)
397             this.map = new HashMap JavaDoc();
398         else
399             expungeStaleEntries();
400         Collection JavaDoc c = (Collection JavaDoc) this.map.get(key);
401         if (c == null) {
402             c = new ArrayList JavaDoc();
403             this.map.put(key, c);
404         }
405         return createSlotCollection(key, c, repos);
406     }
407     
408     protected void handleRemove(Object JavaDoc key, Object JavaDoc value) throws StorageException {
409         Collection JavaDoc c = (Collection JavaDoc) value;
410         for (Iterator JavaDoc it = c.iterator(); it.hasNext();) {
411             Entry e = (Entry) it.next();
412             it.remove();
413             e.dispose();
414             this.txlog.push( new CompensatingTransaction.RemoveCTx(key, e.getValue()));
415         }
416     }
417     
418     /** If true, the collection of values is contrained to hold
419      * no more than one of any value.
420      * @throws StorageException
421      * @param key
422      * @param repos where to fetch objects from
423      * @return
424      */

425     public boolean isUnique() throws StorageException {
426         return this.unique;
427     }
428     
429     /** Removes the first occurrence of the specified element in the list
430      * of values associated with the specified key.
431      * @return true if this index changed as a result of this call
432      * @param key
433      * @param value
434      */

435     public boolean remove(Object JavaDoc key, Object JavaDoc value) throws StorageException {
436         Object JavaDoc result = this.removeNoTx (key, value);
437         this.txlog.push( new CompensatingTransaction.RemoveCTx(key, result));
438         return result != null;
439     }
440     
441     public java.util.Set JavaDoc keySet() throws StorageException {
442         if (this.map == null)
443             this.map = new HashMap JavaDoc();
444         return new MultivaluedEntryKeySet();
445     }
446     
447     
448     /**
449      * Returns key-value pairs, where the key contains the queried prefix.
450      */

451     public Collection JavaDoc queryByKeyPrefix (Object JavaDoc prefix, SinglevaluedIndex primaryIndex) throws StorageException {
452         if (getKeyType () != Storage.EntryType.STRING) {
453             throw new UnsupportedOperationException JavaDoc ("Key type must be EntryType.STRING");
454         }
455         if (!(prefix instanceof String JavaDoc)) {
456             throw new StorageBadRequestException ("String object parameter expected.");
457         }
458         
459         java.util.List JavaDoc result = new java.util.LinkedList JavaDoc ();
460         Iterator JavaDoc iter = keySet().iterator ();
461         while (iter.hasNext ()) {
462             String JavaDoc key = (String JavaDoc) iter.next ();
463             if (key.startsWith ((String JavaDoc) prefix)) {
464                 result.add (new MapEntryImpl (key, getObjects (key, primaryIndex)));
465             }
466         }
467         return result;
468     }
469     
470     protected Object JavaDoc map(Object JavaDoc key, Object JavaDoc value, SinglevaluedIndex index) throws StorageException {
471         if (index == null)
472             return value;
473         String JavaDoc thisStorage = MdrStorage.getStorageIdFromMofId((org.netbeans.mdr.persistence.MOFID)key);
474         String JavaDoc otherStorage = MdrStorage.getStorageIdFromMofId((org.netbeans.mdr.persistence.MOFID)value);
475         if (thisStorage.equals(otherStorage))
476             return index.get(value);
477         else
478             return this.storage.resolve(otherStorage, value);
479     }
480     
481     protected final void addNoTx(Object JavaDoc key, Object JavaDoc value) throws StorageException {
482         if (this.map == null) {
483             this.map = new HashMap JavaDoc();
484         }
485         
486         ArrayList JavaDoc list = (ArrayList JavaDoc) this.map.get(key);
487         if (list == null) {
488             list = new ArrayList JavaDoc();
489             this.map.put(key, list);
490         }
491         this.addToCollection(list, key, value);
492     }
493     
494     protected final Object JavaDoc removeNoTx(Object JavaDoc key, Object JavaDoc value) throws StorageException {
495         if (this.map == null)
496             return null;
497         else
498             expungeStaleEntries();
499         Collection JavaDoc c = (Collection JavaDoc) this.map.get(key);
500         if (c == null)
501             return null;
502         for (Iterator JavaDoc it = c.iterator(); it.hasNext();) {
503             Entry e = (Entry) it.next();
504             Object JavaDoc evalue = e.getValue();
505             if (value.equals(evalue)) {
506                 it.remove();
507                 e.dispose();
508                 return evalue;
509             }
510         }
511         return null;
512     }
513     
514     private void addToCollection(Collection JavaDoc c, Object JavaDoc key, Object JavaDoc value) throws StorageException {
515         if (this.unique) {
516             for (Iterator JavaDoc it = c.iterator(); it.hasNext();) {
517                 Entry e = (Entry) it.next();
518                 if (value.equals(e.getValue()))
519                     throw new StorageBadRequestException("Value: "+value+" is already contained.");
520             }
521         }
522         Entry e = new Entry(key, value);
523         c.add(e);
524     }
525     
526     private static void expungeCollection(Collection JavaDoc c) {
527         if (c == null)
528             return;
529         for (Iterator JavaDoc it = c.iterator(); it.hasNext();) {
530             Entry e = (Entry) it.next();
531             if (!e.isValid()) {
532                 e.dispose();
533                 it.remove();
534             }
535         }
536     }
537     
538     
539     private static boolean isValidCollection(Object JavaDoc obj) {
540         Collection JavaDoc c = (Collection JavaDoc) obj;
541         if (c.size() == 0)
542             return false;
543         for (Iterator JavaDoc it = c.iterator(); it.hasNext();) {
544             Entry e = (Entry) it.next();
545             if (!e.isValid()) {
546                 it.remove();
547                 e.dispose();
548             }
549             else
550                 return true;
551         }
552         return false;
553     }
554     
555 }
556
Popular Tags