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