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