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 javax.faces.component;
20  
21  import java.io.Serializable;
22  import java.util.AbstractCollection;
23  import java.util.AbstractSet;
24  import java.util.Collection;
25  import java.util.Iterator;
26  import java.util.Map;
27  import java.util.Set;
28  
29  /**
30   * @author Manfred Geiler (latest modification by $Author: lu4242 $)
31   * @version $Revision: 1297574 $ $Date: 2012-03-06 16:58:54 +0000 (Tue, 06 Mar 2012) $
32   */
33  class _ComponentFacetMap<V extends UIComponent> implements Map<String, V>, Serializable
34  {
35      private static final long serialVersionUID = -3456937594422167629L;
36      private UIComponent _component;
37      private Map<String, V> _map = new _ArrayMap<String, V>(0,5);
38      private Set<Entry<String, V>> _entrySet = null;
39      private Set<String> _keySet = null;
40      private Collection<V> _valueCollection = null;
41  
42      _ComponentFacetMap(UIComponent component)
43      {
44          _component = component;
45      }
46  
47      public int size()
48      {
49          return _map.size();
50      }
51  
52      public void clear()
53      {
54          UIComponent[] values = _map.values().toArray(new UIComponent[_map.size()]);
55          //remove all elements from underlying map
56          _map.clear();
57          //Set parent to null
58          for (int i = 0; i < values.length; i++)
59          {
60              values[i].setParent(null);
61          }
62      }
63  
64      public boolean isEmpty()
65      {
66          return _map.isEmpty();
67      }
68  
69      public boolean containsKey(Object key)
70      {
71          checkKey(key);
72          return _map.containsKey(key);
73      }
74  
75      public boolean containsValue(Object value)
76      {
77          checkValue(value);
78          return _map.containsValue(value);
79      }
80  
81      public Collection<V> values()
82      {
83          if (_valueCollection == null)
84          {
85              _valueCollection= new ComponentFacetValueCollection();
86          }
87          return _valueCollection;
88      }
89  
90      public void putAll(Map<? extends String, ? extends V> t)
91      {
92          for (Map.Entry<? extends String, ? extends V> entry : t.entrySet())
93          {
94              put(entry.getKey(), entry.getValue());
95          }
96      }
97  
98      public Set<Entry<String, V>> entrySet()
99      {
100         if (_entrySet == null)
101         {
102             _entrySet = new ComponentFacetEntrySet();
103         }
104         return _entrySet;
105     }
106 
107     public Set<String> keySet()
108     {
109         if (_keySet == null)
110         {
111             _keySet = new ComponentFacetKeySet();
112         }
113         return _keySet;
114     }
115 
116     public V get(Object key)
117     {
118         checkKey(key);
119         return _map.get(key);
120     }
121 
122     public V remove(Object key)
123     {
124         checkKey(key);
125         V facet = _map.remove(key);
126         if (facet != null)
127             facet.setParent(null);
128         return facet;
129     }
130 
131     public V put(String key, V value)
132     {
133         //checkKey(key);
134         if (key == null)
135             throw new NullPointerException("key");
136         //checkValue(value);
137         if (value == null)
138             throw new NullPointerException("value");
139         setNewParent(key, value);
140         V previousValue = _map.put(key, value);
141         if (previousValue != null)
142         {
143             previousValue.setParent(null);
144         }
145         return previousValue; 
146     }
147 
148     private void setNewParent(String facetName, UIComponent facet)
149     {
150         UIComponent oldParent = facet.getParent();
151         if (oldParent != null)
152         {
153             if (!oldParent.getChildren().remove(facet))
154             {
155                 // Check if the component is inside a facet and remove from there
156                 if (oldParent.getFacetCount() > 0)
157                 {
158                     for (Iterator< Map.Entry<String, UIComponent > > it = 
159                         oldParent.getFacets().entrySet().iterator() ; it.hasNext() ; )
160                     {
161                         Map.Entry<String, UIComponent > entry = it.next();
162                         
163                         if (entry.getValue().equals(facet))
164                         {
165                             it.remove();
166                             break;
167                         }
168                     }
169                 }
170             }
171         }
172         facet.setParent(_component);
173     }
174 
175     private void checkKey(Object key)
176     {
177         if (key == null)
178             throw new NullPointerException("key");
179         if (!(key instanceof String))
180             throw new ClassCastException("key is not a String");
181     }
182 
183     private void checkValue(Object value)
184     {
185         if (value == null)
186             throw new NullPointerException("value");
187         if (!(value instanceof UIComponent))
188             throw new ClassCastException("value is not a UIComponent");
189     }
190 
191     private class ComponentFacetEntrySet extends AbstractSet<Entry<String, V>>
192     {
193         public ComponentFacetEntrySet()
194         {
195         }
196         
197         public int size()
198         {
199             return _map.size();
200         }
201 
202         public boolean isEmpty()
203         {
204             return _map.isEmpty();
205         }
206 
207         public boolean contains(Object o)
208         {
209             return _map.entrySet().contains(o);
210         }
211 
212         public Iterator<java.util.Map.Entry<String, V>> iterator()
213         {
214             return new ComponentFacetEntryIterator(_map.entrySet().iterator());
215         }
216 
217         public Object[] toArray()
218         {
219             return _map.entrySet().toArray();
220         }
221 
222         public <T> T[] toArray(T[] a)
223         {
224             return _map.entrySet().toArray(a);
225         }
226 
227         public boolean add(java.util.Map.Entry<String, V> o)
228         {
229             // Add over the entry set is not allowed, because this should be done
230             // through the outer Map instance.
231             throw new UnsupportedOperationException();
232         }
233 
234         @SuppressWarnings("unchecked")
235         public boolean remove(Object o)
236         {
237             if (_map.entrySet().remove(o))
238             {
239                 if (o instanceof Map.Entry)
240                 {
241                     Object value = ((Map.Entry<String, V>) o).getValue();
242                     
243                     if (value != null && value instanceof UIComponent)
244                     {
245                         ((UIComponent) value).setParent(null);
246                     }
247                 }
248                 return true;
249             }
250             else
251             {
252                 return false;
253             }
254         }
255 
256         public boolean containsAll(Collection<?> c)
257         {
258             return _map.entrySet().containsAll(c);
259         }
260 
261         public boolean addAll(
262                 Collection<? extends java.util.Map.Entry<String, V>> c)
263         {
264             // Add over the entry set is not allowed, because this should be done
265             // through the outer Map instance.
266             throw new UnsupportedOperationException();
267         }
268 
269         @Override
270         public boolean equals(Object obj)
271         {
272             return _map.entrySet().equals(obj);
273         }
274 
275         @Override
276         public int hashCode()
277         {
278             return _map.entrySet().hashCode();
279         }
280 
281         @Override
282         public String toString()
283         {
284             return _map.entrySet().toString();
285         }
286     }
287     
288     private class ComponentFacetEntryIterator implements Iterator<Map.Entry<String, V>>
289     {
290         private Iterator<Map.Entry<String, V>> _delegate;
291         private V _currentEntryValue;
292         
293         public ComponentFacetEntryIterator(Iterator<Map.Entry<String, V>> it)
294         {
295             _delegate = it;
296             _currentEntryValue = null;
297         }
298         
299         public boolean hasNext()
300         {
301             return _delegate.hasNext();
302         }
303 
304         public java.util.Map.Entry<String, V> next()
305         {
306             java.util.Map.Entry<String, V> next = _delegate.next(); 
307             _currentEntryValue = next.getValue();
308             return new ComponentFacetEntry(next);
309         }
310 
311         public void remove()
312         {
313             _delegate.remove();
314             if (_currentEntryValue != null)
315             {
316                 _currentEntryValue.setParent(null);
317             }
318         }
319     }
320 
321     /**
322      * Wrapper used to override setValue() method
323      * 
324      */
325     private class ComponentFacetEntry implements Map.Entry<String, V>
326     {
327         private java.util.Map.Entry<String, V> _entry;
328         
329         public ComponentFacetEntry(java.util.Map.Entry<String, V> entry)
330         {
331             _entry = entry;
332         }
333 
334         public String getKey()
335         {
336             return _entry.getKey();
337         }
338 
339         public V getValue()
340         {
341             return _entry.getValue();
342         }
343 
344         public V setValue(V value)
345         {
346             setNewParent(_entry.getKey(), value);
347             V previousValue = _entry.setValue(value);
348             if (previousValue != null)
349             {
350                 previousValue.setParent(null);
351             }
352             return previousValue;
353         }
354 
355         @Override
356         public int hashCode()
357         {
358             return _entry.hashCode();
359         }
360 
361         @Override
362         public boolean equals(Object obj)
363         {
364             return _entry.equals(obj);
365         }
366 
367         @Override
368         public String toString()
369         {
370             return _entry.toString();
371         }
372     }
373     
374     private class ComponentFacetKeySet extends AbstractSet<String>
375     {
376 
377         public ComponentFacetKeySet()
378         {
379         }
380         
381         public int size()
382         {
383             return _map.keySet().size();
384         }
385 
386         public boolean isEmpty()
387         {
388             return _map.keySet().isEmpty();
389         }
390 
391         public boolean contains(Object o)
392         {
393             return _map.keySet().contains(o);
394         }
395 
396         public Iterator<String> iterator()
397         {
398             // Iterate over entrySet is equals to iterate over keySet, but
399             // in this case is better use entrySet iterator, because we can
400             // get the value directly and call setParent(null) if the entry is
401             // removed
402             return new ComponentFacetKeyIterator(_map.entrySet().iterator());
403         }
404 
405         public Object[] toArray()
406         {
407             return _map.keySet().toArray();
408         }
409 
410         public <T> T[] toArray(T[] a)
411         {
412             return _map.keySet().toArray(a);
413         }
414 
415         public boolean add(String o)
416         {
417             throw new UnsupportedOperationException();
418         }
419 
420         public boolean remove(Object o)
421         {
422             V previousValue = _map.get(o);
423             if (_map.keySet().remove(o))
424             {
425                 if (previousValue != null)
426                 {
427                     ((UIComponent) previousValue).setParent(null);
428                 }
429                 return true;
430             }
431             else
432             {
433                 return false;
434             }
435         }
436 
437         public boolean containsAll(Collection<?> c)
438         {
439             return _map.keySet().containsAll(c);
440         }
441 
442         public boolean addAll(Collection<? extends String> c)
443         {
444             throw new UnsupportedOperationException();
445         }
446 
447         @Override
448         public boolean equals(Object obj)
449         {
450             return _map.keySet().equals(obj);
451         }
452 
453         @Override
454         public int hashCode()
455         {
456             return _map.keySet().hashCode();
457         }
458 
459         @Override
460         public String toString()
461         {
462             return _map.keySet().toString();
463         }
464     }
465     
466     private class ComponentFacetKeyIterator implements Iterator<String>
467     {
468         private Iterator<Map.Entry<String, V>> _delegate;
469         private V _currentEntryValue;
470         
471         public ComponentFacetKeyIterator(Iterator<Map.Entry<String, V>> it)
472         {
473             _delegate = it;
474             _currentEntryValue = null;
475         }
476         
477         public boolean hasNext()
478         {
479             return _delegate.hasNext();
480         }
481 
482         public String next()
483         {
484             java.util.Map.Entry<String, V> next = _delegate.next(); 
485             _currentEntryValue = next.getValue();
486             return next.getKey();
487         }
488 
489         public void remove()
490         {
491             _delegate.remove();
492             if (_currentEntryValue != null)
493             {
494                 _currentEntryValue.setParent(null);
495             }
496         }
497     }
498 
499     private class ComponentFacetValueCollection extends AbstractCollection<V>
500     {
501         public ComponentFacetValueCollection()
502         {
503         }
504 
505         public int size()
506         {
507             return _map.values().size();
508         }
509 
510         public boolean isEmpty()
511         {
512             return _map.values().isEmpty();
513         }
514 
515         public boolean contains(Object o)
516         {
517             return _map.values().contains(o);
518         }
519 
520         public Iterator<V> iterator()
521         {
522             return new ComponentFacetValueIterator(_map.entrySet().iterator());
523         }
524 
525         public Object[] toArray()
526         {
527             return _map.values().toArray();
528         }
529 
530         public <T> T[] toArray(T[] a)
531         {
532             return _map.values().toArray(a);
533         }
534 
535         public boolean add(V o)
536         {
537             // Add over the entry set is not allowed, because this should be done
538             // through the outer Map instance.
539             throw new UnsupportedOperationException();
540         }
541 
542         public boolean containsAll(Collection<?> c)
543         {
544             return _map.values().containsAll(c);
545         }
546 
547         public boolean addAll(Collection<? extends V> c)
548         {
549             // Add over the entry set is not allowed, because this should be done
550             // through the outer Map instance.
551             throw new UnsupportedOperationException();
552         }
553 
554         @Override
555         public boolean equals(Object obj)
556         {
557             return _map.values().equals(obj);
558         }
559 
560         @Override
561         public int hashCode()
562         {
563             return _map.values().hashCode();
564         }
565 
566         @Override
567         public String toString()
568         {
569             return _map.values().toString();
570         }
571     }
572     
573     private class ComponentFacetValueIterator implements Iterator<V>
574     {
575         private Iterator<Map.Entry<String, V>> _delegate;
576         private V _currentEntryValue;
577         
578         public ComponentFacetValueIterator(Iterator<Map.Entry<String, V>> it)
579         {
580             _delegate = it;
581             _currentEntryValue = null;
582         }
583         
584         public boolean hasNext()
585         {
586             return _delegate.hasNext();
587         }
588 
589         public V next()
590         {
591             java.util.Map.Entry<String, V> next = _delegate.next(); 
592             _currentEntryValue = next.getValue();
593             return next.getValue();
594         }
595 
596         public void remove()
597         {
598             _delegate.remove();
599             if (_currentEntryValue != null)
600             {
601                 _currentEntryValue.setParent(null);
602             }
603         }
604     }
605 }