KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > mdr > persistence > memoryimpl > MultivaluedIndexImpl


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 package org.netbeans.mdr.persistence.memoryimpl;
20
21 import org.netbeans.mdr.persistence.*;
22 import java.util.*;
23 import java.io.*;
24
25 import org.netbeans.mdr.util.*;
26
27 /** Default memory implementation of {@link
28  * org.netbeans.mdr.persistence.MultivaluedIndex} using
29  * {@link java.util.Hashtable}.
30  *
31  * <p>[PENDING]: {@link #isUnique()} is ignored when adding new values.
32  * @author Pavel Buzek, Martin Matula
33  * @version
34  */

35 public abstract class MultivaluedIndexImpl implements MultivaluedIndex, Streamable {
36
37     /* -------------------------------------------------------------------- */
38     /* -- Private atttributes --------------------------------------------- */
39     /* -------------------------------------------------------------------- */
40
41     protected String JavaDoc name;
42     protected Storage.EntryType keyType;
43     protected Storage.EntryType valueType;
44     protected boolean unique;
45     protected Map entries;
46     protected StorageImpl storage;
47     
48     protected MultivalueLog transLog = new MultivalueLog (this);
49     
50     /* -------------------------------------------------------------------- */
51     /* -- Constructors ---------------------------------------------------- */
52     /* -------------------------------------------------------------------- */
53
54     /** Creates a new multi-valued index. */
55     public MultivaluedIndexImpl(String JavaDoc name, StorageImpl storage, Storage.EntryType keyType, Storage.EntryType valueType, boolean unique) {
56         this.name = name;
57         this.keyType = keyType;
58         this.valueType = valueType;
59         this.unique = unique;
60         this.storage = storage;
61         entries = new HashMap();
62     }
63
64     /** Constructor used when restoring the streamable index from a stream. */
65     public MultivaluedIndexImpl() {
66     }
67
68     /* -------------------------------------------------------------------- */
69     /* -- Implementation of org.netbeans.mdr.persistence.Index ------------ */
70     /* -------------------------------------------------------------------- */
71
72     public String JavaDoc getName() throws StorageException {
73         return this.name;
74     }
75
76     public Storage.EntryType getValueType() throws StorageException {
77         return this.valueType;
78     }
79
80     public Storage.EntryType getKeyType() throws StorageException {
81         return this.keyType;
82     }
83     
84     public synchronized boolean remove(Object JavaDoc key) throws StorageException {
85         Object JavaDoc value = entries.remove(key);
86         if (value != null) {
87             transLog.logRemoveKey(key, value);
88             return true;
89         } else
90             return false;
91     }
92
93     public synchronized java.util.Set JavaDoc keySet() throws StorageException {
94         return entries.keySet();
95     }
96     
97     /** Appends the specified element to the end of the list of values
98      * associated with the specified key.
99      */

100     public synchronized void add(Object JavaDoc key,Object JavaDoc value) throws StorageException {
101         Collection vals = (Collection) entries.get (key);
102         if (vals == null) {
103             vals = new ArrayList ();
104             entries.put(key, vals);
105         } else if (unique && vals.contains(value)) {
106             throw createValueAlreadyContainedExc(key, value);
107         }
108         vals.add(value);
109         transLog.logAdd(key, value);
110     }
111
112     /* -------------------------------------------------------------------- */
113     /* -- Implementation of org.netbeans.mdr.persistence.MultivaluedIndex */
114     /* -------------------------------------------------------------------- */
115  
116     public boolean isUnique() throws StorageException {
117         return unique;
118     }
119
120     public synchronized java.util.Collection JavaDoc getItems(Object JavaDoc key) throws StorageException {
121         Collection vals = (Collection) entries.get(key);
122         if (vals == null) {
123             vals = new ArrayList();
124             entries.put(key, vals);
125         }
126         return new MIWrapper((List) vals, key);
127     }
128
129     public synchronized java.util.Collection JavaDoc getObjects(Object JavaDoc key, SinglevaluedIndex s) throws StorageException {
130         if (keyType == Storage.EntryType.MOFID) {
131             return new MOWrapper((List) getItems(key), s, key);
132         } else {
133             return getItems(key);
134         }
135     }
136     
137     /** Removes the first occurrence of the specified element in the list
138      * of values associated with the specified key.
139      */

140     public synchronized boolean remove(Object JavaDoc key,Object JavaDoc value) throws StorageException {
141         Collection vals = (Collection) entries.get (key);
142         if (vals != null && vals.remove(value)) {
143             transLog.logRemove(key, value);
144             return true;
145         } else {
146             return false;
147         }
148     }
149
150     /* -------------------------------------------------------------------- */
151     /* -- Implementation of org.netbeans.mdr.persistence.Streamable ------- */
152     /* -------------------------------------------------------------------- */
153
154     /** This method will be used to move changed object from storage cache
155      * to the persistent part of storage. It writes the object`s state
156      * (set of attributes) in the stream as an array of bytes, for example
157      * in textual representation.
158      * @param outputStream OutputStream that holds value of a Streamable object
159      */

160     public void write(java.io.OutputStream JavaDoc out) throws StorageException {
161         try {
162             IOUtils.writeString(out, name);
163             out.write(keyType.encode());
164             out.write(valueType.encode());
165             Utils.write(out, entries, storage);
166         } catch (java.io.IOException JavaDoc e) {
167             throw new StorageIOException(e);
168         }
169     }
170     /** Restore state of the Storable object from the stream.
171      * @param inputStream InputStream that represents an internal representation of fields of a Streamable object
172      * in which it was written by {@link write } method
173      */

174     public void read(java.io.InputStream JavaDoc is) throws StorageException {
175         try {
176             name = IOUtils.readString(is);
177             keyType = Storage.EntryType.decodeEntryType((byte) is.read());
178             valueType = Storage.EntryType.decodeEntryType((byte) is.read());
179             entries = (Map) Utils.read(is, storage);
180         } catch (java.io.IOException JavaDoc e) {
181             throw new StorageIOException(e);
182         }
183     }
184     
185     /**
186      * Returns key-value pairs, where the key contains the queried prefix.
187      */

188     public synchronized Collection queryByKeyPrefix (Object JavaDoc prefix, SinglevaluedIndex primaryIndex) throws StorageException {
189         if (keyType != Storage.EntryType.STRING) {
190             throw new UnsupportedOperationException JavaDoc ("Key type must be EntryType.STRING");
191         }
192         if (!(prefix instanceof String JavaDoc)) {
193             throw new StorageBadRequestException ("String object parameter expected.");
194         }
195         
196         List result = new LinkedList ();
197         Iterator iter = entries.keySet().iterator ();
198         while (iter.hasNext ()) {
199             String JavaDoc key = (String JavaDoc) iter.next ();
200             if (key.startsWith ((String JavaDoc) prefix)) {
201                 result.add (new MapEntryImpl (key, getObjects (key, primaryIndex)));
202             }
203         }
204         return result;
205     }
206     
207     /* -------------------------------------------------------------------- */
208     /* -- Transaction support --------------------------------------------- */
209     /* -------------------------------------------------------------------- */
210     
211     protected synchronized void rollBackChanges () throws StorageException {
212         transLog.rollBack ();
213         transLog.clear ();
214     }
215     
216     protected synchronized void commitChanges () throws StorageException {
217         transLog.clear ();
218     }
219     
220     /* -------------------------------------------------------------------- */
221     /* -- Methods not specified by any interface -------------------------- */
222     /* -------------------------------------------------------------------- */
223
224     protected static boolean isUniqueValue(List list, Object JavaDoc value, int index) {
225         Iterator iter = list.iterator();
226         for (int x = 0; iter.hasNext(); x++) {
227             Object JavaDoc obj = iter.next();
228             if (x == index)
229                 continue;
230             if (value.equals(obj))
231                 return false;
232         }
233         return true;
234     }
235     
236     protected StorageBadRequestException createValueAlreadyContainedExc(Object JavaDoc key, Object JavaDoc value) {
237         return new StorageBadRequestException("Unique index already contains value " + value + " for key " + key);
238     }
239     
240     public void changed(Object JavaDoc key) {
241     }
242
243     void setKey(Object JavaDoc key, Object JavaDoc vals) {
244         entries.put(key, vals);
245     }
246     
247     private class MIWrapper extends AbstractList {
248         private final List inner;
249         private final Object JavaDoc key;
250         
251         public MIWrapper(List inner, Object JavaDoc key) {
252             this.inner = inner;
253             this.key = key;
254         }
255         
256         public Object JavaDoc get(int param) {
257             synchronized (MultivaluedIndexImpl.this) {
258                 return inner.get(param);
259             }
260         }
261         
262         public int size() {
263             synchronized (MultivaluedIndexImpl.this) {
264                 return inner.size();
265             }
266         }
267         
268         public Object JavaDoc set(int index, Object JavaDoc element) {
269             synchronized (MultivaluedIndexImpl.this) {
270                 Object JavaDoc orig;
271                 if (unique && !isUniqueValue(inner, element, index)) {
272                     throw new RuntimeStorageException(createValueAlreadyContainedExc(key, element));
273                 }
274                 if ((orig = inner.set(index, element)) != null) {
275                     transLog.logReplace(key, orig, index);
276                 }
277                 return orig;
278             }
279         }
280         
281         public void add(int index, Object JavaDoc element) {
282             synchronized (MultivaluedIndexImpl.this) {
283                 if (unique && inner.contains(element)) {
284                     throw new RuntimeStorageException(createValueAlreadyContainedExc(key, element));
285                 }
286                 inner.add(index, element);
287                 transLog.logAdd(key, element, index);
288             }
289         }
290         
291         public Object JavaDoc remove(int index) {
292             synchronized (MultivaluedIndexImpl.this) {
293                 Object JavaDoc orig;
294                 if ((orig = inner.remove(index)) != null) {
295                     transLog.logRemove(key, orig, index);
296                     return orig;
297                 } else {
298                     return null;
299                 }
300             }
301         }
302     }
303
304     private class MOWrapper extends AbstractList {
305         private final List inner;
306         private final SinglevaluedIndex pi;
307         private final Object JavaDoc key;
308         
309         public MOWrapper(List inner, SinglevaluedIndex pi, Object JavaDoc key) {
310             this.inner = inner;
311             this.pi = pi;
312             this.key = key;
313         }
314         
315         public Object JavaDoc get(int param) {
316             try {
317                 return pi.get(inner.get(param));
318             } catch (StorageException e) {
319                 throw (RuntimeException JavaDoc) Logger.getDefault().annotate(new RuntimeException JavaDoc(), e);
320             }
321         }
322         
323         public int size() {
324             synchronized (MultivaluedIndexImpl.this) {
325                 return inner.size();
326             }
327         }
328         
329         public Object JavaDoc set(int index, Object JavaDoc element) {
330             if (element instanceof MOFID) {
331                 if (unique && !isUniqueValue(inner, element, index)) {
332                     throw new RuntimeStorageException(createValueAlreadyContainedExc(key, element));
333                 }
334                 return inner.set(index, element);
335             } else {
336                 throw new IllegalArgumentException JavaDoc();
337             }
338         }
339         
340         public void add(int index, Object JavaDoc element) {
341             if (element instanceof MOFID) {
342                 if (unique && inner.contains(element)) {
343                     throw new RuntimeStorageException(createValueAlreadyContainedExc(key, element));
344                 }
345                 inner.add(index, element);
346             } else {
347                 throw new IllegalArgumentException JavaDoc();
348             }
349         }
350         
351         public Object JavaDoc remove(int index) {
352             return inner.remove(index);
353         }
354     }
355 }
356
Popular Tags