Source code: org/apache/myfaces/context/servlet/AbstractAttributeMap.java
1 /*
2 * Copyright 2004 The Apache Software Foundation.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package org.apache.myfaces.context.servlet;
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 /**
30 * Helper Map implementation for use with different Attribute Maps.
31 *
32 * @author Anton Koinov (latest modification by $Author: grantsmith $)
33 * @version $Revision: 169649 $ $Date: 2005-05-11 11:47:12 -0400 (Wed, 11 May 2005) $
34 */
35 public abstract class AbstractAttributeMap
36 implements Map
37 {
38 private Set _keySet;
39 private Collection _values;
40 private Set _entrySet;
41
42 public void clear()
43 {
44 List names = new ArrayList();
45 for (Enumeration e = getAttributeNames(); e.hasMoreElements();)
46 {
47 names.add(e.nextElement());
48 }
49
50 for (Iterator it = names.iterator(); it.hasNext();)
51 {
52 removeAttribute((String) it.next());
53 }
54 }
55
56 public boolean containsKey(Object key)
57 {
58 return getAttribute(key.toString()) != null;
59 }
60
61 public boolean containsValue(Object findValue)
62 {
63 if (findValue == null)
64 {
65 return false;
66 }
67
68 for (Enumeration e = getAttributeNames(); e.hasMoreElements();)
69 {
70 Object value = getAttribute((String) e.nextElement());
71 if (findValue.equals(value))
72 {
73 return true;
74 }
75 }
76
77 return false;
78 }
79
80 public Set entrySet()
81 {
82 return (_entrySet != null) ? _entrySet : (_entrySet = new EntrySet());
83 }
84
85 public Object get(Object key)
86 {
87 return getAttribute(key.toString());
88 }
89
90 public boolean isEmpty()
91 {
92 return !getAttributeNames().hasMoreElements();
93 }
94
95 public Set keySet()
96 {
97 return (_keySet != null) ? _keySet : (_keySet = new KeySet());
98 }
99
100 public Object put(Object key, Object value)
101 {
102 String key_ = key.toString();
103 Object retval = getAttribute(key_);
104 setAttribute(key_, value);
105 return retval;
106 }
107
108 public void putAll(Map t)
109 {
110 for (Iterator it = t.entrySet().iterator(); it.hasNext();)
111 {
112 Entry entry = (Entry) it.next();
113 setAttribute(entry.getKey().toString(), entry.getValue());
114 }
115 }
116
117 public Object remove(Object key)
118 {
119 String key_ = key.toString();
120 Object retval = getAttribute(key_);
121 removeAttribute(key_);
122 return retval;
123 }
124
125 public int size()
126 {
127 int size = 0;
128 for (Enumeration e = getAttributeNames(); e.hasMoreElements();)
129 {
130 size++;
131 e.nextElement();
132 }
133 return size;
134 }
135
136 public Collection values()
137 {
138 return (_values != null) ? _values : (_values = new Values());
139 }
140
141
142 abstract protected Object getAttribute(String key);
143
144 abstract protected void setAttribute(String key, Object value);
145
146 abstract protected void removeAttribute(String key);
147
148 abstract protected Enumeration getAttributeNames();
149
150
151 private class KeySet extends AbstractSet
152 {
153 public Iterator iterator()
154 {
155 return new KeyIterator();
156 }
157
158 public boolean isEmpty()
159 {
160 return AbstractAttributeMap.this.isEmpty();
161 }
162
163 public int size()
164 {
165 return AbstractAttributeMap.this.size();
166 }
167
168 public boolean contains(Object o)
169 {
170 return AbstractAttributeMap.this.containsKey(o);
171 }
172
173 public boolean remove(Object o)
174 {
175 return AbstractAttributeMap.this.remove(o) != null;
176 }
177
178 public void clear()
179 {
180 AbstractAttributeMap.this.clear();
181 }
182 }
183
184 private class KeyIterator
185 implements Iterator
186 {
187 protected final Enumeration _e = getAttributeNames();
188 protected Object _currentKey;
189
190 public void remove()
191 {
192 // remove() may cause ConcurrentModificationException.
193 // We could throw an exception here, but not throwing an exception
194 // allows one call to remove() to succeed
195 if (_currentKey == null)
196 {
197 throw new NoSuchElementException(
198 "You must call next() at least once");
199 }
200 AbstractAttributeMap.this.remove(_currentKey);
201 }
202
203 public boolean hasNext()
204 {
205 return _e.hasMoreElements();
206 }
207
208 public Object next()
209 {
210 return _currentKey = _e.nextElement();
211 }
212 }
213
214 private class Values extends KeySet
215 {
216 public Iterator iterator()
217 {
218 return new ValuesIterator();
219 }
220
221 public boolean contains(Object o)
222 {
223 return AbstractAttributeMap.this.containsValue(o);
224 }
225
226 public boolean remove(Object o)
227 {
228 if (o == null)
229 {
230 return false;
231 }
232
233 for (Iterator it = iterator(); it.hasNext();)
234 {
235 if (o.equals(it.next()))
236 {
237 it.remove();
238 return true;
239 }
240 }
241
242 return false;
243 }
244 }
245
246 private class ValuesIterator extends KeyIterator
247 {
248 public Object next()
249 {
250 super.next();
251 return AbstractAttributeMap.this.get(_currentKey);
252 }
253 }
254
255 private class EntrySet extends KeySet
256 {
257 public Iterator iterator() {
258 return new EntryIterator();
259 }
260
261 public boolean contains(Object o) {
262 if (!(o instanceof Entry))
263 {
264 return false;
265 }
266
267 Entry entry = (Entry) o;
268 Object key = entry.getKey();
269 Object value = entry.getValue();
270 if (key == null || value == null)
271 {
272 return false;
273 }
274
275 return value.equals(AbstractAttributeMap.this.get(key));
276 }
277
278 public boolean remove(Object o) {
279 if (!(o instanceof Entry))
280 {
281 return false;
282 }
283
284 Entry entry = (Entry) o;
285 Object key = entry.getKey();
286 Object value = entry.getValue();
287 if (key == null || value == null
288 || !value.equals(AbstractAttributeMap.this.get(key)))
289 {
290 return false;
291 }
292
293 return AbstractAttributeMap.this.remove(((Entry) o).getKey()) != null;
294 }
295 }
296
297 /**
298 * Not very efficient since it generates a new instance of <code>Entry</code>
299 * for each element and still internaly uses the <code>KeyIterator</code>.
300 * It is more efficient to use the <code>KeyIterator</code> directly.
301 */
302 private class EntryIterator extends KeyIterator
303 {
304 public Object next()
305 {
306 super.next();
307 // Must create new Entry every time--value of the entry must stay
308 // linked to the same attribute name
309 return new EntrySetEntry(_currentKey);
310 }
311 }
312
313 private class EntrySetEntry implements Entry
314 {
315 private final Object _currentKey;
316
317 public EntrySetEntry(Object currentKey)
318 {
319 _currentKey = currentKey;
320 }
321
322 public Object getKey()
323 {
324 return _currentKey;
325 }
326
327 public Object getValue()
328 {
329 return AbstractAttributeMap.this.get(_currentKey);
330 }
331
332 public Object setValue(Object value)
333 {
334 return AbstractAttributeMap.this.put(_currentKey, value);
335 }
336 }
337 }