]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.databoard/src/org/simantics/databoard/binding/impl/DefaultMapBinding.java
Fixing several binding-related bugs
[simantics/platform.git] / bundles / org.simantics.databoard / src / org / simantics / databoard / binding / impl / DefaultMapBinding.java
1 /*******************************************************************************
2  *  Copyright (c) 2010 Association for Decentralized Information Management in
3  *  Industry THTH ry.
4  *  All rights reserved. This program and the accompanying materials
5  *  are made available under the terms of the Eclipse Public License v1.0
6  *  which accompanies this distribution, and is available at
7  *  http://www.eclipse.org/legal/epl-v10.html
8  *
9  *  Contributors:
10  *      VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.databoard.binding.impl;
13
14 import java.util.IdentityHashMap;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.Map.Entry;
18 import java.util.Set;
19 import java.util.TreeMap;
20
21 import org.simantics.databoard.binding.ArrayBinding;
22 import org.simantics.databoard.binding.Binding;
23 import org.simantics.databoard.binding.MapBinding;
24 import org.simantics.databoard.binding.error.BindingException;
25 import org.simantics.databoard.type.MapType;
26
27 /**
28  * Binds java.util.Map to MapType
29  * 
30  * This Binding type accepts all java.util.Map instances, but creates
31  * java.util.TreeMap instances by default.
32  * 
33  * @author Reino Ruusu <reino.ruusu@vtt.fi>
34  */
35 @SuppressWarnings("rawtypes")
36 public class DefaultMapBinding extends MapBinding {
37
38     public DefaultMapBinding(Binding keyBinding, Binding valueBinding) {
39         super(keyBinding, valueBinding);
40     }
41
42     public DefaultMapBinding(MapType mapType, Binding keyBinding,
43             Binding valueBinding) {
44         super(mapType, keyBinding, valueBinding);
45     }
46
47     public void postConstruction() {
48     }
49
50     @Override
51     public Object create() {
52         return new TreeMap<Object,Object>( keyBinding );
53     }
54
55     @SuppressWarnings("unchecked")
56     @Override
57     public Object create(Object[] keys, Object[] values) {
58         if (keys.length != values.length)
59             throw new IllegalArgumentException("Equal length arrays expected");
60
61         int len = keys.length;
62         Map result = new TreeMap<Object,Object>( keyBinding );
63
64         for (int i = 0; i < len; i++) {
65             Object key = keys[i];
66             Object value = values[i];
67             result.put(key, value);
68         }
69
70         return result;
71     }
72     
73     
74     @SuppressWarnings("unchecked")
75     @Override
76     public Object create(List<Object> keys, List<Object> values) {
77         if (keys.size()!=values.size())
78             throw new IllegalArgumentException("Equal length arrays expected");
79         
80         int len = keys.size();
81         Map result = new TreeMap<Object,Object>( keyBinding );
82         
83         for (int i=0; i<len; i++) {
84             Object key = keys.get(i);
85             Object value = values.get(i);
86             result.put(key, value);
87         }
88         
89         return result;
90     }   
91
92     @Override
93     public Object create(Map<?,?> map) {
94         return map;
95     }
96     
97     @Override
98     public void clear(Object map) {
99         ((Map) map).clear();
100     }
101
102     @Override
103     public boolean containsKey(Object map, Object key) {
104         Map m = ((Map) map);
105         return m.containsKey(key);
106     }
107
108     @Override
109     public boolean containsValue(Object map, Object value) {
110         Map m = ((Map) map);
111         Binding vb = getValueBinding();
112         for (Object v : m.values())
113         {
114             if (vb.equals(v, value)) return true;
115         }
116         return false;
117     }
118
119     @Override
120     public Object get(Object map, Object key) {
121         Map m = ((Map) map);
122         return m.get(key);
123     }
124
125     @SuppressWarnings("unchecked")
126     @Override
127     public Object[] getKeys(Object map) {
128         Map m = ((Map) map);
129         return m.keySet().toArray(new Object[m.size()]);
130     }
131     
132     @SuppressWarnings("unchecked")
133     @Override
134     public void getKeys(Object map, Set<Object> keys) throws BindingException {
135         Map m = ((Map)map);
136         keys.addAll(m.keySet());
137     }   
138     
139     /**
140      * Count the number of entries between two keyes
141      * @param from
142      * @param fromInclusive
143      * @param end 
144      * @param endInclusive
145      * @throws BindingException
146      */
147     @SuppressWarnings("unchecked")
148     @Override
149     public int count(Object src, Object from, boolean fromInclusive, Object end, boolean endInclusive) throws BindingException {
150         // Assert end > from
151         if (keyBinding.compare(from, end)>0) return 0;
152         
153         if (src instanceof TreeMap) {
154             TreeMap m = (TreeMap) src;
155             Map sm = m.subMap(from, fromInclusive, end, endInclusive);
156             return sm.size();
157         }
158         else {
159             int result = 0;
160             Map<Object, Object> m = ((Map<Object, Object>)src);
161             for (Object k : m.keySet()) {
162                 int fk = keyBinding.compare(from, k);
163                 int ek = keyBinding.compare(k, end);
164                 boolean fromMatches = fromInclusive ? fk<=0 : fk<0;
165                 boolean endMatches = endInclusive ? ek<=0 : ek <0;          
166                 if ( fromMatches && endMatches ) result++;
167             }       
168             return result;
169         }
170     }
171     
172     /**
173      * Read a range of entries
174      * 
175      * @param src
176      * @param from
177      * @param fromInclusive
178      * @param end 
179      * @param endInclusive
180      * @param dstKeyArrayBinding
181      * @param dstKeyArray
182      * @param dstValueArrayBinding
183      * @param dstValueArray
184      * @throws BindingException
185      */
186     public int getEntries(Object src, Object from, boolean fromInclusive, Object end, boolean endInclusive, ArrayBinding dstKeyArrayBinding, Object dstKeyArray, ArrayBinding dstValueArrayBinding, Object dstValueArray, int limit) throws BindingException {
187         if (src instanceof TreeMap) {
188             return new TreeMapBinding(keyBinding, valueBinding).getEntries(src, from, fromInclusive, end, endInclusive, dstKeyArrayBinding, dstKeyArray, dstValueArrayBinding, dstValueArray, limit);
189         }
190         else {
191             return new HashMapBinding(keyBinding, valueBinding).getEntries(src, from, fromInclusive, end, endInclusive, dstKeyArrayBinding, dstKeyArray, dstValueArrayBinding, dstValueArray, limit);
192         }
193     }
194     
195
196     @SuppressWarnings("unchecked")
197     @Override
198     public Object[] getValues(Object map) {
199         Map m = ((Map) map);
200         return m.values().toArray(new Object[m.size()]);
201     }
202
203     @Override
204     public <K, V> void put(Object map, K key, V value) {
205         @SuppressWarnings("unchecked")
206         Map<K, V> m = ((Map<K, V>) map);
207         m.put(key, value);
208     }
209
210     @Override
211     public <K, V> void putAll(Object dstMap, Map<K, V> srcMap) {
212         @SuppressWarnings("unchecked")
213         Map<K, V> dst = ((Map<K, V>) dstMap);
214         dst.putAll(srcMap);
215     }
216
217     @SuppressWarnings("unchecked")
218     @Override
219     public void getAll(Object mapFrom, Map to) {
220         Map<?, ?> m = ((Map<?, ?>) mapFrom);
221         to.putAll(m);
222     }
223
224     @SuppressWarnings("unchecked")
225     @Override
226     public void getAll(Object mapFrom, Object[] keys, Object[] values) {
227         Map m = (Map) mapFrom;
228         int i = 0;
229         for (Entry<Object, Object> e : (Set<Entry<Object, Object>>) m.entrySet()) {
230             keys[i] = e.getKey();
231             values[i] = e.getValue();
232             i++;
233         }
234     }
235     
236     @Override
237     public Object remove(Object map, Object key) {
238         Map m = ((Map) map);
239         return m.remove(key);
240     }
241
242     @Override
243     public int size(Object map) {
244         Map m = ((Map) map);
245         return m.size();
246     }
247
248     @Override
249     public boolean isInstance(Object obj) {
250         return obj instanceof Map;
251     }
252
253     @Override
254     public int deepHashValue(Object map, IdentityHashMap<Object, Object> hashedObjects) throws BindingException {
255         int result = 0;
256         Map m = ((Map) map);
257         @SuppressWarnings("unchecked")
258         Set<Entry> s = m.entrySet();
259         for (Entry e : s) {
260             int keyTree = getKeyBinding().deepHashValue(e.getKey(), hashedObjects);
261             int valueTree = getValueBinding().deepHashValue(e.getValue(), hashedObjects);
262             result += (keyTree ^ valueTree);
263         }
264         return result;
265     }
266
267     @Override
268     public Object getCeilingKey(Object map, Object key) {
269         if (map instanceof TreeMap) {
270             return new TreeMapBinding(keyBinding, valueBinding).getCeilingKey(map, key);
271         }
272         else {
273             return new HashMapBinding(keyBinding, valueBinding).getCeilingKey(map, key);
274         }
275     }
276
277     @Override
278     public Object getFirstKey(Object map) {
279         if (map instanceof TreeMap) {
280             return new TreeMapBinding(keyBinding, valueBinding).getFirstKey(map);
281         }
282         else {
283             return new HashMapBinding(keyBinding, valueBinding).getFirstKey(map);
284         }
285     }
286
287     @Override
288     public Object getFloorKey(Object map, Object key) {
289         if (map instanceof TreeMap) {
290             return new TreeMapBinding(keyBinding, valueBinding).getFloorKey(map, key);
291         }
292         else {
293             return new HashMapBinding(keyBinding, valueBinding).getFloorKey(map, key);
294         }
295     }
296
297     @Override
298     public Object getHigherKey(Object map, Object key) {
299         if (map instanceof TreeMap) {
300             return new TreeMapBinding(keyBinding, valueBinding).getHigherKey(map, key);
301         }
302         else {
303             return new HashMapBinding(keyBinding, valueBinding).getHigherKey(map, key);
304         }
305     }
306
307     @Override
308     public Object getLastKey(Object map) {
309         if (map instanceof TreeMap) {
310             return new TreeMapBinding(keyBinding, valueBinding).getLastKey(map);
311         }
312         else {
313             return new HashMapBinding(keyBinding, valueBinding).getLastKey(map);
314         }
315     }
316
317     @Override
318     public Object getLowerKey(Object map, Object key) {
319         if (map instanceof TreeMap) {
320             return new TreeMapBinding(keyBinding, valueBinding).getLowerKey(map, key);
321         }
322         else {
323             return new HashMapBinding(keyBinding, valueBinding).getLowerKey(map, key);
324         }
325     }
326 }