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