Initial commit with hopefully working J2EE request handler.
[jsvc.git] / src / dolda / jsvc / util / WrappedMultiMap.java
1 package dolda.jsvc.util;
2
3 import dolda.jsvc.MultiMap;
4 import java.util.*;
5
6 public class WrappedMultiMap<K, V> implements MultiMap<K, V> {
7     private Map<K, Collection<V>> bk;
8     private EntrySet entryset;
9     private Values values;
10     
11     public WrappedMultiMap(Map<K, Collection<V>> bk) {
12         this.bk = bk;
13     }
14     
15     private V get1(Collection<V> vs) {
16         if(vs == null)
17             return(null);
18         Iterator<V> i = vs.iterator();
19         if(!i.hasNext())
20             return(null);
21         return(i.next());
22     }
23
24     public void clear() {
25         modified();
26         bk.clear();
27     }
28     
29     public boolean containsKey(Object key) {
30         Collection<V> vs = bk.get(key);
31         if(vs == null)
32             return(false);
33         return(!vs.isEmpty());
34     }
35     
36     public boolean equals(Object o) {
37         return(bk.equals(o));
38     }
39     
40     public V get(Object key) {
41         return(get1(bk.get(key)));
42     }
43     
44     public Collection<V> values(K key) {
45         Collection<V> vs = bk.get(key);
46         if(vs == null) {
47             vs = new LinkedList<V>();
48             bk.put(key, vs);
49         }
50         return(vs);
51     }
52     
53     public int hashCode() {
54         return(bk.hashCode());
55     }
56     
57     public boolean isEmpty() {
58         return(values().isEmpty());
59     }
60     
61     public Set<K> keySet() {
62         return(bk.keySet());
63     }
64     
65     public V put(K key, V value) {
66         Collection<V> vs = new LinkedList<V>();
67         vs.add(value);
68         modified();
69         return(get1(bk.put(key, vs)));
70     }
71     
72     public void add(K key, V value) {
73         modified();
74         values(key).add(value);
75     }
76     
77     public Collection<V> putValues(K key, Collection<V> values) {
78         modified();
79         return(bk.put(key, values));
80     }
81     
82     private class DumbEntry implements Map.Entry<K, V> {
83         private K key;
84         private V value;
85         
86         public DumbEntry(K key, V value) {
87             this.key = key;
88             this.value = value;
89         }
90         
91         public boolean equals(Object o) {
92             if(!(o instanceof Map.Entry))
93                 return(false);
94             Map.Entry oe = (Map.Entry)o;
95             return(((key == null)?(oe.getKey() == null):key.equals(oe.getKey())) &&
96                    ((value == null)?(oe.getValue() == null):value.equals(oe.getValue())));
97         }
98         
99         public K getKey() {
100             return(key);
101         }
102         
103         public V getValue() {
104             return(value);
105         }
106         
107         public int hashCode() {
108             return(key.hashCode() + value.hashCode());
109         }
110         
111         public V setValue(V value) {
112             throw(new UnsupportedOperationException());
113         }
114     }
115
116     private class EntrySet extends AbstractSet<Map.Entry<K, V>> {
117         public Iterator<Map.Entry<K, V>> iterator() {
118             return(new Iterator<Map.Entry<K, V>>() {
119                     private Iterator<Map.Entry<K, Collection<V>>> bki = bk.entrySet().iterator();
120                     private K curkey;
121                     private Iterator<V> vsi = null;
122                     
123                     public boolean hasNext() {
124                         if((vsi != null) && vsi.hasNext())
125                             return(true);
126                         return(bki.hasNext());
127                     }
128                     
129                     public Map.Entry<K, V> next() {
130                         if((vsi == null) || !vsi.hasNext()) {
131                             Map.Entry<K, Collection<V>> ne = bki.next();
132                             curkey = ne.getKey();
133                             vsi = ne.getValue().iterator();
134                         }
135                         return(new DumbEntry(curkey, vsi.next()));
136                     }
137                     
138                     public void remove() {
139                         modified();
140                         vsi.remove();
141                     }
142                 });
143         }
144         
145         public int size() {
146             return(WrappedMultiMap.this.size());
147         }
148         
149         public boolean remove(Object o) {
150             modified();
151             return(WrappedMultiMap.this.remove(o) != null);
152         }
153         
154         public void clear() {
155             modified();
156             bk.clear();
157         }
158     }
159
160     private class Values extends AbstractCollection<V> {
161         public Iterator<V> iterator() {
162             return(new Iterator<V>() {
163                     Iterator<Map.Entry<K, V>> bki = WrappedMultiMap.this.entrySet().iterator();
164                     
165                     public boolean hasNext() {
166                         return(bki.hasNext());
167                     }
168
169                     public V next() {
170                         return(bki.next().getValue());
171                     }
172                     
173                     public void remove() {
174                         modified();
175                         bki.remove();
176                     }
177                 });
178         }
179         
180         public int size() {
181             return(WrappedMultiMap.this.size());
182         }
183         
184         public boolean contains(Object o) {
185             return(containsValue(o));
186         }
187         
188         public void clear() {
189             modified();
190             bk.clear();
191         }
192     }
193
194     public Set<Map.Entry<K, V>> entrySet() {
195         if(entryset == null)
196             entryset = new EntrySet();
197         return(entryset);
198     }
199     
200     public Collection<V> values() {
201         if(values == null)
202             values = new Values();
203         return(values);
204     }
205     
206     public void putAll(Map<? extends K, ? extends V> m) {
207         modified();
208         for(Map.Entry<? extends K, ? extends V> e : m.entrySet())
209             add(e.getKey(), e.getValue());
210     }
211     
212     public V remove(Object key) {
213         modified();
214         return(get1(bk.remove(key)));
215     }
216     
217     public boolean containsValue(Object value) {
218         for(Collection<V> vs : bk.values()) {
219             if(vs.contains(value))
220                 return(true);
221         }
222         return(false);
223     }
224     
225     public int size() {
226         int i = 0;
227         for(Collection<V> vs : bk.values())
228             i += vs.size();
229         return(i);
230     }
231     
232     protected void modified() {}
233 }