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: 1296362 $ $Date: 2012-03-02 13:27:53 -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, ((_AttachedDeltaWrapper) lst[i]).getWrappedStateObject());
225                     j++;
226                 }
227                 else if (lst[i] != null)
228                 {
229                     //Full
230                     _delegate.set(j, (T) UIComponentBase.restoreAttachedState(context, lst[i]));
231                     j++;
232                 }
233                 else
234                 {
235                     _delegate.remove(j);
236                 }
237                 i++;
238             }
239             if (i != j)
240             {
241                 // StateHolder transient objects found, next time save and restore it fully
242                 //because the size of the list changes.
243                 clearInitialState();
244             }
245         }
246         else
247         {
248             //Restore delegate
249             Object[] lst = (Object[]) state;
250             _delegate = new ArrayList<T>(lst.length);
251             for (int i = 0; i < lst.length; i++)
252             {
253                 T value = (T) UIComponentBase.restoreAttachedState(context, lst[i]);
254                 if (value != null)
255                 {
256                     _delegate.add(value);
257                 }
258             }
259         }
260     }
261 
262     public Object saveState(FacesContext context)
263     {
264         if (initialStateMarked())
265         {
266             Object [] lst = new Object[_delegate.size()];
267             boolean nullDelta = true;
268             for (int i = 0; i < _delegate.size(); i++)
269             {
270                 Object value = _delegate.get(i);
271                 if (value instanceof PartialStateHolder)
272                 {
273                     //Delta
274                     PartialStateHolder holder = (PartialStateHolder) value;
275                     if (!holder.isTransient())
276                     {
277                         Object attachedState = holder.saveState(context);
278                         if (attachedState != null)
279                         {
280                             nullDelta = false;
281                         }
282                         lst[i] = new _AttachedDeltaWrapper(value.getClass(),
283                             attachedState);
284                     }
285                 }
286                 else
287                 {
288                     //Full
289                     lst[i] = UIComponentBase.saveAttachedState(context, value);
290                     if (value instanceof StateHolder || value instanceof List)
291                     {
292                         nullDelta = false;
293                     }
294                 }
295             }
296             if (nullDelta)
297             {
298                 return null;
299             }
300             return lst;
301         }
302         else
303         {
304             Object [] lst = new Object[_delegate.size()];
305             for (int i = 0; i < _delegate.size(); i++)
306             {
307                 lst[i] = UIComponentBase.saveAttachedState(context, _delegate.get(i));
308             }
309             return lst;
310         }
311     }
312 
313     public void clearInitialState()
314     {
315         //Reset delta setting to null
316         if (_initialStateMarked)
317         {
318             _initialStateMarked = false;
319             if (_delegate != null)
320             {
321                 for (T value : _delegate)
322                 {
323                     if (value instanceof PartialStateHolder)
324                     {
325                         ((PartialStateHolder)value).clearInitialState();
326                     }
327                 }
328             }
329         }
330     }
331 
332     public boolean initialStateMarked()
333     {
334         return _initialStateMarked;
335     }
336 
337     public void markInitialState()
338     {
339         _initialStateMarked = true;
340         if (_delegate != null)
341         {
342             int size = _delegate.size();
343             for (int i = 0; i < size; i++)
344             {
345                 T value = _delegate.get(i);
346                 if (value instanceof PartialStateHolder)
347                 {
348                     ((PartialStateHolder)value).markInitialState();
349                 }
350             }
351         }
352     }
353 }