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