comparison org.eclipse.core.databinding/src/org/eclipse/core/databinding/observable/set/MappedSet.d @ 78:0a55d2d5a946

Added file for databinding
author Frank Benoit <benoit@tionex.de>
date Tue, 14 Apr 2009 11:35:29 +0200
parents
children 383ce7bd736b
comparison
equal deleted inserted replaced
76:f05e6e8b2f2d 78:0a55d2d5a946
1 /*******************************************************************************
2 * Copyright (c) 2006, 2007 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 *******************************************************************************/
11
12 module org.eclipse.core.databinding.observable.set.MappedSet;
13
14 import java.lang.all;
15
16 import java.util.Collections;
17 import java.util.HashMap;
18 import java.util.HashSet;
19 import java.util.Iterator;
20 import java.util.Map;
21 import java.util.Set;
22
23 import org.eclipse.core.databinding.observable.Diffs;
24 import org.eclipse.core.databinding.observable.Realm;
25 import org.eclipse.core.databinding.observable.map.IMapChangeListener;
26 import org.eclipse.core.databinding.observable.map.IObservableMap;
27 import org.eclipse.core.databinding.observable.map.MapChangeEvent;
28 import org.eclipse.core.databinding.observable.map.MapDiff;
29
30 /**
31 *
32 * <p>
33 * This class is thread safe. All state accessing methods must be invoked from
34 * the {@link Realm#isCurrent() current realm}. Methods for adding and removing
35 * listeners may be invoked from any thread.
36 * </p>
37 *
38 * @since 1.0
39 *
40 */
41 public class MappedSet : ObservableSet {
42
43 private final IObservableMap wrappedMap;
44
45 /*
46 * Map from values (range elements) to Integer ref counts
47 */
48 private Map valueCounts = new HashMap();
49
50 private ISetChangeListener domainListener = new class() ISetChangeListener {
51 public void handleSetChange(SetChangeEvent event) {
52 Set additions = new HashSet();
53 for (Iterator it = event.diff.getAdditions().iterator(); it.hasNext();) {
54 Object added = it.next();
55 Object mapValue = wrappedMap.get(added);
56 if (handleAddition(mapValue)) {
57 additions.add(mapValue);
58 }
59 }
60 Set removals = new HashSet();
61 for (Iterator it = event.diff.getRemovals().iterator(); it.hasNext();) {
62 Object removed = it.next();
63 Object mapValue = wrappedMap.get(removed);
64 if (handleRemoval(mapValue)) {
65 removals.add(mapValue);
66 }
67 }
68 fireSetChange(Diffs.createSetDiff(additions, removals));
69 }
70 };
71
72 private IMapChangeListener mapChangeListener = new class() IMapChangeListener {
73 public void handleMapChange(MapChangeEvent event) {
74 MapDiff diff = event.diff;
75 Set additions = new HashSet();
76 Set removals = new HashSet();
77 for (Iterator it = diff.getRemovedKeys().iterator(); it.hasNext();) {
78 Object key = it.next();
79 Object oldValue = diff.getOldValue(key);
80 if (handleRemoval(oldValue)) {
81 removals.add(oldValue);
82 }
83 }
84 for (Iterator it = diff.getChangedKeys().iterator(); it.hasNext();) {
85 Object key = it.next();
86 Object oldValue = diff.getOldValue(key);
87 Object newValue = diff.getNewValue(key);
88 if (handleRemoval(oldValue)) {
89 removals.add(oldValue);
90 }
91 if (handleAddition(newValue)) {
92 additions.add(newValue);
93 }
94 }
95 for (Iterator it = diff.getAddedKeys().iterator(); it.hasNext();) {
96 Object key = it.next();
97 Object newValue = diff.getNewValue(key);
98 if (handleAddition(newValue)) {
99 additions.add(newValue);
100 }
101 }
102 fireSetChange(Diffs.createSetDiff(additions, removals));
103 }
104 };
105
106 private IObservableSet input;
107
108 /**
109 * @param input
110 * @param map
111 */
112 public this(IObservableSet input, IObservableMap map) {
113 super(input.getRealm(), Collections.EMPTY_SET, Object.classinfo);
114 setWrappedSet(valueCounts.keySet());
115 this.wrappedMap = map;
116 this.input = input;
117 for (Iterator it = input.iterator(); it.hasNext();) {
118 Object element = it.next();
119 Object functionValue = wrappedMap.get(element);
120 handleAddition(functionValue);
121 }
122 input.addSetChangeListener(domainListener);
123 map.addMapChangeListener(mapChangeListener);
124 }
125
126 /**
127 * @param mapValue
128 * @return true if the given mapValue was an addition
129 */
130 protected bool handleAddition(Object mapValue) {
131 Integer count = cast(Integer) valueCounts.get(mapValue);
132 if (count is null) {
133 valueCounts.put(mapValue, new Integer(1));
134 return true;
135 }
136 valueCounts.put(mapValue, new Integer(count.intValue() + 1));
137 return false;
138 }
139
140 /**
141 * @param mapValue
142 * @return true if the given mapValue has been removed
143 */
144 protected bool handleRemoval(Object mapValue) {
145 Integer count = cast(Integer) valueCounts.get(mapValue);
146 if (count.intValue() <= 1) {
147 valueCounts.remove(mapValue);
148 return true;
149 }
150 valueCounts.put(mapValue, new Integer(count.intValue() - 1));
151 return false;
152 }
153
154 public synchronized void dispose() {
155 wrappedMap.removeMapChangeListener(mapChangeListener);
156 input.removeSetChangeListener(domainListener);
157 }
158
159 }