78
|
1 /*******************************************************************************
|
|
2 * Copyright (c) 2008 Matthew Hall 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 * Matthew Hall - initial API and implementation (bug 215531)
|
|
10 * Matthew Hall - bug 228125
|
|
11 ******************************************************************************/
|
|
12
|
|
13 module org.eclipse.jface.internal.databinding.viewers.ViewerElementMap;
|
|
14
|
|
15 import java.lang.all;
|
|
16
|
|
17 import java.lang.reflect.Array;
|
|
18 import java.util.Collection;
|
|
19 import java.util.HashMap;
|
|
20 import java.util.Iterator;
|
|
21 import java.util.Map;
|
|
22 import java.util.Set;
|
|
23
|
|
24 import org.eclipse.core.runtime.Assert;
|
|
25 import org.eclipse.jface.util.Util;
|
|
26 import org.eclipse.jface.viewers.IElementComparer;
|
|
27 import org.eclipse.jface.viewers.StructuredViewer;
|
|
28
|
|
29 /**
|
|
30 * A {@link Map} whose keys are elements in a {@link StructuredViewer}. The
|
|
31 * keys in the map are compared using an {@link IElementComparer} instead of
|
|
32 * {@link #equals(Object)}.
|
|
33 * <p>
|
|
34 * This class is <i>not</i> a strict implementation the {@link Map} interface.
|
|
35 * It intentionally violates the {@link Map} contract, which requires the use of
|
|
36 * {@link #equals(Object)} when comparing keys. This class is designed for use
|
|
37 * with {@link StructuredViewer} which uses {@link IElementComparer} for element
|
|
38 * comparisons.
|
|
39 *
|
|
40 * @since 1.2
|
|
41 */
|
|
42 public class ViewerElementMap : Map {
|
|
43 private Map wrappedMap;
|
|
44 private IElementComparer comparer;
|
|
45
|
|
46 /**
|
|
47 * Constructs a ViewerElementMap using the given {@link IElementComparer}.
|
|
48 *
|
|
49 * @param comparer
|
|
50 * the {@link IElementComparer} used for comparing keys.
|
|
51 */
|
|
52 public this(IElementComparer comparer) {
|
|
53 Assert.isNotNull(comparer);
|
|
54 this.wrappedMap = new HashMap();
|
|
55 this.comparer = comparer;
|
|
56 }
|
|
57
|
|
58 /**
|
|
59 * Constructs a ViewerElementMap containing all the entries in the specified
|
|
60 * map.
|
|
61 *
|
|
62 * @param map
|
|
63 * the map whose entries are to be added to this map.
|
|
64 * @param comparer
|
|
65 * the {@link IElementComparer} used for comparing keys.
|
|
66 */
|
|
67 public this(Map map, IElementComparer comparer) {
|
|
68 this(comparer);
|
|
69 Assert.isNotNull(map);
|
|
70 putAll(map);
|
|
71 }
|
|
72
|
|
73 public void clear() {
|
|
74 wrappedMap.clear();
|
|
75 }
|
|
76
|
|
77 public bool containsKey(Object key) {
|
|
78 return wrappedMap.containsKey(new ViewerElementWrapper(key, comparer));
|
|
79 }
|
|
80
|
|
81 public bool containsValue(Object value) {
|
|
82 return wrappedMap.containsValue(value);
|
|
83 }
|
|
84
|
|
85 public Set entrySet() {
|
|
86 final Set wrappedEntrySet = wrappedMap.entrySet();
|
|
87 return new class() Set {
|
|
88 public bool add(Object o) {
|
|
89 throw new UnsupportedOperationException();
|
|
90 }
|
|
91
|
|
92 public bool addAll(Collection c) {
|
|
93 throw new UnsupportedOperationException();
|
|
94 }
|
|
95
|
|
96 public void clear() {
|
|
97 wrappedEntrySet.clear();
|
|
98 }
|
|
99
|
|
100 public bool contains(Object o) {
|
|
101 for (Iterator iterator = iterator(); iterator.hasNext();)
|
|
102 if (iterator.next().equals(o))
|
|
103 return true;
|
|
104 return false;
|
|
105 }
|
|
106
|
|
107 public bool containsAll(Collection c) {
|
|
108 for (Iterator iterator = c.iterator(); iterator.hasNext();)
|
|
109 if (!contains(iterator.next()))
|
|
110 return false;
|
|
111 return true;
|
|
112 }
|
|
113
|
|
114 public bool isEmpty() {
|
|
115 return wrappedEntrySet.isEmpty();
|
|
116 }
|
|
117
|
|
118 public Iterator iterator() {
|
|
119 final Iterator wrappedIterator = wrappedEntrySet.iterator();
|
|
120 return new class() Iterator {
|
|
121 public bool hasNext() {
|
|
122 return wrappedIterator.hasNext();
|
|
123 }
|
|
124
|
|
125 public Object next() {
|
|
126 Map.Entry wrappedEntry = cast(Map.Entry) wrappedIterator
|
|
127 .next();
|
|
128 return new class() Map.Entry {
|
|
129 public Object getKey() {
|
|
130 return (cast(ViewerElementWrapper) wrappedEntry.getKey())
|
|
131 .unwrap();
|
|
132 }
|
|
133
|
|
134 public Object getValue() {
|
|
135 return wrappedEntry.getValue();
|
|
136 }
|
|
137
|
|
138 public Object setValue(Object value) {
|
|
139 return wrappedEntry.setValue(value);
|
|
140 }
|
|
141
|
|
142 public bool equals(Object obj) {
|
|
143 if (obj is this)
|
|
144 return true;
|
|
145 if (obj is null || !(null !is cast(Map.Entry)obj))
|
|
146 return false;
|
|
147 Map.Entry that = cast(Map.Entry) obj;
|
|
148 return comparer.equals(this.getKey(), that
|
|
149 .getKey())
|
|
150 && Util.equals(this.getValue(), that
|
|
151 .getValue());
|
|
152 }
|
|
153
|
|
154 public int hashCode() {
|
|
155 return wrappedEntry.hashCode();
|
|
156 }
|
|
157 };
|
|
158 }
|
|
159
|
|
160 public void remove() {
|
|
161 wrappedIterator.remove();
|
|
162 }
|
|
163 };
|
|
164 }
|
|
165
|
|
166 public bool remove(Object o) {
|
|
167 Map.Entry unwrappedEntry = cast(Map.Entry) o;
|
|
168 final ViewerElementWrapper wrappedKey = new ViewerElementWrapper(
|
|
169 unwrappedEntry.getKey(), comparer);
|
|
170 Map.Entry wrappedEntry = new class() Map.Entry {
|
|
171 public Object getKey() {
|
|
172 return wrappedKey;
|
|
173 }
|
|
174
|
|
175 public Object getValue() {
|
|
176 return unwrappedEntry.getValue();
|
|
177 }
|
|
178
|
|
179 public Object setValue(Object value) {
|
|
180 throw new UnsupportedOperationException();
|
|
181 }
|
|
182
|
|
183 public bool equals(Object obj) {
|
|
184 if (obj is this)
|
|
185 return true;
|
|
186 if (obj is null || !(null !is cast(Map.Entry)obj))
|
|
187 return false;
|
|
188 Map.Entry that = cast(Map.Entry) obj;
|
|
189 return Util.equals(wrappedKey, that.getKey())
|
|
190 && Util
|
|
191 .equals(this.getValue(), that
|
|
192 .getValue());
|
|
193 }
|
|
194
|
|
195 public int hashCode() {
|
|
196 return wrappedKey.hashCode()
|
|
197 ^ (getValue() is null ? 0 : getValue()
|
|
198 .hashCode());
|
|
199 }
|
|
200 };
|
|
201 return wrappedEntrySet.remove(wrappedEntry);
|
|
202 }
|
|
203
|
|
204 public bool removeAll(Collection c) {
|
|
205 bool changed = false;
|
|
206 for (Iterator iterator = c.iterator(); iterator.hasNext();)
|
|
207 changed |= remove(iterator.next());
|
|
208 return changed;
|
|
209 }
|
|
210
|
|
211 public bool retainAll(Collection c) {
|
|
212 bool changed = false;
|
|
213 Object[] toRetain = c.toArray();
|
|
214 outer: for (Iterator iterator = iterator(); iterator.hasNext();) {
|
|
215 Object entry = iterator.next();
|
|
216 for (int i = 0; i < toRetain.length; i++)
|
|
217 if (entry.equals(toRetain[i]))
|
|
218 continue outer;
|
|
219 iterator.remove();
|
|
220 changed = true;
|
|
221 }
|
|
222 return changed;
|
|
223 }
|
|
224
|
|
225 public int size() {
|
|
226 return wrappedEntrySet.size();
|
|
227 }
|
|
228
|
|
229 public Object[] toArray() {
|
|
230 return toArray(new Object[size()]);
|
|
231 }
|
|
232
|
|
233 public Object[] toArray(Object[] a) {
|
|
234 int size = size();
|
|
235 if (a.length < size) {
|
|
236 a = cast(Object[]) Array.newInstance(a.getClass()
|
|
237 .getComponentType(), size);
|
|
238 }
|
|
239 int i = 0;
|
|
240 for (Iterator iterator = iterator(); iterator.hasNext();) {
|
|
241 a[i] = iterator.next();
|
|
242 i++;
|
|
243 }
|
|
244 return a;
|
|
245 }
|
|
246
|
|
247 public bool equals(Object obj) {
|
|
248 if (obj is this)
|
|
249 return true;
|
|
250 if (obj is null || !(null !is cast(Set)obj))
|
|
251 return false;
|
|
252 Set that = cast(Set) obj;
|
|
253 return this.size() is that.size() && containsAll(that);
|
|
254 }
|
|
255
|
|
256 public int hashCode() {
|
|
257 return wrappedEntrySet.hashCode();
|
|
258 }
|
|
259 };
|
|
260 }
|
|
261
|
|
262 public Object get(Object key) {
|
|
263 return wrappedMap.get(new ViewerElementWrapper(key, comparer));
|
|
264 }
|
|
265
|
|
266 public bool isEmpty() {
|
|
267 return wrappedMap.isEmpty();
|
|
268 }
|
|
269
|
|
270 public Set keySet() {
|
|
271 final Set wrappedKeySet = wrappedMap.keySet();
|
|
272 return new class() Set {
|
|
273 public bool add(Object o) {
|
|
274 throw new UnsupportedOperationException();
|
|
275 }
|
|
276
|
|
277 public bool addAll(Collection c) {
|
|
278 throw new UnsupportedOperationException();
|
|
279 }
|
|
280
|
|
281 public void clear() {
|
|
282 wrappedKeySet.clear();
|
|
283 }
|
|
284
|
|
285 public bool contains(Object o) {
|
|
286 return wrappedKeySet.contains(new ViewerElementWrapper(o, comparer));
|
|
287 }
|
|
288
|
|
289 public bool containsAll(Collection c) {
|
|
290 for (Iterator iterator = c.iterator(); iterator.hasNext();)
|
|
291 if (!wrappedKeySet.contains(new ViewerElementWrapper(iterator.next(), comparer)))
|
|
292 return false;
|
|
293 return true;
|
|
294 }
|
|
295
|
|
296 public bool isEmpty() {
|
|
297 return wrappedKeySet.isEmpty();
|
|
298 }
|
|
299
|
|
300 public Iterator iterator() {
|
|
301 final Iterator wrappedIterator = wrappedKeySet.iterator();
|
|
302 return new class() Iterator {
|
|
303 public bool hasNext() {
|
|
304 return wrappedIterator.hasNext();
|
|
305 }
|
|
306
|
|
307 public Object next() {
|
|
308 return (cast(ViewerElementWrapper) wrappedIterator.next()).unwrap();
|
|
309 }
|
|
310
|
|
311 public void remove() {
|
|
312 wrappedIterator.remove();
|
|
313 }
|
|
314 };
|
|
315 }
|
|
316
|
|
317 public bool remove(Object o) {
|
|
318 return wrappedKeySet.remove(new ViewerElementWrapper(o, comparer));
|
|
319 }
|
|
320
|
|
321 public bool removeAll(Collection c) {
|
|
322 bool changed = false;
|
|
323 for (Iterator iterator = c.iterator(); iterator.hasNext();)
|
|
324 changed |= wrappedKeySet
|
|
325 .remove(new ViewerElementWrapper(iterator.next(), comparer));
|
|
326 return changed;
|
|
327 }
|
|
328
|
|
329 public bool retainAll(Collection c) {
|
|
330 bool changed = false;
|
|
331 Object[] toRetain = c.toArray();
|
|
332 outer: for (Iterator iterator = iterator(); iterator.hasNext();) {
|
|
333 Object element = iterator.next();
|
|
334 for (int i = 0; i < toRetain.length; i++)
|
|
335 if (comparer.equals(element, toRetain[i]))
|
|
336 continue outer;
|
|
337 // element not contained in collection, remove.
|
|
338 remove(element);
|
|
339 changed = true;
|
|
340 }
|
|
341 return changed;
|
|
342 }
|
|
343
|
|
344 public int size() {
|
|
345 return wrappedKeySet.size();
|
|
346 }
|
|
347
|
|
348 public Object[] toArray() {
|
|
349 return toArray(new Object[wrappedKeySet.size()]);
|
|
350 }
|
|
351
|
|
352 public Object[] toArray(Object[] a) {
|
|
353 int size = wrappedKeySet.size();
|
|
354 ViewerElementWrapper[] wrappedArray = cast(ViewerElementWrapper[]) wrappedKeySet
|
|
355 .toArray(new ViewerElementWrapper[size]);
|
|
356 Object[] result = a;
|
|
357 if (a.length < size) {
|
|
358 result = cast(Object[]) Array.newInstance(a.getClass()
|
|
359 .getComponentType(), size);
|
|
360 }
|
|
361 for (int i = 0; i < size; i++)
|
|
362 result[i] = wrappedArray[i].unwrap();
|
|
363 return result;
|
|
364 }
|
|
365
|
|
366 public bool equals(Object obj) {
|
|
367 if (obj is this)
|
|
368 return true;
|
|
369 if (obj is null || !(null !is cast(Set)obj))
|
|
370 return false;
|
|
371 Set that = cast(Set) obj;
|
|
372 return this.size() is that.size() && containsAll(that);
|
|
373 }
|
|
374
|
|
375 public int hashCode() {
|
|
376 return wrappedKeySet.hashCode();
|
|
377 }
|
|
378 };
|
|
379 }
|
|
380
|
|
381 public Object put(Object key, Object value) {
|
|
382 return wrappedMap.put(new ViewerElementWrapper(key, comparer), value);
|
|
383 }
|
|
384
|
|
385 public void putAll(Map other) {
|
|
386 for (Iterator iterator = other.entrySet().iterator(); iterator
|
|
387 .hasNext();) {
|
|
388 Map.Entry entry = cast(Map.Entry) iterator.next();
|
|
389 wrappedMap.put(new ViewerElementWrapper(entry.getKey(), comparer), entry.getValue());
|
|
390 }
|
|
391 }
|
|
392
|
|
393 public Object remove(Object key) {
|
|
394 return wrappedMap.remove(new ViewerElementWrapper(key, comparer));
|
|
395 }
|
|
396
|
|
397 public int size() {
|
|
398 return wrappedMap.size();
|
|
399 }
|
|
400
|
|
401 public Collection values() {
|
|
402 return wrappedMap.values();
|
|
403 }
|
|
404
|
|
405 public bool equals(Object obj) {
|
|
406 if (obj is this)
|
|
407 return true;
|
|
408 if (obj is null || !(null !is cast(Map)obj))
|
|
409 return false;
|
|
410 Map that = cast(Map) obj;
|
|
411 return this.entrySet().equals(that.entrySet());
|
|
412 }
|
|
413
|
|
414 public int hashCode() {
|
|
415 return wrappedMap.hashCode();
|
|
416 }
|
|
417
|
|
418 /**
|
|
419 * Returns a Map for mapping viewer elements as keys to values, using the
|
|
420 * given {@link IElementComparer} for key comparisons.
|
|
421 *
|
|
422 * @param comparer
|
|
423 * the element comparer to use in key comparisons. If null, the
|
|
424 * returned map will compare keys according to the standard
|
|
425 * contract for {@link Map} interface contract.
|
|
426 * @return a Map for mapping viewer elements as keys to values, using the
|
|
427 * given {@link IElementComparer} for key comparisons.
|
|
428 */
|
|
429 public static Map withComparer(IElementComparer comparer) {
|
|
430 if (comparer is null)
|
|
431 return new HashMap();
|
|
432 return new ViewerElementMap(comparer);
|
|
433 }
|
|
434 }
|