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.Collection;
24 import java.util.Collections;
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 public abstract class AbstractThreadSafeAttributeMap<V> extends AbstractMap<String, V>
39 {
40 private Set<String> _keySet;
41 private Collection<V> _values;
42 private Set<Entry<String, V>> _entrySet;
43
44 @Override
45 public void clear()
46 {
47 final List<String> names = Collections.list(getAttributeNames());
48
49 for (String name : names)
50 {
51 removeAttribute(name);
52 }
53 }
54
55 @Override
56 public final boolean containsKey(final Object key)
57 {
58 return getAttribute(key.toString()) != null;
59 }
60
61 @Override
62 public boolean containsValue(final Object findValue)
63 {
64 if (findValue == null)
65 {
66 return false;
67 }
68
69 for (final Enumeration<String> e = getAttributeNames(); e.hasMoreElements();)
70 {
71 final Object value = getAttribute(e.nextElement());
72 if (findValue.equals(value))
73 {
74 return true;
75 }
76 }
77
78 return false;
79 }
80
81 @Override
82 public Set<Entry<String, V>> entrySet()
83 {
84 return (_entrySet != null) ? _entrySet : (_entrySet = new EntrySet());
85 }
86
87 @Override
88 public V get(final Object key)
89 {
90 return getAttribute(key.toString());
91 }
92
93 @Override
94 public boolean isEmpty()
95 {
96 return !getAttributeNames().hasMoreElements();
97 }
98
99 @Override
100 public Set<String> keySet()
101 {
102 return (_keySet != null) ? _keySet : (_keySet = new KeySet());
103 }
104
105 @Override
106 public final V put(final String key, final V value)
107 {
108 final V retval = getAttribute(key);
109 setAttribute(key, value);
110 return retval;
111 }
112
113 @Override
114 public void putAll(final Map<? extends String, ? extends V> t)
115 {
116 for (final Entry<? extends String, ? extends V> entry : t.entrySet())
117 {
118 setAttribute(entry.getKey(), entry.getValue());
119 }
120 }
121
122 @Override
123 public final V remove(final Object key)
124 {
125 final String key_ = key.toString();
126 final V retval = getAttribute(key_);
127 removeAttribute(key_);
128 return retval;
129 }
130
131 @Override
132 public int size()
133 {
134 int size = 0;
135 for (final Enumeration<String> e = getAttributeNames(); e.hasMoreElements();)
136 {
137 size++;
138 e.nextElement();
139 }
140 return size;
141 }
142
143 @Override
144 public Collection<V> values()
145 {
146 return (_values != null) ? _values : (_values = new Values());
147 }
148
149 abstract protected V getAttribute(String key);
150
151 abstract protected void setAttribute(String key, V value);
152
153 abstract protected void removeAttribute(String key);
154
155 abstract protected Enumeration<String> getAttributeNames();
156
157 private abstract class AbstractAttributeSet<E> extends AbstractSet<E>
158 {
159 @Override
160 public boolean isEmpty()
161 {
162 return AbstractThreadSafeAttributeMap.this.isEmpty();
163 }
164
165 @Override
166 public int size()
167 {
168 return AbstractThreadSafeAttributeMap.this.size();
169 }
170
171 @Override
172 public void clear()
173 {
174 AbstractThreadSafeAttributeMap.this.clear();
175 }
176 }
177
178 private final class KeySet extends AbstractAttributeSet<String>
179 {
180 @Override
181 public Iterator<String> iterator()
182 {
183 return new KeyIterator();
184 }
185
186 @Override
187 public boolean contains(final Object o)
188 {
189 return AbstractThreadSafeAttributeMap.this.containsKey(o);
190 }
191
192 @Override
193 public boolean remove(final Object o)
194 {
195 return AbstractThreadSafeAttributeMap.this.remove(o) != null;
196 }
197
198 }
199
200 private abstract class AbstractAttributeIterator<E> implements Iterator<E>
201 {
202
203
204
205
206
207
208 protected final Iterator<String> _i = Collections.list(getAttributeNames()).iterator();
209 protected String _currentKey;
210
211 public void remove()
212 {
213 if (_currentKey == null)
214 {
215 throw new NoSuchElementException("You must call next() at least once");
216 }
217 AbstractThreadSafeAttributeMap.this.remove(_currentKey);
218 }
219
220 public boolean hasNext()
221 {
222 return _i.hasNext();
223 }
224
225 public E next()
226 {
227 return getValue(_currentKey = _i.next());
228 }
229
230 protected abstract E getValue(String attributeName);
231 }
232
233 private final class KeyIterator extends AbstractAttributeIterator<String>
234 {
235 @Override
236 protected String getValue(final String attributeName)
237 {
238 return attributeName;
239 }
240 }
241
242 private class Values extends AbstractAttributeSet<V>
243 {
244 @Override
245 public Iterator<V> iterator()
246 {
247 return new ValuesIterator();
248 }
249
250 @Override
251 public boolean contains(final Object o)
252 {
253 if (o == null)
254 {
255 return false;
256 }
257
258 for (final Iterator<V> it = iterator(); it.hasNext();)
259 {
260 if (o.equals(it.next()))
261 {
262 return true;
263 }
264 }
265
266 return false;
267 }
268
269 @Override
270 public boolean remove(final Object o)
271 {
272 if (o == null)
273 {
274 return false;
275 }
276
277 for (final Iterator<V> it = iterator(); it.hasNext();)
278 {
279 if (o.equals(it.next()))
280 {
281 it.remove();
282 return true;
283 }
284 }
285
286 return false;
287 }
288 }
289
290 private class ValuesIterator extends AbstractAttributeIterator<V>
291 {
292 @Override
293 protected V getValue(final String attributeName)
294 {
295 return AbstractThreadSafeAttributeMap.this.get(attributeName);
296 }
297 }
298
299 private final class EntrySet extends AbstractAttributeSet<Entry<String, V>>
300 {
301 @Override
302 public Iterator<Entry<String, V>> iterator()
303 {
304 return new EntryIterator();
305 }
306
307 @SuppressWarnings("unchecked")
308 @Override
309 public boolean contains(final Object o)
310 {
311 if (!(o instanceof Entry))
312 {
313 return false;
314 }
315
316 final Entry<String, V> entry = (Entry<String, V>)o;
317 final Object key = entry.getKey();
318 final Object value = entry.getValue();
319 if (key == null || value == null)
320 {
321 return false;
322 }
323
324 return value.equals(AbstractThreadSafeAttributeMap.this.get(key));
325 }
326
327 @SuppressWarnings("unchecked")
328 @Override
329 public boolean remove(final Object o)
330 {
331 if (!(o instanceof Entry))
332 {
333 return false;
334 }
335
336 final Entry<String, V> entry = (Entry<String, V>)o;
337 final Object key = entry.getKey();
338 final Object value = entry.getValue();
339 if (key == null || value == null || !value.equals(AbstractThreadSafeAttributeMap.this.get(key)))
340 {
341 return false;
342 }
343
344 return AbstractThreadSafeAttributeMap.this.remove(((Entry<String, V>)o).getKey()) != null;
345 }
346 }
347
348
349
350
351
352 private final class EntryIterator extends AbstractAttributeIterator<Entry<String, V>>
353 {
354 @Override
355 protected Entry<String, V> getValue(final String attributeName)
356 {
357
358
359 return new EntrySetEntry(attributeName);
360 }
361 }
362
363 private final class EntrySetEntry implements Entry<String, V>
364 {
365 private final String _currentKey;
366
367 public EntrySetEntry(final String currentKey)
368 {
369 _currentKey = currentKey;
370 }
371
372 public String getKey()
373 {
374 return _currentKey;
375 }
376
377 public V getValue()
378 {
379 return AbstractThreadSafeAttributeMap.this.get(_currentKey);
380 }
381
382 public V setValue(final V value)
383 {
384 return AbstractThreadSafeAttributeMap.this.put(_currentKey, value);
385 }
386
387 @Override
388 public int hashCode()
389 {
390 int result = 1;
391 result = 31 * result + ((_currentKey == null) ? 0 : _currentKey.hashCode());
392 return result;
393 }
394
395 @Override
396 public boolean equals(final Object obj)
397 {
398 if (this == obj)
399 return true;
400 if (obj == null)
401 return false;
402 if (getClass() != obj.getClass())
403 return false;
404 final EntrySetEntry other = (EntrySetEntry)obj;
405 if (_currentKey == null)
406 {
407 if (other._currentKey != null)
408 return false;
409 }
410 else if (!_currentKey.equals(other._currentKey))
411 return false;
412 return true;
413 }
414
415 }
416 }