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.behavior;
20  
21  import java.util.ArrayList;
22  import java.util.Collection;
23  import java.util.Iterator;
24  import java.util.List;
25  import java.util.ListIterator;
26  
27  import javax.faces.component.PartialStateHolder;
28  import javax.faces.component.StateHolder;
29  import javax.faces.component.UIComponentBase;
30  import javax.faces.context.FacesContext;
31  
32  /**
33   * This class handle deltas on facesListener and validatorList.
34   * 
35   * It is only used by this methods on UIComponentBase:
36   * 
37   * addFacesListener
38   * broadcast
39   * getFacesListeners
40   * removeFacesListener
41   * 
42   * A facesListener could hold PartialStateHolder instances, so it 
43   * is necessary to provide convenient methods to track deltas.
44   * 
45   * @author Leonardo Uribe (latest modification by $Author: bommel $)
46   * @version $Revision: 1187700 $ $Date: 2011-10-22 07:19:37 -0500 (Sat, 22 Oct 2011) $
47   */
48  class _DeltaList<T> implements List<T>, PartialStateHolder
49  {
50  
51      private List<T> _delegate;
52      private boolean _initialStateMarked;
53      
54      public _DeltaList()
55      {
56      }
57      
58      public _DeltaList(List<T> delegate)
59      {
60          _delegate = delegate;
61      }
62      
63      public void add(int index, T element)
64      {
65          clearInitialState();
66          _delegate.add(index, element);
67      }
68  
69      public boolean add(T e)
70      {
71          clearInitialState();
72          return _delegate.add(e);
73      }
74  
75      public boolean addAll(Collection<? extends T> c)
76      {
77          clearInitialState();
78          return _delegate.addAll(c);
79      }
80  
81      public boolean addAll(int index, Collection<? extends T> c)
82      {
83          clearInitialState();
84          return _delegate.addAll(index, c);
85      }
86  
87      public void clear()
88      {
89          clearInitialState();
90          _delegate.clear();
91      }
92  
93      public boolean contains(Object o)
94      {
95          return _delegate.contains(o);
96      }
97  
98      public boolean containsAll(Collection<?> c)
99      {
100         return _delegate.containsAll(c);
101     }
102 
103     public boolean equals(Object o)
104     {
105         return _delegate.equals(o);
106     }
107 
108     public T get(int index)
109     {
110         return _delegate.get(index);
111     }
112 
113     public int hashCode()
114     {
115         return _delegate.hashCode();
116     }
117 
118     public int indexOf(Object o)
119     {
120         return _delegate.indexOf(o);
121     }
122 
123     public boolean isEmpty()
124     {
125         return _delegate.isEmpty();
126     }
127 
128     public Iterator<T> iterator()
129     {
130         return _delegate.iterator();
131     }
132 
133     public int lastIndexOf(Object o)
134     {
135         return _delegate.lastIndexOf(o);
136     }
137 
138     public ListIterator<T> listIterator()
139     {
140         return _delegate.listIterator();
141     }
142 
143     public ListIterator<T> listIterator(int index)
144     {
145         return _delegate.listIterator(index);
146     }
147 
148     public T remove(int index)
149     {
150         clearInitialState();
151         return _delegate.remove(index);
152     }
153 
154     public boolean remove(Object o)
155     {
156         clearInitialState();
157         return _delegate.remove(o);
158     }
159 
160     public boolean removeAll(Collection<?> c)
161     {
162         clearInitialState();
163         return _delegate.removeAll(c);
164     }
165 
166     public boolean retainAll(Collection<?> c)
167     {
168         clearInitialState();
169         return _delegate.retainAll(c);
170     }
171 
172     public T set(int index, T element)
173     {
174         clearInitialState();
175         return _delegate.set(index, element);
176     }
177 
178     public int size()
179     {
180         return _delegate == null ? 0 : _delegate.size();
181     }
182 
183     public List<T> subList(int fromIndex, int toIndex)
184     {
185         return _delegate.subList(fromIndex, toIndex);
186     }
187 
188     public Object[] toArray()
189     {
190         return _delegate.toArray();
191     }
192 
193     public <T> T[] toArray(T[] a)
194     {
195         return _delegate.toArray(a);
196     }
197 
198     public boolean isTransient()
199     {
200         return false;
201     }
202 
203     public void setTransient(boolean newTransientValue)
204     {
205         throw new UnsupportedOperationException();
206     }
207 
208     public void restoreState(FacesContext context, Object state)
209     {
210         if (state == null)
211         {
212             return;
213         }
214         
215         if (initialStateMarked())
216         {            
217             //Restore delta
218             Object[] lst = (Object[]) state;
219             int j = 0;
220             int i = 0;
221             while (i < lst.length)
222             {
223                 if (lst[i] instanceof _AttachedDeltaWrapper)
224                 {
225                     //Delta
226                     ((StateHolder)_delegate.get(j)).restoreState(context, ((_AttachedDeltaWrapper) lst[i]).getWrappedStateObject());
227                     j++;
228                 }
229                 else if (lst[i] != null)
230                 {
231                     //Full
232                     _delegate.set(j, (T) UIComponentBase.restoreAttachedState(context, lst[i]));
233                     j++;
234                 }
235                 else
236                 {
237                     _delegate.remove(j);
238                 }
239                 i++;
240             }
241             if (i != j)
242             {
243                 // StateHolder transient objects found, next time save and restore it fully
244                 //because the size of the list changes.
245                 clearInitialState();
246             }
247         }
248         else
249         {
250             //Restore delegate
251             Object[] lst = (Object[]) state;
252             _delegate = new ArrayList<T>(lst.length);
253             for (int i = 0; i < lst.length; i++)
254             {
255                 T value = (T) UIComponentBase.restoreAttachedState(context, lst[i]);
256                 if (value != null)
257                 {
258                     _delegate.add(value);
259                 }
260             }
261         }
262     }
263 
264     public Object saveState(FacesContext context)
265     {
266         if (initialStateMarked())
267         {
268             Object [] lst = new Object[_delegate.size()];
269             boolean nullDelta = true;
270             for (int i = 0; i < _delegate.size(); i++)
271             {
272                 Object value = _delegate.get(i);
273                 if (value instanceof PartialStateHolder)
274                 {
275                     //Delta
276                     PartialStateHolder holder = (PartialStateHolder) value;
277                     if (!holder.isTransient())
278                     {
279                         Object attachedState = holder.saveState(context);
280                         if (attachedState != null)
281                         {
282                             nullDelta = false;
283                         }
284                         lst[i] = new _AttachedDeltaWrapper(value.getClass(),
285                             attachedState);
286                     }
287                 }
288                 else
289                 {
290                     //Full
291                     lst[i] = UIComponentBase.saveAttachedState(context, value);
292                     if (value instanceof StateHolder || value instanceof List)
293                     {
294                         nullDelta = false;
295                     }
296                 }
297             }
298             if (nullDelta)
299             {
300                 return null;
301             }
302             return lst;
303         }
304         else
305         {
306             Object [] lst = new Object[_delegate.size()];
307             for (int i = 0; i < _delegate.size(); i++)
308             {
309                 lst[i] = UIComponentBase.saveAttachedState(context, _delegate.get(i));
310             }
311             return lst;
312         }
313     }
314 
315     public void clearInitialState()
316     {
317         //Reset delta setting to null
318         if (_initialStateMarked)
319         {
320             _initialStateMarked = false;
321             if (_delegate != null)
322             {
323                 for (T value : _delegate)
324                 {
325                     if (value instanceof PartialStateHolder)
326                     {
327                         ((PartialStateHolder)value).clearInitialState();
328                     }
329                 }
330             }
331         }
332     }
333 
334     public boolean initialStateMarked()
335     {
336         return _initialStateMarked;
337     }
338 
339     public void markInitialState()
340     {
341         _initialStateMarked = true;
342         if (_delegate != null)
343         {
344             int size = _delegate.size();
345             for (int i = 0; i < size; i++)
346             {
347                 T value = _delegate.get(i);
348                 if (value instanceof PartialStateHolder)
349                 {
350                     ((PartialStateHolder)value).markInitialState();
351                 }
352             }
353         }
354     }
355 }