1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.util;
20
21 import java.util.AbstractMap;
22 import java.util.AbstractSet;
23 import java.util.ArrayList;
24 import java.util.Collection;
25 import java.util.Enumeration;
26 import java.util.Iterator;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.NoSuchElementException;
30 import java.util.Set;
31
32
33
34
35
36
37
38
39 public abstract class AbstractThreadSafeAttributeMap extends AbstractMap
40 {
41 private Set _keySet;
42 private Collection _values;
43 private Set _entrySet;
44
45 public void clear()
46 {
47 final List names = _list(getAttributeNames());
48
49 for (Iterator it = names.iterator(); it.hasNext();)
50 {
51 removeAttribute((String) it.next());
52 }
53 }
54
55 public boolean containsKey(Object key)
56 {
57 return getAttribute(key.toString()) != null;
58 }
59
60 public boolean containsValue(Object findValue)
61 {
62 if (findValue == null)
63 {
64 return false;
65 }
66
67 for (Enumeration e = getAttributeNames(); e.hasMoreElements();)
68 {
69 Object value = getAttribute((String) e.nextElement());
70 if (findValue.equals(value))
71 {
72 return true;
73 }
74 }
75
76 return false;
77 }
78
79 public Set entrySet()
80 {
81 return (_entrySet != null) ? _entrySet : (_entrySet = new EntrySet());
82 }
83
84 public Object get(Object key)
85 {
86 return getAttribute(key.toString());
87 }
88
89 public boolean isEmpty()
90 {
91 return !getAttributeNames().hasMoreElements();
92 }
93
94 public Set keySet()
95 {
96 return (_keySet != null) ? _keySet : (_keySet = new KeySet());
97 }
98
99 public Object put(Object key, Object value)
100 {
101 String key_ = key.toString();
102 Object retval = getAttribute(key_);
103 setAttribute(key_, value);
104 return retval;
105 }
106
107 public void putAll(Map t)
108 {
109 for (Iterator it = t.entrySet().iterator(); it.hasNext();)
110 {
111 Entry entry = (Entry) it.next();
112 setAttribute(entry.getKey().toString(), entry.getValue());
113 }
114 }
115
116 public Object remove(Object key)
117 {
118 String key_ = key.toString();
119 Object retval = getAttribute(key_);
120 removeAttribute(key_);
121 return retval;
122 }
123
124 public int size()
125 {
126 int size = 0;
127 for (Enumeration e = getAttributeNames(); e.hasMoreElements();)
128 {
129 size++;
130 e.nextElement();
131 }
132 return size;
133 }
134
135 public Collection values()
136 {
137 return (_values != null) ? _values : (_values = new Values());
138 }
139
140
141
142
143 private ArrayList _list(Enumeration e) {
144 ArrayList l = new ArrayList();
145 while (e.hasMoreElements())
146 {
147 l.add(e.nextElement());
148 }
149 return l;
150 }
151
152
153 abstract protected Object getAttribute(String key);
154
155 abstract protected void setAttribute(String key, Object value);
156
157 abstract protected void removeAttribute(String key);
158
159 abstract protected Enumeration getAttributeNames();
160
161
162 private class KeySet extends AbstractSet
163 {
164 public Iterator iterator()
165 {
166 return new KeyIterator();
167 }
168
169 public boolean isEmpty()
170 {
171 return AbstractThreadSafeAttributeMap.this.isEmpty();
172 }
173
174 public int size()
175 {
176 return AbstractThreadSafeAttributeMap.this.size();
177 }
178
179 public boolean contains(Object o)
180 {
181 return AbstractThreadSafeAttributeMap.this.containsKey(o);
182 }
183
184 public boolean remove(Object o)
185 {
186 return AbstractThreadSafeAttributeMap.this.remove(o) != null;
187 }
188
189 public void clear()
190 {
191 AbstractThreadSafeAttributeMap.this.clear();
192 }
193 }
194
195 private class KeyIterator
196 implements Iterator
197 {
198
199
200
201
202
203
204 protected final Iterator _i = _list(getAttributeNames()).iterator();
205 protected Object _currentKey;
206
207 public void remove()
208 {
209 if (_currentKey == null)
210 {
211 throw new NoSuchElementException(
212 "You must call next() at least once");
213 }
214 AbstractThreadSafeAttributeMap.this.remove(_currentKey);
215 }
216
217 public boolean hasNext()
218 {
219 return _i.hasNext();
220 }
221
222 public Object next()
223 {
224 return _currentKey = _i.next();
225 }
226 }
227
228 private class Values extends KeySet
229 {
230 public Iterator iterator()
231 {
232 return new ValuesIterator();
233 }
234
235 public boolean contains(Object o)
236 {
237 return AbstractThreadSafeAttributeMap.this.containsValue(o);
238 }
239
240 public boolean remove(Object o)
241 {
242 if (o == null)
243 {
244 return false;
245 }
246
247 for (Iterator it = iterator(); it.hasNext();)
248 {
249 if (o.equals(it.next()))
250 {
251 it.remove();
252 return true;
253 }
254 }
255
256 return false;
257 }
258 }
259
260 private class ValuesIterator extends KeyIterator
261 {
262 public Object next()
263 {
264 super.next();
265 return AbstractThreadSafeAttributeMap.this.get(_currentKey);
266 }
267 }
268
269 private class EntrySet extends KeySet
270 {
271 public Iterator iterator() {
272 return new EntryIterator();
273 }
274
275 public boolean contains(Object o) {
276 if (!(o instanceof Entry))
277 {
278 return false;
279 }
280
281 Entry entry = (Entry) o;
282 Object key = entry.getKey();
283 Object value = entry.getValue();
284 if (key == null || value == null)
285 {
286 return false;
287 }
288
289 return value.equals(AbstractThreadSafeAttributeMap.this.get(key));
290 }
291
292 public boolean remove(Object o) {
293 if (!(o instanceof Entry))
294 {
295 return false;
296 }
297
298 Entry entry = (Entry) o;
299 Object key = entry.getKey();
300 Object value = entry.getValue();
301 if (key == null || value == null
302 || !value.equals(AbstractThreadSafeAttributeMap.this.get(key)))
303 {
304 return false;
305 }
306
307 return AbstractThreadSafeAttributeMap.this.remove(((Entry) o).getKey()) != null;
308 }
309 }
310
311
312
313
314
315
316 private class EntryIterator extends KeyIterator
317 {
318 public Object next()
319 {
320 super.next();
321
322
323 return new EntrySetEntry(_currentKey);
324 }
325 }
326
327 private class EntrySetEntry implements Entry
328 {
329 private final Object _currentKey;
330
331 public EntrySetEntry(Object currentKey)
332 {
333 _currentKey = currentKey;
334 }
335
336 public Object getKey()
337 {
338 return _currentKey;
339 }
340
341 public Object getValue()
342 {
343 return AbstractThreadSafeAttributeMap.this.get(_currentKey);
344 }
345
346 public Object setValue(Object value)
347 {
348 return AbstractThreadSafeAttributeMap.this.put(_currentKey, value);
349 }
350
351 public int hashCode() {
352 return _currentKey == null ? 0 : _currentKey.hashCode();
353 }
354
355 public boolean equals(Object obj) {
356 if (!(obj instanceof EntrySetEntry))
357 return false;
358 return _currentKey != null && _currentKey.equals(obj);
359 }
360 }
361 }