001: /*
002: * Primitive Collections for Java.
003: * Copyright (C) 2002 Søren Bak
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2.1 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public
016: * License along with this library; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018: */
019: package bak.pcj.adapter;
020:
021: import bak.pcj.map.ObjectKeyBooleanMap;
022: import bak.pcj.map.ObjectKeyBooleanMapIterator;
023: import bak.pcj.map.MapDefaults;
024: import bak.pcj.hash.DefaultBooleanHashFunction;
025: import bak.pcj.util.Exceptions;
026:
027: import java.util.Iterator;
028: import java.util.Collection;
029: import java.util.AbstractSet;
030: import java.util.Map;
031: import java.util.Set;
032:
033: /**
034: * This class represents adapters of primitive maps from
035: * object values to <S> values to Java Collections
036: * Framework maps. The adapter is implemented as a wrapper
037: * around a primitive map. Thus,
038: * changes to the underlying map are reflected by this
039: * map and vice versa.
040: *
041: * @see ObjectKeyBooleanMap
042: * @see java.util.Map
043: *
044: * @author Søren Bak
045: * @version 1.1 20-08-2003 23:09
046: * @since 1.1
047: */
048: public class ObjectKeyBooleanMapToMapAdapter implements Map {
049:
050: /** The underlying primitive map. */
051: protected ObjectKeyBooleanMap map;
052:
053: /**
054: * Creates a new adaption of a primitive map of object
055: * keys and boolean values to a Java Collections Framework map.
056: *
057: * @param map
058: * the underlying primitive map.
059: *
060: * @throws NullPointerException
061: * if <tt>map</tt> is <tt>null</tt>.
062: */
063: public ObjectKeyBooleanMapToMapAdapter(ObjectKeyBooleanMap map)
064: throws NullPointerException /* Exception marked to work around bug in Javadoc 1.3 */{
065: if (map == null)
066: Exceptions.nullArgument("map");
067: this .map = map;
068: }
069:
070: /**
071: * Clears this map. The underlying map is cleared.
072: *
073: * @throws UnsupportedOperationException
074: * if the operation is not supported by the
075: * underlying map.
076: */
077: public void clear() {
078: map.clear();
079: }
080:
081: /**
082: * Indicates whether this map contains a mapping from a specified
083: * key. This is so, only if the underlying collection contains
084: * the unwrapped key.
085: *
086: * @param key
087: * the key to test for.
088: *
089: * @return <tt>true</tt> if this map contains a mapping from
090: * the specified key; returns <tt>false</tt>
091: * otherwise.
092: */
093: public boolean containsKey(Object key) {
094: return map.containsKey(key);
095: }
096:
097: /**
098: * Indicates whether this map contains a mapping to a specified
099: * value. For this map to contain an object, the
100: * underlying map must contain its unwrapped value.
101: * <p>Note that this map can never contain <tt>null</tt>
102: * values or values of other classes than {@link Boolean Boolean}.
103: * In those cases, this method will return <tt>false</tt>.
104: *
105: * @param value
106: * the value to test for.
107: *
108: * @return <tt>true</tt> if this map contains at least one
109: * mapping to the specified value; returns
110: * <tt>false</tt> otherwise.
111: */
112: public boolean containsValue(Object value) {
113: if (value == null)
114: return false;
115: return map.containsValue(((Boolean) value).booleanValue());
116: }
117:
118: /**
119: * Returns a set view of the entries of this map. The returned
120: * set is a view, so changes to this map are reflected by the
121: * returned set and vice versa. All elements of the returned
122: * set implements {@link java.util.Map.Entry java.util.Map.Entry}.
123: *
124: * @return a set view of the entries of this map.
125: */
126: public Set entrySet() {
127: return new EntrySet();
128: }
129:
130: /**
131: * Indicates whether this map is equal to some object.
132: *
133: * @param obj
134: * the object with which to compare this map.
135: *
136: * @return <tt>true</tt> if this map is equal to the
137: * specified object; returns <tt>false</tt>
138: * otherwise.
139: */
140: public boolean equals(Object obj) {
141: if (!(obj instanceof Map))
142: return false;
143: Map m = (Map) obj;
144: if (m.size() != map.size())
145: return false;
146: Iterator i = m.entrySet().iterator();
147: while (i.hasNext()) {
148: Map.Entry e = (Map.Entry) i.next();
149: if (e.getValue() == null)
150: return false;
151: if (!get(e.getKey()).equals(e.getValue()))
152: return false;
153: }
154: return true;
155: }
156:
157: /**
158: * Maps a specified key to a value. Returns <tt>null</tt>
159: * if no mapping exists for the specified key.
160: * The returned value will always be of class {@link <JS> <JS>}.
161: *
162: * @param key
163: * the key to map to a value.
164: *
165: * @return the value that the specified key maps to, or
166: * <tt>null</tt>, if no such mapping exists.
167: */
168: public Object get(Object key) {
169: boolean v = map.get(key);
170: if (v == MapDefaults.defaultBoolean())
171: if (!map.containsKey(key))
172: return null;
173: return new Boolean(v);
174: }
175:
176: /**
177: * Returns a hash code value for this map. The hash code
178: * returned is that of the underlying map.
179: *
180: * @return a hash code value for this map.
181: */
182: public int hashCode() {
183: return map.hashCode();
184: }
185:
186: /**
187: * Indicates whether this map is empty.
188: *
189: * @return <tt>true</tt> if this map is empty; returns
190: * <tt>false</tt> otherwise.
191: */
192: public boolean isEmpty() {
193: return map.isEmpty();
194: }
195:
196: /**
197: * Returns a set view of the keys of this map. Removals from the
198: * returned set removes the corresponding entries in this map.
199: * Changes to the map are reflected in the set.
200: *
201: * @return a set view of the keys of this map.
202: */
203: public Set keySet() {
204: return map.keySet();
205: }
206:
207: /**
208: * Adds a mapping from a specified key to a specified value to
209: * this map. If a mapping already exists for the specified key
210: * it is overwritten by the new mapping. The mapping is
211: * added to the underlying map.
212: *
213: * @param key
214: * the key of the mapping to add to this map.
215: *
216: * @param value
217: * the value of the mapping to add to this map.
218: *
219: * @return the old value if a
220: * mapping from the specified key already existed
221: * in this map; returns <tt>null</tt> otherwise.
222: *
223: * @throws UnsupportedOperationException
224: * if the operation is not supported by this map.
225: *
226: * @throws NullPointerException
227: * if <tt>value</tt> is <tt>null</tt>.
228: *
229: * @throws ClassCastException
230: * if <tt>value</tt> is not of class {@link Boolean Boolean}.
231: */
232: public Object put(Object key, Object value)
233: throws NullPointerException, ClassCastException /* Exception marked to work around bug in Javadoc 1.3 */{
234: Object result = get(key);
235: map.put(key, ((Boolean) value).booleanValue());
236: return result;
237: }
238:
239: /**
240: * Adds all mappings from a specified map to this map. Any
241: * existing mappings whose keys collide with a new mapping is
242: * overwritten by the new mapping. The mappings are
243: * added to the underlying map.
244: *
245: * @param map
246: * the map whose mappings to add to this map.
247: *
248: * @throws NullPointerException
249: * if <tt>map</tt> is <tt>null</tt>.
250: *
251: * @throws UnsupportedOperationException
252: * if the operation is not supported by this map.
253: *
254: * @throws NullPointerException
255: * if a value in <tt>map</tt> is <tt>null</tt>.
256: *
257: * @throws ClassCastException
258: * if a value in <tt>value</tt> is not of class {@link Boolean Boolean}.
259: */
260: public void putAll(Map map) throws NullPointerException,
261: ClassCastException /* Exceptions marked to work around bug in Javadoc 1.3 */{
262: Iterator i = map.entrySet().iterator();
263: while (i.hasNext()) {
264: Map.Entry e = (Map.Entry) i.next();
265: put(e.getKey(), e.getValue());
266: }
267: }
268:
269: /**
270: * Removes the mapping from a specified key from this map.
271: * The mapping is removed from the underlying map.
272: *
273: * @param key
274: * the key whose mapping to remove from this map.
275: *
276: * @return the old value if a
277: * mapping from the specified key already existed
278: * in this map; returns <tt>null</tt> otherwise.
279: *
280: * @throws UnsupportedOperationException
281: * if the operation is not supported by the
282: * underlying map.
283: */
284: public Object remove(Object key) {
285: Object result = get(key);
286: map.remove(key);
287: return result;
288: }
289:
290: /**
291: * Returns the size of this map. The size is defined as the
292: * number of mappings from keys to values. The size is that
293: * of the underlying map.
294: *
295: * @return the size of this map.
296: */
297: public int size() {
298: return map.size();
299: }
300:
301: /**
302: * Returns a collection view of the values in this map. The
303: * collection is not modifiable, but changes to the map are
304: * reflected in the collection. All elements
305: * in the returned set is of class {@link Boolean Boolean}.
306: *
307: * @return a collection view of the values in this map.
308: */
309: public Collection values() {
310: return new BooleanCollectionToCollectionAdapter(map.values());
311: }
312:
313: class EntrySet extends AbstractSet {
314:
315: public Iterator iterator() {
316: return new Iterator() {
317: ObjectKeyBooleanMapIterator i = map.entries();
318:
319: public boolean hasNext() {
320: return i.hasNext();
321: }
322:
323: public Object next() {
324: i.next();
325: return new Entry(i.getKey(), i.getValue());
326: }
327:
328: public void remove() {
329: i.remove();
330: }
331: };
332: }
333:
334: public boolean add(Object obj) {
335: Map.Entry e = (Map.Entry) obj;
336: if (contains(e))
337: return false;
338: put(e.getKey(), e.getValue());
339: return true;
340: }
341:
342: public int size() {
343: return map.size();
344: }
345: }
346:
347: class Entry implements Map.Entry {
348: Object key;
349: Boolean value;
350:
351: Entry(Object key, boolean value) {
352: this .key = key;
353: this .value = new Boolean(value);
354: }
355:
356: public Object getKey() {
357: return key;
358: }
359:
360: public Object getValue() {
361: return value;
362: }
363:
364: public Object setValue(Object value) {
365: return put(key, value);
366: }
367:
368: public int hashCode() {
369: return (key == null ? 0 : key.hashCode())
370: ^ DefaultBooleanHashFunction.INSTANCE.hash(value
371: .booleanValue());
372: }
373:
374: public boolean equals(Object obj) {
375: if (!(obj instanceof Map.Entry))
376: return false;
377: Map.Entry e = (Map.Entry) obj;
378: return (key == null ? e.getKey() == null : key.equals(e
379: .getKey()))
380: && value.equals(e.getValue());
381: }
382: }
383:
384: }
|