]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_8_1_1/main/tests/core/src/com/ibm/icu/dev/test/util/Relation.java
Added flags.
[Dictionary.git] / jars / icu4j-4_8_1_1 / main / tests / core / src / com / ibm / icu / dev / test / util / Relation.java
1 /*
2  **********************************************************************
3  * Copyright (c) 2002-2011, International Business Machines
4  * Corporation and others.  All Rights Reserved.
5  **********************************************************************
6  * Author: Mark Davis
7  **********************************************************************
8  */
9 package com.ibm.icu.dev.test.util;
10
11 import java.lang.reflect.Constructor;
12 import java.util.Arrays;
13 import java.util.Collection;
14 import java.util.Collections;
15 import java.util.Comparator;
16 import java.util.HashMap;
17 import java.util.LinkedHashSet;
18 import java.util.Map;
19 import java.util.Map.Entry;
20 import java.util.Set;
21
22 import com.ibm.icu.util.Freezable;
23
24 /**
25  * A Relation is a set of mappings from keys to values.
26  * Unlike Map, there is not guaranteed to be a single value per key.
27  * The Map-like APIs return collections for values.
28  * @author medavis
29
30  */
31 public class Relation<K, V> implements Freezable { // TODO: add , Map<K, Collection<V>>, but requires API changes
32     private Map<K, Set<V>> data;
33
34     Constructor<Set<V>> setCreator;
35     Object[] setComparatorParam;
36
37     public static <K,V> Relation<K, V> of(Map<K, Set<V>> map, Class<?> setCreator) {
38         return new Relation(map, setCreator);
39     }
40
41     public static <K,V> Relation<K, V> of(Map<K, Set<V>> map, Class setCreator, Comparator<V> setComparator) {
42         return new Relation(map, setCreator, setComparator);
43     }
44
45     public Relation(Map<K, Set<V>> map, Class<Set<V>> setCreator) {
46         this(map, setCreator, null);
47     }
48
49     public Relation(Map<K, Set<V>> map, Class<Set<V>> setCreator, Comparator<V> setComparator) {
50         try {
51             setComparatorParam = setComparator == null ? null : new Object[]{setComparator};
52             if (setComparator == null) {
53                 this.setCreator = setCreator.getConstructor();
54                 this.setCreator.newInstance(setComparatorParam); // check to make sure compiles
55             } else {
56                 this.setCreator = setCreator.getConstructor(Comparator.class);
57                 this.setCreator.newInstance(setComparatorParam); // check to make sure compiles        
58             }
59             data = map == null ? new HashMap() : map;     
60         } catch (Exception e) {
61             throw (RuntimeException) new IllegalArgumentException("Can't create new set").initCause(e);
62         }
63     }
64
65     public void clear() {
66         data.clear();
67     }
68
69     public boolean containsKey(Object key) {
70         return data.containsKey(key);
71     }
72
73     public boolean containsValue(Object value) {
74         for (Set<V> values : data.values()) {
75             if (values.contains(value)) {
76                 return true;
77             }
78         }
79         return false;
80     }
81
82     public final Set<Entry<K, V>> entrySet() {
83         return keyValueSet();
84     }
85     
86     public Set<Entry<K, Set<V>>> keyValuesSet() {
87         return data.entrySet();
88     }
89     
90     public Set<Entry<K, V>> keyValueSet() {
91         Set<Entry<K, V>> result = new LinkedHashSet();
92         for (K key : data.keySet()) {
93             for (V value : data.get(key)) {
94                 result.add(new SimpleEntry(key, value));
95             }
96         }
97         return result;
98     }
99
100     public boolean equals(Object o) {
101         if (o == null)
102             return false;
103         if (o.getClass() != this.getClass())
104             return false;
105         return data.equals(((Relation) o).data);
106     }
107
108     //  public V get(Object key) {
109     //      Set<V> set = data.get(key);
110     //      if (set == null || set.size() == 0)
111     //        return null;
112     //      return set.iterator().next();
113     //  }
114
115     public Set<V> getAll(Object key) {
116         return data.get(key);
117     }
118
119     public Set<V> get(Object key) {
120         return data.get(key);
121     }
122
123     public int hashCode() {
124         return data.hashCode();
125     }
126
127     public boolean isEmpty() {
128         return data.isEmpty();
129     }
130
131     public Set<K> keySet() {
132         return data.keySet();
133     }
134
135     public V put(K key, V value) {
136         Set<V> set = data.get(key);
137         if (set == null) {
138             data.put(key, set = newSet());
139         }
140         set.add(value);
141         return value;
142     }
143
144     public V putAll(K key, Collection<? extends V> values) {
145         Set<V> set = data.get(key);
146         if (set == null) {
147             data.put(key, set = newSet());
148         }
149         set.addAll(values);
150         return values.size() == 0 ? null : values.iterator().next();
151     }
152
153     public V putAll(Collection<K> keys, V value) {
154         V result = null;
155         for (K key : keys) {
156             result = put(key, value);
157         }
158         return result;
159     }
160
161     private Set<V> newSet() {
162         try {
163             return (Set<V>) setCreator.newInstance(setComparatorParam);
164         } catch (Exception e) {
165             throw (RuntimeException) new IllegalArgumentException("Can't create new set").initCause(e);
166         }
167     }
168
169     public void putAll(Map<? extends K, ? extends V> t) {
170         for (K key : t.keySet()) {
171             put(key, t.get(key));
172         }
173     }
174
175     public void putAll(Relation<? extends K, ? extends V> t) {
176         for (K key : t.keySet()) {
177             for (V value : t.getAll(key)) {
178                 put(key, value);
179             }
180         }
181     }
182
183     public Set<V> removeAll(K key) {
184         return data.remove(key);
185     }
186
187     public boolean remove(K key, V value) {
188         Set<V> set = data.get(key);
189         if (set == null) return false;
190         boolean result = set.remove(value);
191         if (set.size() == 0) {
192             data.remove(key);
193         }
194         return result;
195     }
196
197     public int size() {
198         return data.size();
199     }
200
201     public Set<V> values() {
202         Set<V> result = newSet();
203         for (K key : data.keySet()) {
204             result.addAll(data.get(key));
205         }
206         return result;
207     }
208
209     public String toString() {
210         return data.toString();
211     }
212
213     static class SimpleEntry<K, V> implements Entry<K, V> {
214         K key;
215
216         V value;
217
218         public SimpleEntry(K key, V value) {
219             this.key = key;
220             this.value = value;
221         }
222
223         public SimpleEntry(Entry<K, V> e) {
224             this.key = e.getKey();
225             this.value = e.getValue();
226         }
227
228         public K getKey() {
229             return key;
230         }
231
232         public V getValue() {
233             return value;
234         }
235
236         public V setValue(V value) {
237             V oldValue = this.value;
238             this.value = value;
239             return oldValue;
240         }
241     }
242
243     public Relation<K,V> addAllInverted(Relation<V,K> source) {
244         for (V value : source.data.keySet()) {
245             for (K key : source.data.get(value)) {
246                 put(key, value);
247             }
248         }
249         return this;
250     }
251
252     public Relation<K,V> addAllInverted(Map<V,K> source) {
253         for (V value : source.keySet()) {
254             put(source.get(value), value);
255         }
256         return this;
257     }
258
259     boolean frozen = false;
260
261     public boolean isFrozen() {
262         return frozen;
263     }
264
265     public Object freeze() {
266         if (!frozen) {
267             frozen = true;
268             // does not handle one level down, so we do that on a case-by-case basis
269             for (K key : data.keySet()) {
270                 data.put(key, Collections.unmodifiableSet(data.get(key)));
271             }
272             // now do top level
273             data = Collections.unmodifiableMap(data);
274         }
275         return this;
276     }
277
278     public Object cloneAsThawed() {
279         // TODO do later
280         throw new UnsupportedOperationException();
281     }
282
283     public boolean removeAll(Relation<K, V> toBeRemoved) {
284         boolean result = false;
285         for (K key : toBeRemoved.keySet()) {
286             Set<V> values = toBeRemoved.getAll(key);
287             if (values != null) {
288                 result |= removeAll(key, values);
289             }
290         }
291         return result;
292     }
293
294     public Set<V> removeAll(K... keys) {
295         return data.remove(Arrays.asList(keys));
296     }
297
298     public boolean removeAll(K key, Iterable<V> toBeRemoved) {
299         boolean result = false;
300         for (V value : toBeRemoved) {
301             result |= remove(key, value);
302         }
303         return result;
304     }
305
306     public Set<V> removeAll(Collection<K> toBeRemoved) {
307         Set<V> result = new LinkedHashSet();
308         for (K key : toBeRemoved) {
309             final Set<V> removals = data.remove(key);
310             if (removals != null) {
311                 result.addAll(removals);
312             }
313         }
314         return result;
315     }
316 }