1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.ini4j;
17
18 import org.ini4j.spi.Warnings;
19
20 import java.io.Serializable;
21
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.HashSet;
25 import java.util.LinkedHashMap;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Map.Entry;
29 import java.util.Set;
30
31 public class BasicMultiMap<K, V> implements MultiMap<K, V>, Serializable
32 {
33 private static final long serialVersionUID = 4716749660560043989L;
34 private final Map<K, List<V>> _impl;
35
36 public BasicMultiMap()
37 {
38 this(new LinkedHashMap<K, List<V>>());
39 }
40
41 public BasicMultiMap(Map<K, List<V>> impl)
42 {
43 _impl = impl;
44 }
45
46 @Override public List<V> getAll(Object key)
47 {
48 return _impl.get(key);
49 }
50
51 @Override public boolean isEmpty()
52 {
53 return _impl.isEmpty();
54 }
55
56 @Override public void add(K key, V value)
57 {
58 getList(key, true).add(value);
59 }
60
61 @Override public void add(K key, V value, int index)
62 {
63 getList(key, true).add(index, value);
64 }
65
66 @Override public void clear()
67 {
68 _impl.clear();
69 }
70
71 @Override public boolean containsKey(Object key)
72 {
73 return _impl.containsKey(key);
74 }
75
76 @Override public boolean containsValue(Object value)
77 {
78 boolean ret = false;
79
80 for (List<V> all : _impl.values())
81 {
82 if (all.contains(value))
83 {
84 ret = true;
85
86 break;
87 }
88 }
89
90 return ret;
91 }
92
93 @Override public Set<Entry<K, V>> entrySet()
94 {
95 Set<Entry<K, V>> ret = new HashSet<Entry<K, V>>();
96
97 for (K key : keySet())
98 {
99 ret.add(new ShadowEntry(key));
100 }
101
102 return ret;
103 }
104
105 @Override public V get(Object key)
106 {
107 List<V> values = getList(key, false);
108
109 return (values == null) ? null : values.get(values.size() - 1);
110 }
111
112 @Override public V get(Object key, int index)
113 {
114 List<V> values = getList(key, false);
115
116 return (values == null) ? null : values.get(index);
117 }
118
119 @Override public Set<K> keySet()
120 {
121 return _impl.keySet();
122 }
123
124 @Override public int length(Object key)
125 {
126 List<V> values = getList(key, false);
127
128 return (values == null) ? 0 : values.size();
129 }
130
131 @Override public V put(K key, V value)
132 {
133 V ret = null;
134 List<V> values = getList(key, true);
135
136 if (values.isEmpty())
137 {
138 values.add(value);
139 }
140 else
141 {
142 ret = values.set(values.size() - 1, value);
143 }
144
145 return ret;
146 }
147
148 @Override public V put(K key, V value, int index)
149 {
150 return getList(key, false).set(index, value);
151 }
152
153 @SuppressWarnings(Warnings.UNCHECKED)
154 @Override public void putAll(Map<? extends K, ? extends V> map)
155 {
156 if (map instanceof MultiMap)
157 {
158 MultiMap<K, V> mm = (MultiMap<K, V>) map;
159
160 for (Object key : mm.keySet())
161 {
162 putAll((K) key, mm.getAll(key));
163 }
164 }
165 else
166 {
167 for (K key : map.keySet())
168 {
169 put(key, map.get(key));
170 }
171 }
172 }
173
174 @Override public List<V> putAll(K key, List<V> values)
175 {
176 List<V> ret = _impl.get(key);
177
178 _impl.put(key, new ArrayList<V>(values));
179
180 return ret;
181 }
182
183 @Override public V remove(Object key)
184 {
185 List<V> prev = _impl.remove(key);
186
187 return (prev == null) ? null : prev.get(0);
188 }
189
190 @Override public V remove(Object key, int index)
191 {
192 V ret = null;
193 List<V> values = getList(key, false);
194
195 if (values != null)
196 {
197 ret = values.remove(index);
198 if (values.isEmpty())
199 {
200 _impl.remove(key);
201 }
202 }
203
204 return ret;
205 }
206
207 @Override public int size()
208 {
209 return _impl.size();
210 }
211
212 @Override public String toString()
213 {
214 return _impl.toString();
215 }
216
217 @Override public Collection<V> values()
218 {
219 List<V> all = new ArrayList<V>(_impl.size());
220
221 for (List<V> values : _impl.values())
222 {
223 all.addAll(values);
224 }
225
226 return all;
227 }
228
229 @SuppressWarnings(Warnings.UNCHECKED)
230 private List<V> getList(Object key, boolean create)
231 {
232 List<V> values = _impl.get(key);
233
234 if ((values == null) && create)
235 {
236 values = new ArrayList<V>();
237 _impl.put((K) key, values);
238 }
239
240 return values;
241 }
242
243 class ShadowEntry implements Map.Entry<K, V>
244 {
245 private final K _key;
246
247 ShadowEntry(K key)
248 {
249 _key = key;
250 }
251
252 @Override public K getKey()
253 {
254 return _key;
255 }
256
257 @Override public V getValue()
258 {
259 return get(_key);
260 }
261
262 @Override public V setValue(V value)
263 {
264 return put(_key, value);
265 }
266 }
267 }