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