KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jruby > util > GenericMap


1 /***** BEGIN LICENSE BLOCK *****
2  * Version: CPL 1.0/GPL 2.0/LGPL 2.1
3  *
4  * The contents of this file are subject to the Common Public
5  * License Version 1.0 (the "License"); you may not use this file
6  * except in compliance with the License. You may obtain a copy of
7  * the License at http://www.eclipse.org/legal/cpl-v10.html
8  *
9  * Software distributed under the License is distributed on an "AS
10  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
11  * implied. See the License for the specific language governing
12  * rights and limitations under the License.
13  *
14  * Copyright (C) 2006 Kresten Krab Thorup <krab@gnu.org>
15  *
16  * Alternatively, the contents of this file may be used under the terms of
17  * either of the GNU General Public License Version 2 or later (the "GPL"),
18  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
19  * in which case the provisions of the GPL or the LGPL are applicable instead
20  * of those above. If you wish to allow use of your version of this file only
21  * under the terms of either the GPL or the LGPL, and not to allow others to
22  * use your version of this file under the terms of the CPL, indicate your
23  * decision by deleting the provisions above and replace them with the notice
24  * and other provisions required by the GPL or the LGPL. If you do not delete
25  * the provisions above, a recipient may use your version of this file under
26  * the terms of any one of the CPL, the GPL or the LGPL.
27  ***** END LICENSE BLOCK *****/

28
29 package org.jruby.util;
30
31 import java.util.AbstractCollection JavaDoc;
32 import java.util.AbstractSet JavaDoc;
33 import java.util.Collection JavaDoc;
34 import java.util.Iterator JavaDoc;
35 import java.util.Map JavaDoc;
36 import java.util.Set JavaDoc;
37
38 /**
39  * A <code>GenericMap</code> is simply an abstract <code>java.util.Map</code>
40  * implementation for which subclasses really only need to implement
41  * the method entryIterator.
42  *
43  * @author Kresten Krab Thorup (krab@trifork.com)
44  */

45
46 abstract class GenericMap implements Map JavaDoc {
47     protected int size;
48
49     public int size() {
50         return size;
51     }
52
53     public boolean isEmpty() {
54         return size() == 0;
55     }
56
57     protected int keyHash(Object JavaDoc key) {
58         if (key == null)
59             return 0;
60         else
61             return key.hashCode();
62     }
63
64     protected boolean keyEquals(Object JavaDoc containedKey, Object JavaDoc givenKey) {
65         if (containedKey == null)
66             return givenKey == null;
67         else
68             return containedKey.equals(givenKey);
69     }
70
71     protected int valueHash(Object JavaDoc value) {
72         if (value == null)
73             return 0;
74         else
75             return value.hashCode();
76     }
77
78     protected boolean valueEquals(Object JavaDoc value1, Object JavaDoc value2) {
79         if (value1 == null)
80             return value2 == null;
81         else
82             return value1.equals(value2);
83     }
84
85     abstract class Entry implements Map.Entry JavaDoc {
86         public int hashCode() {
87             return keyHash(getKey()) ^ valueHash(getValue());
88         }
89
90         public boolean equals(Object JavaDoc other) {
91             if (other instanceof Map.Entry JavaDoc) {
92                 Map.Entry JavaDoc ent = (Map.Entry JavaDoc) other;
93                 return keyEquals(getKey(), ent.getKey())
94                         && valueEquals(getValue(), ent.getValue());
95             } else {
96                 return false;
97             }
98         }
99
100     }
101
102     public void putAll(Map JavaDoc other) {
103         if (other == this)
104             return;
105
106         Iterator JavaDoc it = other.entrySet().iterator();
107         while (it.hasNext()) {
108             Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
109             put(entry.getKey(), entry.getValue());
110         }
111     }
112
113     protected abstract Iterator JavaDoc entryIterator();
114
115     protected Iterator JavaDoc keyIterator() {
116         return new KeyIterator();
117     }
118
119     protected Iterator JavaDoc valueIterator() {
120         return new ValueIterator();
121     }
122
123     abstract class KeyOrValueIterator implements Iterator JavaDoc {
124         Iterator JavaDoc iter = entryIterator();
125
126         public boolean hasNext() {
127             return iter.hasNext();
128         }
129
130         protected Map.Entry JavaDoc nextEntry() {
131             return (Map.Entry JavaDoc) iter.next();
132         }
133
134         public void remove() {
135             throw new UnsupportedOperationException JavaDoc();
136         }
137
138     }
139
140     class KeyIterator extends KeyOrValueIterator {
141         public Object JavaDoc next() {
142             return nextEntry().getKey();
143         }
144     }
145
146     class ValueIterator extends KeyOrValueIterator {
147         public Object JavaDoc next() {
148             return nextEntry().getValue();
149         }
150     }
151
152     /**
153      * I don't quite understand why we need to replace this method from
154      * AbstractCollection, but it has been observed that toArray returns the
155      * *reverse* order of elements. --Kresten
156      */

157
158     private static Object JavaDoc[] toArray(Object JavaDoc[] arr, int size, Iterator JavaDoc it) {
159         Object JavaDoc[] out;
160
161         if (arr != null && arr.length >= size) {
162             out = arr;
163         } else if (arr == null) {
164             out = new Object JavaDoc[size];
165         } else {
166             out = (Object JavaDoc[]) java.lang.reflect.Array.newInstance(arr.getClass()
167                     .getComponentType(), size);
168         }
169
170         for (int i = 0; i < size; i++) {
171             out[i] = it.next();
172         }
173
174         if (out.length > size)
175             out[size] = null;
176
177         return out;
178     }
179
180     public Collection JavaDoc values() {
181         return new AbstractCollection JavaDoc() {
182             public Iterator JavaDoc iterator() {
183                 return valueIterator();
184             }
185
186             public int size() {
187                 return GenericMap.this.size();
188             }
189
190             public Object JavaDoc[] toArray(Object JavaDoc[] arr) {
191                 return GenericMap.toArray(arr, size(), iterator());
192             }
193         };
194     }
195
196     public Set JavaDoc keySet() {
197         return new AbstractSet JavaDoc() {
198             public Iterator JavaDoc iterator() {
199                 return keyIterator();
200             }
201
202             public int size() {
203                 return GenericMap.this.size();
204             }
205
206             public Object JavaDoc[] toArray(Object JavaDoc[] arr) {
207                 return GenericMap.toArray(arr, size(), iterator());
208             }
209         };
210     }
211
212     public int hashCode() {
213         int code = 0;
214         Iterator JavaDoc it = entryIterator();
215         while (it.hasNext()) {
216             code += it.next().hashCode();
217         }
218         return code;
219     }
220
221     public boolean equals(Object JavaDoc other) {
222         if (other instanceof Map JavaDoc) {
223             Map JavaDoc map = (Map JavaDoc) other;
224
225             if (map.size() != size())
226                 return false;
227
228             Iterator JavaDoc it = entryIterator();
229             while (it.hasNext()) {
230                 Entry ent = (Entry) it.next();
231                 Object JavaDoc key = ent.getKey();
232                 Object JavaDoc val = ent.getValue();
233
234                 if (map.containsKey(key)) {
235                     Object JavaDoc otherVal = map.get(key);
236                     if (!valueEquals(val, otherVal))
237                         return false;
238                 }
239             }
240             return true;
241         }
242         return false;
243     }
244
245     public Set JavaDoc entrySet() {
246         return new AbstractSet JavaDoc() {
247             public Iterator JavaDoc iterator() {
248                 return entryIterator();
249             }
250
251             public int size() {
252                 return size;
253             }
254
255             public Object JavaDoc[] toArray(Object JavaDoc[] arr) {
256                 return GenericMap.toArray(arr, size(), iterator());
257             }
258         };
259     }
260
261     /** return the element with the given key */
262     public boolean containsValue(Object JavaDoc value) {
263         Iterator JavaDoc it = valueIterator();
264         while (it.hasNext()) {
265             if (valueEquals(value, it.next()))
266                 return true;
267         }
268         return false;
269     }
270
271     public boolean containsKey(Object JavaDoc key) {
272         return get(key) != null;
273     }
274 }
275
Popular Tags