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