KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ozoneDB > collections > AbstractOzoneMap


1 /*
2  * AbstractOzoneMap.java
3  * $Id: AbstractOzoneMap.java,v 1.6.2.1 2004/01/11 20:42:22 per_nyfelt Exp $
4  * This file is based on AbstractMap.java from GNU Classpath. Quote:
5
6 AbstractMap.java -- Abstract implementation of most of Map
7 Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
8
9 This file is part of GNU Classpath.
10
11 GNU Classpath is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15
16 GNU Classpath is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with GNU Classpath; see the file COPYING. If not, write to the
23 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
24 02111-1307 USA.
25
26 Linking this library statically or dynamically with other modules is
27 making a combined work based on this library. Thus, the terms and
28 conditions of the GNU General Public License cover the whole
29 combination.
30
31 As a special exception, the copyright holders of this library give you
32 permission to link this library with independent modules to produce an
33 executable, regardless of the license terms of these independent
34 modules, and to copy and distribute the resulting executable under
35 terms of your choice, provided that you also meet, for each linked
36 independent module, the terms and conditions of the license of that
37 module. An independent module is a module which is not derived from
38 or based on this library. If you modify this library, you may extend
39 this exception to your version of the library, but you are not
40 obligated to do so. If you do not wish to do so, delete this
41 exception statement from your version.
42
43  * end quote.
44  *
45  * This file is licenced under the same conditions as its original (GPL +
46  * "special exception").
47  */

48
49 package org.ozoneDB.collections;
50
51 import java.util.Collection JavaDoc;
52 import java.util.Iterator JavaDoc;
53 import java.util.Map JavaDoc;
54 import java.util.Set JavaDoc;
55 import org.ozoneDB.OzoneObject;
56
57 /**
58  * An abstract implementation of Map to make it easier to create your own
59  * implementations. In order to create an unmodifiable Map, subclass
60  * AbstractMap and implement the <code>entrySet</code> (usually via an
61  * AbstractSet). To make it modifiable, also implement <code>put</code>,
62  * and have <code>entrySet().iterator()</code> support <code>remove</code>.
63  * <p>
64  *
65  * It is recommended that classes which extend this support at least the
66  * no-argument constructor, and a constructor which accepts another Map.
67  * Further methods in this class may be overridden if you have a more
68  * efficient implementation.
69  *
70  * @author Original author unknown
71  * @author Bryce McKinlay
72  * @author Eric Blake <ebb9@email.byu.edu>
73  * @author <a HREF="mailto:ozoneATmekenkampD0Tcom">Leo Mekenkamp (mind the anti-sp@m)</a> (adaptation for ozone)
74  * @see java.util.AbstractMap
75  */

76 public abstract class AbstractOzoneMap extends OzoneObject implements OzoneMap {
77
78     private static final long serialVersionUID = 1L;
79
80     /** An "enum" of iterator types. */
81     // Package visible for use by subclasses.
82
/** the keys type */
83     static final int KEYS = 0;
84     /** the values type */
85     static final int VALUES = 1;
86     /** the entries type */
87     static final int ENTRIES = 2;
88
89     /**
90      * property for {@link #keySet()}.
91      */

92     protected Set JavaDoc keys;
93
94     /**
95      * property for {@link #values()}.
96      */

97     protected Collection JavaDoc values;
98
99     /**
100      * The main constructor, for use by subclasses.
101      */

102     protected AbstractOzoneMap() {
103     }
104
105     /**
106      * Remove all entries from this Map (optional operation). This default
107      * implementation calls entrySet().clear(). NOTE: If the entry set does
108      * not permit clearing, then this will fail, too. Subclasses often
109      * override this for efficiency. Your implementation of entrySet() should
110      * not call <code>AbstractMap.clear</code> unless you want an infinite loop.
111      *
112      * @throws UnsupportedOperationException if <code>entrySet().clear()</code>
113      * does not support clearing.
114      * @see Set#clear()
115      */

116     public void clear() {
117         entrySet().clear();
118     }
119
120     /**
121      * Create a shallow copy of this Map, no keys or values are copied. The
122      * default implementation simply calls <code>super.clone()</code>.
123      *
124      * @return the shallow clone
125      * @throws CloneNotSupportedException if a subclass is not Cloneable
126      * @see Cloneable
127      * @see Object#clone()
128      */

129     protected Object JavaDoc clone() throws CloneNotSupportedException JavaDoc {
130 // AbstractMap copy = (AbstractMap) super.clone();
131
AbstractOzoneMap copy = (AbstractOzoneMap) super.clone();
132         // Clear out the caches; they are stale.
133
copy.keys = null;
134         copy.values = null;
135         return copy;
136     }
137
138     /**
139      * Returns true if this contains a mapping for the given key. This
140      * implementation does a linear search, O(n), over the
141      * <code>entrySet()</code>, returning <code>true</code> if a match
142      * is found, <code>false</code> if the iteration ends. Many subclasses
143      * can implement this more efficiently.
144      *
145      * @param key the key to search for
146      * @return true if the map contains the key
147      * @throws NullPointerException if key is <code>null</code> but the map
148      * does not permit null keys
149      * @see #containsValue(Object)
150      */

151     public boolean containsKey(Object JavaDoc key) {
152         Iterator JavaDoc entries = ((OzoneSet) entrySet())._org_ozoneDB_internalIterator();
153         int pos = size();
154         while (--pos >= 0)
155             if (equals(key, ((Map.Entry JavaDoc) entries.next()).getKey()))
156                 return true;
157         return false;
158     }
159
160     /**
161      * Returns true if this contains at least one mapping with the given value.
162      * This implementation does a linear search, O(n), over the
163      * <code>entrySet()</code>, returning <code>true</code> if a match
164      * is found, <code>false</code> if the iteration ends. A match is
165      * defined as <code>(value == null ? v == null : value.equals(v))</code>
166      * Subclasses are unlikely to implement this more efficiently.
167      *
168      * @param value the value to search for
169      * @return true if the map contains the value
170      * @see #containsKey(Object)
171      */

172     public boolean containsValue(Object JavaDoc value) {
173         Iterator JavaDoc entries = ((OzoneSet) entrySet())._org_ozoneDB_internalIterator();
174         int pos = size();
175         while (--pos >= 0)
176             if (equals(value, ((Map.Entry JavaDoc) entries.next()).getValue()))
177                 return true;
178         return false;
179     }
180
181     /**
182      * Returns a set view of the mappings in this Map. Each element in the
183      * set must be an implementation of Map.Entry. The set is backed by
184      * the map, so that changes in one show up in the other. Modifications
185      * made while an iterator is in progress cause undefined behavior. If
186      * the set supports removal, these methods must be valid:
187      * <code>Iterator.remove</code>, <code>Set.remove</code>,
188      * <code>removeAll</code>, <code>retainAll</code>, and <code>clear</code>.
189      * Element addition is not supported via this set.
190      *
191      * @return the entry set
192      * @see java.util.Map.Entry
193      */

194     public abstract Set JavaDoc entrySet();
195
196     /**
197      * Compares the specified object with this map for equality. Returns
198      * <code>true</code> if the other object is a Map with the same mappings,
199      * that is,<br>
200      * <code>o instanceof Map && entrySet().equals(((Map) o).entrySet();</code>
201      *
202      * @param o the object to be compared
203      * @return true if the object equals this map
204      * @see Set#equals(Object)
205      */

206     public boolean equals(Object JavaDoc o) {
207         return super.equals(o) || (o instanceof Map JavaDoc && entrySet().equals(((Map JavaDoc) o).entrySet()));
208     }
209
210     /**
211      * Returns the value mapped by the given key. Returns <code>null</code> if
212      * there is no mapping. However, in Maps that accept null values, you
213      * must rely on <code>containsKey</code> to determine if a mapping exists.
214      * This iteration takes linear time, searching entrySet().iterator() of
215      * the key. Many implementations override this method.
216      *
217      * @param key the key to look up
218      * @return the value associated with the key, or null if key not in map
219      * @throws NullPointerException if this map does not accept null keys
220      * @see #containsKey(Object)
221      */

222     public Object JavaDoc get(Object JavaDoc key) {
223         Iterator JavaDoc entries = ((OzoneSet) entrySet())._org_ozoneDB_internalIterator();
224         int pos = size();
225         while (--pos >= 0) {
226             Map.Entry JavaDoc entry = (Map.Entry JavaDoc) entries.next();
227             if (equals(key, entry.getKey()))
228                 return entry.getValue();
229         }
230         return null;
231     }
232
233     /**
234      * Returns the hash code for this map. As defined in Map, this is the sum
235      * of all hashcodes for each Map.Entry object in entrySet, or basically
236      * entrySet().hashCode().
237      *
238      * @return the hash code
239      * @see java.util.Map.Entry#hashCode()
240      * @see Set#hashCode()
241      */

242     public int hashCode() {
243         return entrySet().hashCode();
244     }
245
246     /**
247      * Returns true if the map contains no mappings. This is implemented by
248      * <code>size() == 0</code>.
249      *
250      * @return true if the map is empty
251      * @see #size()
252      */

253     public boolean isEmpty() {
254         return size() == 0;
255     }
256
257     /**
258      * Returns a set view of this map's keys. The set is backed by the map,
259      * so changes in one show up in the other. Modifications while an iteration
260      * is in progress produce undefined behavior. The set supports removal
261      * if entrySet() does, but does not support element addition.
262      * <p>
263      *
264      * This implementation creates an AbstractSet, where the iterator wraps
265      * the entrySet iterator, size defers to the Map's size, and contains
266      * defers to the Map's containsKey. The set is created on first use, and
267      * returned on subsequent uses, although since no synchronization occurs,
268      * there is a slight possibility of creating two sets.
269      *
270      * @return a Set view of the keys
271      * @see Set#iterator()
272      * @see #size()
273      * @see #containsKey(Object)
274      * @see #values()
275      */

276     public Set JavaDoc keySet() {
277         if (keys == null) {
278 // ozone
279
// code moved to AbstractOzoneMap_KeySetImpl.java and AbstractOzoneMap_KeySetImpl_IteratorImpl.java
280
// TODO: when FakeFactoryGenerator is finished replace with
281
// keys = AbstractDbSetImplFactory.getDefault.create(self());
282
keys = (Set JavaDoc) database().createObject(_AbstractOzoneMap_keySet.class,
283                             new Class JavaDoc[] {OzoneMap.class},
284                             new Object JavaDoc[] {self()}
285             );
286         }
287 // ~ozone
288
return keys;
289     }
290
291     /**
292      * Associates the given key to the given value (optional operation). If the
293      * map already contains the key, its value is replaced. This implementation
294      * simply throws an UnsupportedOperationException. Be aware that in a map
295      * that permits <code>null</code> values, a null return does not always
296      * imply that the mapping was created.
297      *
298      * @param key the key to map
299      * @param value the value to be mapped
300      * @return the previous value of the key, or null if there was no mapping
301      * @throws UnsupportedOperationException if the operation is not supported
302      * @throws ClassCastException if the key or value is of the wrong type
303      * @throws IllegalArgumentException if something about this key or value
304      * prevents it from existing in this map
305      * @throws NullPointerException if the map forbids null keys or values
306      * @see #containsKey(Object)
307      */

308     public Object JavaDoc put(Object JavaDoc key, Object JavaDoc value) {
309         throw new UnsupportedOperationException JavaDoc();
310     }
311
312     /**
313      * Copies all entries of the given map to this one (optional operation). If
314      * the map already contains a key, its value is replaced. This implementation
315      * simply iterates over the map's entrySet(), calling <code>put</code>,
316      * so it is not supported if puts are not.
317      *
318      * @param m the mapping to load into this map
319      * @throws UnsupportedOperationException if the operation is not supported
320      * @throws ClassCastException if a key or value is of the wrong type
321      * @throws IllegalArgumentException if something about a key or value
322      * prevents it from existing in this map
323      * @throws NullPointerException if the map forbids null keys or values, or
324      * if <code>m</code> is null.
325      * @see #put(Object, Object)
326      */

327     public void putAll(Map JavaDoc m) {
328         Iterator JavaDoc entries;
329         if (m instanceof OzoneMap) {
330             entries = ((OzoneSet) entrySet())._org_ozoneDB_internalIterator();
331         } else {
332             entries = m.entrySet().iterator();
333         }
334         int pos = m.size();
335         while (--pos >= 0) {
336             Map.Entry JavaDoc entry = (Map.Entry JavaDoc) entries.next();
337             put(entry.getKey(), entry.getValue());
338         }
339     }
340
341     /**
342      * Removes the mapping for this key if present (optional operation). This
343      * implementation iterates over the entrySet searching for a matching
344      * key, at which point it calls the iterator's <code>remove</code> method.
345      * It returns the result of <code>getValue()</code> on the entry, if found,
346      * or null if no entry is found. Note that maps which permit null values
347      * may also return null if the key was removed. If the entrySet does not
348      * support removal, this will also fail. This is O(n), so many
349      * implementations override it for efficiency.
350      *
351      * @param key the key to remove
352      * @return the value the key mapped to, or null if not present
353      * @throws UnsupportedOperationException if deletion is unsupported
354      * @see Iterator#remove()
355      */

356     public Object JavaDoc remove(Object JavaDoc key) {
357         Iterator JavaDoc entries = ((OzoneSet) entrySet())._org_ozoneDB_internalIterator();
358         int pos = size();
359         while (--pos >= 0) {
360             Map.Entry JavaDoc entry = (Map.Entry JavaDoc) entries.next();
361             if (equals(key, entry.getKey())) {
362                 // Must get the value before we remove it from iterator.
363
Object JavaDoc r = entry.getValue();
364                 entries.remove();
365                 return r;
366             }
367         }
368         return null;
369     }
370
371     /**
372      * Returns the number of key-value mappings in the map. If there are more
373      * than Integer.MAX_VALUE mappings, return Integer.MAX_VALUE. This is
374      * implemented as <code>entrySet().size()</code>.
375      *
376      * @return the number of mappings
377      * @see Set#size()
378      */

379     public int size() {
380         return entrySet().size();
381     }
382
383     /**
384      * Returns a String representation of this map. This is a listing of the
385      * map entries (which are specified in Map.Entry as being
386      * <code>getKey() + "=" + getValue()</code>), separated by a comma and
387      * space (", "), and surrounded by braces ('{' and '}'). This implementation
388      * uses a StringBuffer and iterates over the entrySet to build the String.
389      * Note that this can fail with an exception if underlying keys or
390      * values complete abruptly in toString().
391      *
392      * @return a String representation
393      * @see java.util.Map.Entry
394      * @see Object#toString()
395      */

396     public String JavaDoc toString() {
397         Iterator JavaDoc entries = ((OzoneSet) entrySet())._org_ozoneDB_internalIterator();
398         StringBuffer JavaDoc r = new StringBuffer JavaDoc("{");
399         for (int pos = size(); pos > 0; pos--) {
400             Map.Entry JavaDoc entry = (Map.Entry JavaDoc) entries.next();
401             r.append(entry.getKey());
402             r.append('=');
403             r.append(entry.getValue());
404             if (pos > 1)
405                 r.append(", ");
406         }
407         r.append("}");
408         return r.toString();
409     }
410
411     /**
412      * Returns a collection or bag view of this map's values. The collection
413      * is backed by the map, so changes in one show up in the other.
414      * Modifications while an iteration is in progress produce undefined
415      * behavior. The collection supports removal if entrySet() does, but
416      * does not support element addition.
417      * <p>
418      *
419      * This implementation creates an AbstractCollection, where the iterator
420      * wraps the entrySet iterator, size defers to the Map's size, and contains
421      * defers to the Map's containsValue. The collection is created on first
422      * use, and returned on subsequent uses, although since no synchronization
423      * occurs, there is a slight possibility of creating two collections.
424      *
425      * @return a Collection view of the values
426      * @see Collection#iterator()
427      * @see #size()
428      * @see #containsValue(Object)
429      * @see #keySet()
430      */

431     public Collection JavaDoc values() {
432         if (values == null) {
433 // code moved to AbstractOzoneMap_KeySetImpl.java and AbstractOzoneMap_KeySetImpl_IteratorImpl.java
434
// TODO: when FakeFactoryGenerator is finished replace with
435
// keys = AbstractDbSetImplFactory.getDefault.create(self());
436
values = (Collection JavaDoc) database().createObject(
437                     _AbstractOzoneMap_values.class,
438                     new Class JavaDoc[] {OzoneMap.class},
439                     new Object JavaDoc[] {self()}
440             );
441         }
442         return values;
443     }
444
445     /**
446      * Compare two objects according to Collection semantics.
447      *
448      * @param o1 the first object
449      * @param o2 the second object
450      * @return o1 == null ? o2 == null : o2 == null ? false : o1.equals(o2);
451      */

452     // Package visible for use throughout java.util.
453
// It may be inlined since it is final.
454
static final boolean equals(Object JavaDoc o1, Object JavaDoc o2) {
455         return o1 == null ? o2 == null : o2 == null ? false : o1.equals(o2);
456     }
457
458     /**
459      * Hash an object according to Collection semantics.
460      *
461      * @param o the object to hash
462      * @return o1 == null ? 0 : o1.hashCode()
463      */

464     // Package visible for use throughout java.util.
465
// It may be inlined since it is final.
466
static final int hashCode(Object JavaDoc o) {
467         return o == null ? 0 : o.hashCode();
468     }
469
470     public OzoneCollection ozoneValues() {
471         return (OzoneCollection) values();
472     }
473
474     public OzoneSet ozoneKeySet() {
475         return (OzoneSet) keySet();
476     }
477     
478     public OzoneSet ozoneEntrySet() {
479         return (OzoneSet) entrySet();
480     }
481     
482     interface Node extends OzoneMap.Node {
483
484     }
485
486
487     class AbstractNode implements Node {
488
489         private Object JavaDoc key;
490
491         private Object JavaDoc value;
492
493         /**
494          * Basic constructor initializes the fields.
495          * @param newKey the key
496          * @param newValue the value
497          */

498         public AbstractNode(Object JavaDoc newKey, Object JavaDoc newValue) {
499             key = newKey;
500             value = newValue;
501         }
502
503         /**
504          * Compares the specified object with this entry. Returns true only if
505          * the object is a mapping of identical key and value.
506          *
507          * @param o the object to compare
508          *
509          * @return <code>true</code> if it is equal
510          */

511         public final boolean equals(Object JavaDoc o) {
512             boolean result;
513             if (! (o instanceof Map.Entry JavaDoc)) {
514                 result = false;
515             // Optimize for our own entries.
516
} else if (o instanceof AbstractNode) {
517                 AbstractNode e = (AbstractNode) o;
518                 result = (AbstractOzoneMap.equals(key, e.key) && AbstractOzoneMap.equals(value, e.value));
519             } else {
520                 Map.Entry JavaDoc e = (Map.Entry JavaDoc) o;
521                 result = (AbstractOzoneMap.equals(key, e.getKey()) && AbstractOzoneMap.equals(value, e.getValue()));
522             }
523             return result;
524         }
525
526         /**
527          * Get the key corresponding to this entry.
528          *
529          * @return the key
530          */

531         public final Object JavaDoc getKey() {
532             return key;
533         }
534
535         /**
536          * Get the value corresponding to this entry. If you already called
537          * Iterator.remove(), the behavior undefined, but in this case it works.
538          *
539          * @return the value
540          */

541         public final Object JavaDoc getValue() {
542             return value;
543         }
544
545         /**
546          * Returns the hash code of the entry. This is defined as the exclusive-or
547          * of the hashcodes of the key and value (using 0 for null). In other
548          * words, this must be:
549          *
550     <pre>(getKey() == null ? 0 : getKey().hashCode())
551     ^ (getValue() == null ? 0 : getValue().hashCode())</pre>
552          *
553          * @return the hash code
554          */

555         public final int hashCode() {
556             return (AbstractOzoneMap.hashCode(key) ^ AbstractOzoneMap.hashCode(value));
557         }
558
559         /**
560          * Replaces the value with the specified object. This writes through
561          * to the map, unless you have already called Iterator.remove(). It
562          * may be overridden to restrict a null value.
563          *
564          * @param newVal the new value to store
565          * @return the old value
566          * @throws NullPointerException if the map forbids null values
567          */

568         public Object JavaDoc setValue(Object JavaDoc newVal) {
569             Object JavaDoc r = value;
570             value = newVal;
571             return r;
572         }
573
574         /**
575          * This provides a string representation of the entry. It is of the form
576          * "key=value", where string concatenation is used on key and value.
577          *
578          * @return the string representation
579          */

580         public final String JavaDoc toString() {
581             return key + "=" + value;
582         }
583
584         public void setKey(Object JavaDoc key) {
585             this.key = key;
586         }
587
588     }
589
590 }
Popular Tags