comparison dwtx/core/internal/jobs/ObjectMap.d @ 122:9d0585bcb7aa

Add core.jobs package
author Frank Benoit <benoit@tionex.de>
date Tue, 12 Aug 2008 02:34:21 +0200
parents
children
comparison
equal deleted inserted replaced
121:c0304616ea23 122:9d0585bcb7aa
1 /*******************************************************************************
2 * Copyright (c) 2000, 2006 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 * Port to the D programming language:
11 * Frank Benoit <benoit@tionex.de>
12 *******************************************************************************/
13 module dwtx.core.internal.jobs.ObjectMap;
14
15 import dwt.dwthelper.utils;
16 import dwtx.dwtxhelper.Collection;
17 import dwtx.core.internal.jobs.StringPool;
18
19 /**
20 * A specialized map implementation that is optimized for a small set of object
21 * keys.
22 *
23 * Implemented as a single array that alternates keys and values.
24 *
25 * Note: This class is copied from dwtx.core.resources
26 */
27 public class ObjectMap : Map {
28 // 8 attribute keys, 8 attribute values
29 protected static const int DEFAULT_SIZE = 16;
30 protected static const int GROW_SIZE = 10;
31 protected int count = 0;
32 protected Object[] elements = null;
33
34 /**
35 * Creates a new object map.
36 *
37 * @param initialCapacity
38 * The initial number of elements that will fit in the map.
39 */
40 public this(int initialCapacity) {
41 if (initialCapacity > 0)
42 elements = new Object[Math.max(initialCapacity * 2, 0)];
43 }
44
45 /**
46 * Creates a new object map of the same size as the given map and populate
47 * it with the key/attribute pairs found in the map.
48 *
49 * @param map
50 * The entries in the given map will be added to the new map.
51 */
52 public this(Map map) {
53 this(map.size());
54 putAll(map);
55 }
56
57 /**
58 * @see Map#clear()
59 */
60 public void clear() {
61 elements = null;
62 count = 0;
63 }
64
65 /**
66 * @see java.lang.Object#clone()
67 */
68 public Object clone() {
69 return new ObjectMap(this);
70 }
71
72 /**
73 * @see Map#containsKey(java.lang.Object)
74 */
75 public bool containsKey(Object key) {
76 if (elements is null || count is 0)
77 return false;
78 for (int i = 0; i < elements.length; i = i + 2)
79 if (elements[i] !is null && elements[i].opEquals(key))
80 return true;
81 return false;
82 }
83 public bool containsKey(String key) {
84 return containsKey(stringcast(key));
85 }
86 /**
87 * @see Map#containsValue(java.lang.Object)
88 */
89 public bool containsValue(Object value) {
90 if (elements is null || count is 0)
91 return false;
92 for (int i = 1; i < elements.length; i = i + 2)
93 if (elements[i] !is null && elements[i].opEquals(value))
94 return true;
95 return false;
96 }
97
98 /**
99 * @see Map#entrySet()
100 *
101 * Note: This implementation does not conform properly to the
102 * specification in the Map interface. The returned collection will not
103 * be bound to this map and will not remain in sync with this map.
104 */
105 public Set entrySet() {
106 return count is 0 ? Collections.EMPTY_SET : toHashMap().entrySet();
107 }
108
109 /**
110 * @see Object#equals(java.lang.Object)
111 */
112 public override int opEquals(Object o) {
113 if (!(cast(Map)o ))
114 return false;
115 Map other = cast(Map) o;
116 //must be same size
117 if (count !is other.size())
118 return false;
119 //keysets must be equal
120 if (!(cast(Object)keySet()).opEquals(cast(Object)other.keySet()))
121 return false;
122 //values for each key must be equal
123 for (int i = 0; i < elements.length; i = i + 2) {
124 if (elements[i] !is null && (!elements[i + 1].opEquals(other.get(elements[i]))))
125 return false;
126 }
127 return true;
128 }
129
130 /**
131 * @see Map#get(java.lang.Object)
132 */
133 public Object get(Object key) {
134 if (elements is null || count is 0)
135 return null;
136 for (int i = 0; i < elements.length; i = i + 2)
137 if (elements[i] !is null && elements[i].opEquals(key))
138 return elements[i + 1];
139 return null;
140 }
141 public Object get(String key) {
142 return get(stringcast(key));
143 }
144
145 /**
146 * The capacity of the map has been exceeded, grow the array by GROW_SIZE to
147 * accomodate more entries.
148 */
149 protected void grow() {
150 Object[] expanded = new Object[elements.length + GROW_SIZE];
151 System.arraycopy(elements, 0, expanded, 0, elements.length);
152 elements = expanded;
153 }
154
155 /**
156 * @see Object#hashCode()
157 */
158 public override hash_t toHash() {
159 int hash = 0;
160 for (int i = 0; i < elements.length; i = i + 2) {
161 if (elements[i] !is null) {
162 hash += elements[i].toHash();
163 }
164 }
165 return hash;
166 }
167
168 /**
169 * @see Map#isEmpty()
170 */
171 public bool isEmpty() {
172 return count is 0;
173 }
174
175 /**
176 * Returns all keys in this table as an array.
177 */
178 public String[] keys() {
179 String[] result = new String[count];
180 int next = 0;
181 for (int i = 0; i < elements.length; i = i + 2)
182 if (elements[i] !is null)
183 result[next++] = stringcast( elements[i] );
184 return result;
185 }
186
187 /**
188 * @see Map#keySet()
189 *
190 * Note: This implementation does not conform properly to the
191 * specification in the Map interface. The returned collection will not
192 * be bound to this map and will not remain in sync with this map.
193 */
194 public Set keySet() {
195 Set result = new HashSet(size());
196 for (int i = 0; i < elements.length; i = i + 2) {
197 if (elements[i] !is null) {
198 result.add(elements[i]);
199 }
200 }
201 return result;
202 }
203
204 /**
205 * @see Map#put(java.lang.Object, java.lang.Object)
206 */
207 public Object put(Object key, Object value) {
208 if (key is null)
209 throw new NullPointerException();
210 if (value is null)
211 return remove(key);
212
213 // handle the case where we don't have any attributes yet
214 if (elements is null)
215 elements = new Object[DEFAULT_SIZE];
216 if (count is 0) {
217 elements[0] = key;
218 elements[1] = value;
219 count++;
220 return null;
221 }
222
223 int emptyIndex = -1;
224 // replace existing value if it exists
225 for (int i = 0; i < elements.length; i += 2) {
226 if (elements[i] !is null) {
227 if (elements[i].opEquals(key)) {
228 Object oldValue = elements[i + 1];
229 elements[i + 1] = value;
230 return oldValue;
231 }
232 } else if (emptyIndex is -1) {
233 // keep track of the first empty index
234 emptyIndex = i;
235 }
236 }
237 // this will put the emptyIndex greater than the size but
238 // that's ok because we will grow first.
239 if (emptyIndex is -1)
240 emptyIndex = count * 2;
241
242 // otherwise add it to the list of elements.
243 // grow if necessary
244 if (elements.length <= (count * 2))
245 grow();
246 elements[emptyIndex] = key;
247 elements[emptyIndex + 1] = value;
248 count++;
249 return null;
250 }
251 public Object put(String key, Object value) {
252 return put( stringcast(key), value );
253 }
254 public Object put(Object key, String value) {
255 return put( key, stringcast(value) );
256 }
257 public Object put(String key, String value) {
258 return put( stringcast(key), stringcast(value) );
259 }
260
261 /**
262 * @see Map#putAll(java.util.Map)
263 */
264 public void putAll(Map map) {
265 for (Iterator i = map.keySet().iterator(); i.hasNext();) {
266 Object key = i.next();
267 Object value = map.get(key);
268 put(key, value);
269 }
270 }
271
272 /**
273 * @see Map#remove(java.lang.Object)
274 */
275 public Object remove(Object key) {
276 if (elements is null || count is 0)
277 return null;
278 for (int i = 0; i < elements.length; i = i + 2) {
279 if (elements[i] !is null && elements[i].opEquals(key)) {
280 elements[i] = null;
281 Object result = elements[i + 1];
282 elements[i + 1] = null;
283 count--;
284 return result;
285 }
286 }
287 return null;
288 }
289 public Object remove(String key) {
290 return remove( stringcast(key));
291 }
292
293 /* (non-Javadoc
294 * Method declared on IStringPoolParticipant
295 */
296 public void shareStrings(StringPool set) {
297 //copy elements for thread safety
298 Object[] array = elements;
299 if (array is null)
300 return;
301 for (int i = 0; i < array.length; i++) {
302 Object o = array[i];
303 if (cast(ArrayWrapperString)o )
304 array[i] = stringcast(set.add(stringcast( o)));
305 }
306 }
307
308 /**
309 * @see Map#size()
310 */
311 public int size() {
312 return count;
313 }
314
315 /**
316 * Creates a new hash map with the same contents as this map.
317 */
318 private HashMap toHashMap() {
319 HashMap result = new HashMap(size());
320 for (int i = 0; i < elements.length; i = i + 2) {
321 if (elements[i] !is null) {
322 result.put(elements[i], elements[i + 1]);
323 }
324 }
325 return result;
326 }
327
328 /**
329 * @see Map#values()
330 *
331 * Note: This implementation does not conform properly to the
332 * specification in the Map interface. The returned collection will not
333 * be bound to this map and will not remain in sync with this map.
334 */
335 public Collection values() {
336 Set result = new HashSet(size());
337 for (int i = 1; i < elements.length; i = i + 2) {
338 if (elements[i] !is null) {
339 result.add(elements[i]);
340 }
341 }
342 return result;
343 }
344
345 public int opApply (int delegate(ref Object value) dg){
346 implMissing(__FILE__, __LINE__ );
347 return 0;
348 }
349 public int opApply (int delegate(ref Object key, ref Object value) dg){
350 implMissing(__FILE__, __LINE__ );
351 return 0;
352 }
353
354 }