1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.portals.bridges.jsf;
18
19 import java.util.AbstractSet;
20 import java.util.ArrayList;
21 import java.util.Collection;
22 import java.util.Enumeration;
23 import java.util.Iterator;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.NoSuchElementException;
27 import java.util.Set;
28
29 /***
30 * <p>
31 * Helper Map implementation for use with different Attribute Maps.
32 * </p>
33 * <p>
34 * See MyFaces project for servlet implementation.
35 * </p>
36 *
37 * @author <a href="dlestrat@apache.org">David Le Strat </a>
38 *
39 */
40 public abstract class AbstractAttributeMap implements Map
41 {
42 private Set keySet;
43
44 private Collection values;
45
46 private Set entrySet;
47
48 /***
49 * @see java.util.Map#clear()
50 */
51 public void clear()
52 {
53 List names = new ArrayList();
54 for (Enumeration e = getAttributeNames(); e.hasMoreElements();)
55 {
56 names.add(e.nextElement());
57 }
58
59 for (Iterator it = names.iterator(); it.hasNext();)
60 {
61 removeAttribute((String) it.next());
62 }
63 }
64
65 /***
66 * @see java.util.Map#containsKey(java.lang.Object)
67 */
68 public boolean containsKey(Object key)
69 {
70 return getAttribute(key.toString()) != null;
71 }
72
73 /***
74 * @see java.util.Map#containsValue(java.lang.Object)
75 */
76 public boolean containsValue(Object findValue)
77 {
78 if (findValue == null)
79 {
80 return false;
81 }
82
83 for (Enumeration e = getAttributeNames(); e.hasMoreElements();)
84 {
85 Object value = getAttribute((String) e.nextElement());
86 if (findValue.equals(value))
87 {
88 return true;
89 }
90 }
91
92 return false;
93 }
94
95 /***
96 * @see java.util.Map#entrySet()
97 */
98 public Set entrySet()
99 {
100 return (entrySet != null) ? entrySet : (entrySet = new EntrySet());
101 }
102
103 /***
104 * @see java.util.Map#get(java.lang.Object)
105 */
106 public Object get(Object key)
107 {
108 return getAttribute(key.toString());
109 }
110
111 /***
112 * @see java.util.Map#isEmpty()
113 */
114 public boolean isEmpty()
115 {
116 return !getAttributeNames().hasMoreElements();
117 }
118
119 /***
120 * @see java.util.Map#keySet()
121 */
122 public Set keySet()
123 {
124 return (keySet != null) ? keySet : (keySet = new KeySet());
125 }
126
127 /***
128 * @see java.util.Map#put(java.lang.Object, java.lang.Object)
129 */
130 public Object put(Object key, Object value)
131 {
132 String localKey = key.toString();
133 Object retval = getAttribute(localKey);
134 setAttribute(localKey, value);
135 return retval;
136 }
137
138 /***
139 * @see java.util.Map#putAll(java.util.Map)
140 */
141 public void putAll(Map t)
142 {
143 for (Iterator it = t.entrySet().iterator(); it.hasNext();)
144 {
145 Entry entry = (Entry) it.next();
146 setAttribute(entry.getKey().toString(), entry.getValue());
147 }
148 }
149
150 /***
151 * @see java.util.Map#remove(java.lang.Object)
152 */
153 public Object remove(Object key)
154 {
155 String localKey = key.toString();
156 Object retval = getAttribute(localKey);
157 removeAttribute(localKey);
158 return retval;
159 }
160
161 /***
162 * @see java.util.Map#size()
163 */
164 public int size()
165 {
166 int size = 0;
167 for (Enumeration e = getAttributeNames(); e.hasMoreElements();)
168 {
169 size++;
170 e.nextElement();
171 }
172 return size;
173 }
174
175 /***
176 * @see java.util.Map#values()
177 */
178 public Collection values()
179 {
180 return (values != null) ? values : (values = new Values());
181 }
182
183 /***
184 * <p>
185 * Gets an attribute given a key.
186 * </p>
187 *
188 * @param key The key.
189 * @return The attribute.
190 */
191 abstract protected Object getAttribute(String key);
192
193 /***
194 * <p>
195 * Sets an attribute given a key/value.
196 * </p>
197 *
198 * @param key The key.
199 * @param value The value.
200 */
201 abstract protected void setAttribute(String key, Object value);
202
203 /***
204 * <p>
205 * Removes an attribute.
206 * </p>
207 *
208 * @param key The key.
209 */
210 abstract protected void removeAttribute(String key);
211
212 /***
213 * <p>
214 * Gets the attributes names.
215 * </p>
216 *
217 * @return An enumeration of attributes names.
218 */
219 abstract protected Enumeration getAttributeNames();
220
221 private class KeySet extends AbstractSet
222 {
223 public Iterator iterator()
224 {
225 return new KeyIterator();
226 }
227
228 public boolean isEmpty()
229 {
230 return AbstractAttributeMap.this.isEmpty();
231 }
232
233 public int size()
234 {
235 return AbstractAttributeMap.this.size();
236 }
237
238 public boolean contains(Object o)
239 {
240 return AbstractAttributeMap.this.containsKey(o);
241 }
242
243 public boolean remove(Object o)
244 {
245 return AbstractAttributeMap.this.remove(o) != null;
246 }
247
248 public void clear()
249 {
250 AbstractAttributeMap.this.clear();
251 }
252 }
253
254 private class KeyIterator implements Iterator
255 {
256 protected final Enumeration _e = getAttributeNames();
257
258 protected Object _currentKey;
259
260 public void remove()
261 {
262
263
264
265 if (_currentKey == null)
266 {
267 throw new NoSuchElementException("You must call next() at least once");
268 }
269 AbstractAttributeMap.this.remove(_currentKey);
270 }
271
272 public boolean hasNext()
273 {
274 return _e.hasMoreElements();
275 }
276
277 public Object next()
278 {
279 return _currentKey = _e.nextElement();
280 }
281 }
282
283 private class Values extends KeySet
284 {
285 public Iterator iterator()
286 {
287 return new ValuesIterator();
288 }
289
290 public boolean contains(Object o)
291 {
292 return AbstractAttributeMap.this.containsValue(o);
293 }
294
295 public boolean remove(Object o)
296 {
297 if (o == null)
298 {
299 return false;
300 }
301
302 for (Iterator it = iterator(); it.hasNext();)
303 {
304 if (o.equals(it.next()))
305 {
306 it.remove();
307 return true;
308 }
309 }
310
311 return false;
312 }
313 }
314
315 private class ValuesIterator extends KeyIterator
316 {
317 public Object next()
318 {
319 super.next();
320 return AbstractAttributeMap.this.get(_currentKey);
321 }
322 }
323
324 private class EntrySet extends KeySet
325 {
326 public Iterator iterator()
327 {
328 return new EntryIterator();
329 }
330
331 public boolean contains(Object o)
332 {
333 if (!(o instanceof Entry))
334 {
335 return false;
336 }
337
338 Entry entry = (Entry) o;
339 Object key = entry.getKey();
340 Object value = entry.getValue();
341 if (key == null || value == null)
342 {
343 return false;
344 }
345
346 return value.equals(AbstractAttributeMap.this.get(key));
347 }
348
349 public boolean remove(Object o)
350 {
351 if (!(o instanceof Entry))
352 {
353 return false;
354 }
355
356 Entry entry = (Entry) o;
357 Object key = entry.getKey();
358 Object value = entry.getValue();
359 if (key == null || value == null || !value.equals(AbstractAttributeMap.this.get(key)))
360 {
361 return false;
362 }
363
364 return AbstractAttributeMap.this.remove(((Entry) o).getKey()) != null;
365 }
366 }
367
368 /***
369 * Not very efficient since it generates a new instance of
370 * <code>Entry</code> for each element and still internaly uses the
371 * <code>KeyIterator</code>. It is more efficient to use the
372 * <code>KeyIterator</code> directly.
373 */
374 private class EntryIterator extends KeyIterator
375 {
376 public Object next()
377 {
378 super.next();
379
380
381 return new EntrySetEntry(_currentKey);
382 }
383 }
384
385 private class EntrySetEntry implements Entry
386 {
387 private final Object _currentKey;
388
389 public EntrySetEntry(Object currentKey)
390 {
391 _currentKey = currentKey;
392 }
393
394 public Object getKey()
395 {
396 return _currentKey;
397 }
398
399 public Object getValue()
400 {
401 return AbstractAttributeMap.this.get(_currentKey);
402 }
403
404 public Object setValue(Object value)
405 {
406 return AbstractAttributeMap.this.put(_currentKey, value);
407 }
408 }
409 }