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