View Javadoc

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