1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.eclipse.jetty.util;
15
16 import java.io.Serializable;
17 import java.util.Arrays;
18 import java.util.Collection;
19 import java.util.HashMap;
20 import java.util.List;
21 import java.util.Map;
22 import java.util.Set;
23 import java.util.concurrent.ConcurrentHashMap;
24 import java.util.concurrent.ConcurrentMap;
25
26
27
28
29
30
31
32
33
34
35
36
37 public class MultiMap<K> implements ConcurrentMap<K,Object>, Serializable
38 {
39 private static final long serialVersionUID = -6878723138353851005L;
40 Map<K,Object> _map;
41 ConcurrentMap<K, Object> _cmap;
42
43 public MultiMap()
44 {
45 _map=new HashMap<K, Object>();
46 }
47
48 public MultiMap(Map<K,Object> map)
49 {
50 if (map instanceof ConcurrentMap)
51 _map=_cmap=new ConcurrentHashMap<K, Object>(map);
52 else
53 _map=new HashMap<K, Object>(map);
54 }
55
56 public MultiMap(MultiMap<K> map)
57 {
58 if (map._cmap!=null)
59 _map=_cmap=new ConcurrentHashMap<K, Object>(map._cmap);
60 else
61 _map=new HashMap<K,Object>(map._map);
62 }
63
64 public MultiMap(int capacity)
65 {
66 _map=new HashMap<K, Object>(capacity);
67 }
68
69 public MultiMap(boolean concurrent)
70 {
71 if (concurrent)
72 _map=_cmap=new ConcurrentHashMap<K, Object>();
73 else
74 _map=new HashMap<K, Object>();
75 }
76
77
78
79
80
81
82
83
84 public List getValues(Object name)
85 {
86 return LazyList.getList(_map.get(name),true);
87 }
88
89
90
91
92
93
94
95
96
97 public Object getValue(Object name,int i)
98 {
99 Object l=_map.get(name);
100 if (i==0 && LazyList.size(l)==0)
101 return null;
102 return LazyList.get(l,i);
103 }
104
105
106
107
108
109
110
111
112
113
114 public String getString(Object name)
115 {
116 Object l=_map.get(name);
117 switch(LazyList.size(l))
118 {
119 case 0:
120 return null;
121 case 1:
122 Object o=LazyList.get(l,0);
123 return o==null?null:o.toString();
124 default:
125 {
126 StringBuilder values=new StringBuilder(128);
127 for (int i=0; i<LazyList.size(l); i++)
128 {
129 Object e=LazyList.get(l,i);
130 if (e!=null)
131 {
132 if (values.length()>0)
133 values.append(',');
134 values.append(e.toString());
135 }
136 }
137 return values.toString();
138 }
139 }
140 }
141
142
143 public Object get(Object name)
144 {
145 Object l=_map.get(name);
146 switch(LazyList.size(l))
147 {
148 case 0:
149 return null;
150 case 1:
151 Object o=LazyList.get(l,0);
152 return o;
153 default:
154 return LazyList.getList(l,true);
155 }
156 }
157
158
159
160
161
162
163
164 public Object put(K name, Object value)
165 {
166 return _map.put(name,LazyList.add(null,value));
167 }
168
169
170
171
172
173
174
175 public Object putValues(K name, List<? extends Object> values)
176 {
177 return _map.put(name,values);
178 }
179
180
181
182
183
184
185
186 public Object putValues(K name, String... values)
187 {
188 Object list=null;
189 for (int i=0;i<values.length;i++)
190 list=LazyList.add(list,values[i]);
191 return _map.put(name,list);
192 }
193
194
195
196
197
198
199
200
201
202 public void add(K name, Object value)
203 {
204 Object lo = _map.get(name);
205 Object ln = LazyList.add(lo,value);
206 if (lo!=ln)
207 _map.put(name,ln);
208 }
209
210
211
212
213
214
215
216
217 public void addValues(K name, List<? extends Object> values)
218 {
219 Object lo = _map.get(name);
220 Object ln = LazyList.addCollection(lo,values);
221 if (lo!=ln)
222 _map.put(name,ln);
223 }
224
225
226
227
228
229
230
231
232 public void addValues(K name, String[] values)
233 {
234 Object lo = _map.get(name);
235 Object ln = LazyList.addCollection(lo,Arrays.asList(values));
236 if (lo!=ln)
237 _map.put(name,ln);
238 }
239
240
241
242
243
244
245
246 public boolean removeValue(K name,Object value)
247 {
248 Object lo = _map.get(name);
249 Object ln=lo;
250 int s=LazyList.size(lo);
251 if (s>0)
252 {
253 ln=LazyList.remove(lo,value);
254 if (ln==null)
255 _map.remove(name);
256 else
257 _map.put(name, ln);
258 }
259 return LazyList.size(ln)!=s;
260 }
261
262
263
264
265
266
267 public void putAll(Map<? extends K, ? extends Object> m)
268 {
269 boolean multi = (m instanceof MultiMap);
270
271 if (multi)
272 {
273 for (Map.Entry<? extends K, ? extends Object> entry : m.entrySet())
274 {
275 _map.put(entry.getKey(),LazyList.clone(entry.getValue()));
276 }
277 }
278 else
279 {
280 _map.putAll(m);
281 }
282 }
283
284
285
286
287
288 public Map<K,String[]> toStringArrayMap()
289 {
290 HashMap<K,String[]> map = new HashMap<K,String[]>(_map.size()*3/2);
291
292 for(Map.Entry<K,Object> entry: _map.entrySet())
293 {
294 String[] a = LazyList.toStringArray(entry.getValue());
295 map.put(entry.getKey(),a);
296 }
297 return map;
298 }
299
300 @Override
301 public String toString()
302 {
303 return _cmap==null?_map.toString():_cmap.toString();
304 }
305
306 public void clear()
307 {
308 _map.clear();
309 }
310
311 public boolean containsKey(Object key)
312 {
313 return _map.containsKey(key);
314 }
315
316 public boolean containsValue(Object value)
317 {
318 return _map.containsValue(value);
319 }
320
321 public Set<Entry<K, Object>> entrySet()
322 {
323 return _map.entrySet();
324 }
325
326 @Override
327 public boolean equals(Object o)
328 {
329 return _map.equals(o);
330 }
331
332 @Override
333 public int hashCode()
334 {
335 return _map.hashCode();
336 }
337
338 public boolean isEmpty()
339 {
340 return _map.isEmpty();
341 }
342
343 public Set<K> keySet()
344 {
345 return _map.keySet();
346 }
347
348 public Object remove(Object key)
349 {
350 return _map.remove(key);
351 }
352
353 public int size()
354 {
355 return _map.size();
356 }
357
358 public Collection<Object> values()
359 {
360 return _map.values();
361 }
362
363
364
365 public Object putIfAbsent(K key, Object value)
366 {
367 if (_cmap==null)
368 throw new UnsupportedOperationException();
369 return _cmap.putIfAbsent(key,value);
370 }
371
372 public boolean remove(Object key, Object value)
373 {
374 if (_cmap==null)
375 throw new UnsupportedOperationException();
376 return _cmap.remove(key,value);
377 }
378
379 public boolean replace(K key, Object oldValue, Object newValue)
380 {
381 if (_cmap==null)
382 throw new UnsupportedOperationException();
383 return _cmap.replace(key,oldValue,newValue);
384 }
385
386 public Object replace(K key, Object value)
387 {
388 if (_cmap==null)
389 throw new UnsupportedOperationException();
390 return _cmap.replace(key,value);
391 }
392 }