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