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 org.apache.myfaces.view.facelets.component;
20  
21  import java.io.IOException;
22  import java.io.Serializable;
23  import java.sql.ResultSet;
24  import java.util.ArrayList;
25  import java.util.Collection;
26  import java.util.Collections;
27  import java.util.HashMap;
28  import java.util.Iterator;
29  import java.util.List;
30  import java.util.Map;
31  
32  import javax.el.ValueExpression;
33  import javax.faces.FacesException;
34  import javax.faces.application.FacesMessage;
35  import javax.faces.component.ContextCallback;
36  import javax.faces.component.EditableValueHolder;
37  import javax.faces.component.NamingContainer;
38  import javax.faces.component.UIComponent;
39  import javax.faces.component.UIComponentBase;
40  import javax.faces.component.visit.VisitCallback;
41  import javax.faces.component.visit.VisitContext;
42  import javax.faces.component.visit.VisitHint;
43  import javax.faces.component.visit.VisitResult;
44  import javax.faces.context.FacesContext;
45  import javax.faces.event.AbortProcessingException;
46  import javax.faces.event.FacesEvent;
47  import javax.faces.event.FacesListener;
48  import javax.faces.event.PhaseId;
49  import javax.faces.model.ArrayDataModel;
50  import javax.faces.model.CollectionDataModel;
51  import javax.faces.model.DataModel;
52  import javax.faces.model.IterableDataModel;
53  import javax.faces.model.ListDataModel;
54  import javax.faces.model.ResultSetDataModel;
55  import javax.faces.model.ScalarDataModel;
56  import javax.faces.render.Renderer;
57  
58  import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFComponent;
59  import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFProperty;
60  import org.apache.myfaces.cdi.model.DataModelBuilderProxy;
61  import org.apache.myfaces.shared.renderkit.html.util.SharedStringBuilder;
62  import org.apache.myfaces.util.ExternalSpecifications;
63  
64  /**
65   *  
66   */
67  @JSFComponent(name="ui:repeat", defaultRendererType="facelets.ui.Repeat")
68  public class UIRepeat extends UIComponentBase implements NamingContainer
69  {
70      public static final String COMPONENT_TYPE = "facelets.ui.Repeat";
71  
72      public static final String COMPONENT_FAMILY = "facelets";
73      
74      private static final String STRING_BUILDER_KEY
75              = UIRepeat.class.getName() + ".SHARED_STRING_BUILDER";
76  
77      private final static DataModel<?> EMPTY_MODEL = new ListDataModel<Object>(Collections.emptyList());
78      
79      private static final Class<Object[]> OBJECT_ARRAY_CLASS = Object[].class;
80  
81      private static final Object[] LEAF_NO_STATE = new Object[]{null,null};
82      
83      private Object _initialDescendantComponentState = null;
84  
85      // Holds for each row the states of the child components of this UIData.
86      // Note that only "partial" component state is saved: the component fields
87      // that are expected to vary between rows.
88      private Map<String, Collection<Object[]>> _rowStates = new HashMap<String, Collection<Object[]>>();
89      
90      /**
91       * Handle case where this table is nested inside another table. See method getDataModel for more details.
92       * <p>
93       * Key: parentClientId (aka rowId when nested within a parent table) Value: DataModel
94       */
95      private Map<String, DataModel> _dataModelMap = new HashMap<String, DataModel>();
96      
97      // will be set to false if the data should not be refreshed at the beginning of the encode phase
98      private boolean _isValidChilds = true;
99      
100     private boolean _emptyModel = false;
101 
102     private int _end = -1;
103     
104     private int _count;
105     
106     private int _index = -1;
107 
108     private transient Object _origValue;
109     private transient Object _origVarStatus;
110 
111     private transient FacesContext _facesContext;
112     
113     static final Integer RESET_MODE_OFF = 0;
114     static final Integer RESET_MODE_SOFT = 1;
115     static final Integer RESET_MODE_HARD = 2;    
116     
117     public UIRepeat()
118     {
119         setRendererType("facelets.ui.Repeat");
120     }
121 
122     @Override
123     public String getFamily()
124     {
125         return COMPONENT_FAMILY;
126     }
127     
128     @JSFProperty
129     public int getOffset()
130     {
131         return (Integer) getStateHelper().eval(PropertyKeys.offset, 0);
132     }
133 
134     public void setOffset(int offset)
135     {
136         getStateHelper().put(PropertyKeys.offset, offset );
137     }
138     
139     @JSFProperty
140     public int getSize()
141     {
142         return (Integer) getStateHelper().eval(PropertyKeys.size, -1);
143     }
144 
145     public void setSize(int size)
146     {
147         getStateHelper().put(PropertyKeys.size, size );
148     }
149     
150     @JSFProperty
151     public int getStep()
152     {
153         return (Integer) getStateHelper().eval(PropertyKeys.step, 1);
154     }
155 
156     public void setStep(int step)
157     {
158         getStateHelper().put(PropertyKeys.step, step );
159     }
160     
161     @JSFProperty
162     public int getBegin()
163     {
164         return (Integer) getStateHelper().eval(PropertyKeys.begin, -1);
165     }
166 
167     public void setBegin(int begin)
168     {
169         getStateHelper().put(PropertyKeys.begin, begin );
170     }
171     
172     @JSFProperty
173     public int getEnd()
174     {
175         return (Integer) getStateHelper().eval(PropertyKeys.end, -1);
176     }
177 
178     public void setEnd(int end)
179     {
180         getStateHelper().put(PropertyKeys.end, end );
181     }
182     
183     @JSFProperty(literalOnly=true)
184     public String getVar()
185     {
186         return (String) getStateHelper().get(PropertyKeys.var);
187     }
188 
189     public void setVar(String var)
190     {
191         getStateHelper().put(PropertyKeys.var, var );
192     }
193     
194     @JSFProperty(literalOnly=true)
195     public String getVarStatus ()
196     {
197         return (String) getStateHelper().get(PropertyKeys.varStatus);
198     }
199     
200     public void setVarStatus (String varStatus)
201     {
202         getStateHelper().put(PropertyKeys.varStatus, varStatus );
203     }
204     
205     protected DataModel getDataModel()
206     {
207         DataModel dataModel;
208         String clientID = "";
209 
210         UIComponent parent = getParent();
211         if (parent != null)
212         {
213             clientID = parent.getContainerClientId(getFacesContext());
214         }
215         dataModel = _dataModelMap.get(clientID);
216         if (dataModel == null)
217         {
218             dataModel = createDataModel();
219             _dataModelMap.put(clientID, dataModel);
220         }
221         return dataModel;
222     }
223     
224     private DataModel createDataModel()
225     {
226         Object value = getValue();
227 
228         if (value == null)
229         {
230             return EMPTY_MODEL;
231         }
232         else if (value instanceof DataModel)
233         {
234             return (DataModel) value;
235         }
236         else
237         {
238             DataModel dataModel = null;
239             if (ExternalSpecifications.isCDIAvailable(getFacesContext().getExternalContext()))
240             {
241                 dataModel = (new DataModelBuilderProxy()).createDataModel(
242                         getFacesContext(), value.getClass(), value);
243             }
244             if (dataModel == null)
245             {
246                 if (value instanceof List)
247                 {
248                     return new ListDataModel((List<?>) value);
249                 }
250                 else if (OBJECT_ARRAY_CLASS.isAssignableFrom(value.getClass()))
251                 {
252                     return new ArrayDataModel((Object[]) value);
253                 }
254                 else if (value instanceof ResultSet)
255                 {
256                     return new ResultSetDataModel((ResultSet) value);
257                 }
258                 else if (value instanceof Iterable)
259                 {
260                     return new IterableDataModel<>((Iterable<?>) value);
261                 } 
262                 else if (value instanceof Map) 
263                 {
264                     return new IterableDataModel<>(((Map<?, ?>) value).entrySet());
265                 }
266                 else if (value instanceof Collection)
267                 {
268                     return new CollectionDataModel((Collection) value);
269                 }
270                 else
271                 {
272                     return new ScalarDataModel(value);
273                 }
274             }
275             else
276             {
277                 return dataModel;
278             }
279         }
280     }
281     
282     @Override
283     public void setValueExpression(String name, ValueExpression binding)
284     {
285         if (name == null)
286         {
287             throw new NullPointerException("name");
288         }
289         else if (name.equals("value"))
290         {
291             _dataModelMap.clear();
292         }
293         else if (name.equals("rowIndex"))
294         {
295             throw new IllegalArgumentException("name " + name);
296         }
297         super.setValueExpression(name, binding);
298     }
299     
300     @JSFProperty
301     public Object getValue()
302     {
303         return  getStateHelper().eval(PropertyKeys.value);
304     }
305 
306     public void setValue(Object value)
307     {
308         getStateHelper().put(PropertyKeys.value, value);
309         _dataModelMap.clear();
310         _rowStates.clear();
311         _isValidChilds = true;
312     }
313 
314     @Override
315     public String getContainerClientId(FacesContext context)
316     {
317         //MYFACES-2744 UIData.getClientId() should not append rowIndex, instead use UIData.getContainerClientId()
318         String clientId = super.getContainerClientId(context);
319         
320         int index = getIndex();
321         if (index == -1)
322         {
323             return clientId;
324         }
325 
326         StringBuilder sb = SharedStringBuilder.get(context, STRING_BUILDER_KEY);
327         return sb.append(clientId).append(context.getNamingContainerSeparatorChar()).append(index).toString();
328     }
329     
330     private RepeatStatus _getRepeatStatus()
331     {
332         int begin = getBegin();
333         if (begin == -1) 
334         {
335             begin = getOffset();
336         }
337         
338         return new RepeatStatus(_count == 0, _index + getStep() >= getRowCount(),
339             _count, _index, begin, _end, getStep());
340         
341     }
342 
343     private void _captureScopeValues()
344     {
345         String var = getVar();
346         if (var != null)
347         {
348             _origValue = getFacesContext().getExternalContext().getRequestMap().get(var);
349         }
350         String varStatus = getVarStatus();
351         if (varStatus != null)
352         {
353             _origVarStatus = getFacesContext().getExternalContext().getRequestMap().get(varStatus);
354         }
355     }
356 
357     private boolean _isIndexAvailable()
358     {
359         return _emptyModel || getDataModel().isRowAvailable();
360     }
361 
362     private void _restoreScopeValues()
363     {
364         String var = getVar();
365         if (var != null)
366         {
367             Map<String, Object> attrs = getFacesContext().getExternalContext().getRequestMap();
368             if (_origValue != null)
369             {
370                 attrs.put(var, _origValue);
371                 _origValue = null;
372             }
373             else
374             {
375                 attrs.remove(var);
376             }
377         }
378         String varStatus = getVarStatus();
379         if (getVarStatus() != null)
380         {
381             Map<String, Object> attrs = getFacesContext().getExternalContext().getRequestMap();
382             if (_origVarStatus != null)
383             {
384                 attrs.put(varStatus, _origVarStatus);
385                 _origVarStatus = null;
386             }
387             else
388             {
389                 attrs.remove(varStatus);
390             }
391         }
392     }
393     
394     /**
395      * Overwrite the state of the child components of this component with data previously saved by method
396      * saveDescendantComponentStates.
397      * <p>
398      * The saved state info only covers those fields that are expected to vary between rows of a table. 
399      * Other fields are not modified.
400      */
401     @SuppressWarnings("unchecked")
402     private void restoreDescendantComponentStates(UIComponent parent, boolean iterateFacets, Object state,
403                                                   boolean restoreChildFacets)
404     {
405         int descendantStateIndex = -1;
406         List<? extends Object[]> stateCollection = null;
407         
408         if (iterateFacets && parent.getFacetCount() > 0)
409         {
410             Iterator<UIComponent> childIterator = parent.getFacets().values().iterator();
411             
412             while (childIterator.hasNext())
413             {
414                 UIComponent component = childIterator.next();
415 
416                 // reset the client id (see spec 3.1.6)
417                 component.setId(component.getId());
418                 if (!component.isTransient())
419                 {
420                     if (descendantStateIndex == -1)
421                     {
422                         stateCollection = ((List<? extends Object[]>) state);
423                         descendantStateIndex = stateCollection.isEmpty() ? -1 : 0;
424                     }
425                     
426                     if (descendantStateIndex != -1 && descendantStateIndex < stateCollection.size())
427                     {
428                         Object[] object = stateCollection.get(descendantStateIndex);
429                         if (object[0] != null && component instanceof EditableValueHolder)
430                         {
431                             ((SavedState) object[0]).restoreState((EditableValueHolder) component);
432                         }
433                         // If there is descendant state to restore, call it recursively, otherwise
434                         // it is safe to skip iteration.
435                         if (object[1] != null)
436                         {
437                             restoreDescendantComponentStates(component, restoreChildFacets, object[1], true);
438                         }
439                         else
440                         {
441                             restoreDescendantComponentWithoutRestoreState(component, restoreChildFacets, true);
442                         }
443                     }
444                     else
445                     {
446                         restoreDescendantComponentWithoutRestoreState(component, restoreChildFacets, true);
447                     }
448                     descendantStateIndex++;
449                 }
450             }
451         }
452         
453         if (parent.getChildCount() > 0)
454         {
455             for (int i = 0; i < parent.getChildCount(); i++)
456             {
457                 UIComponent component = parent.getChildren().get(i);
458 
459                 // reset the client id (see spec 3.1.6)
460                 component.setId(component.getId());
461                 if (!component.isTransient())
462                 {
463                     if (descendantStateIndex == -1)
464                     {
465                         stateCollection = ((List<? extends Object[]>) state);
466                         descendantStateIndex = stateCollection.isEmpty() ? -1 : 0;
467                     }
468                     
469                     if (descendantStateIndex != -1 && descendantStateIndex < stateCollection.size())
470                     {
471                         Object[] object = stateCollection.get(descendantStateIndex);
472                         if (object[0] != null && component instanceof EditableValueHolder)
473                         {
474                             ((SavedState) object[0]).restoreState((EditableValueHolder) component);
475                         }
476                         // If there is descendant state to restore, call it recursively, otherwise
477                         // it is safe to skip iteration.
478                         if (object[1] != null)
479                         {
480                             restoreDescendantComponentStates(component, restoreChildFacets, object[1], true);
481                         }
482                         else
483                         {
484                             restoreDescendantComponentWithoutRestoreState(component, restoreChildFacets, true);
485                         }
486                     }
487                     else
488                     {
489                         restoreDescendantComponentWithoutRestoreState(component, restoreChildFacets, true);
490                     }
491                     descendantStateIndex++;
492                 }
493             }
494         }
495     }
496 
497     /**
498      * Just call component.setId(component.getId()) to reset all client ids and 
499      * ensure they will be calculated for the current row, but do not waste time
500      * dealing with row state code.
501      * 
502      * @param parent
503      * @param iterateFacets
504      * @param restoreChildFacets 
505      */
506     private void restoreDescendantComponentWithoutRestoreState(UIComponent parent, boolean iterateFacets,
507                                                                boolean restoreChildFacets)
508     {
509         if (iterateFacets && parent.getFacetCount() > 0)
510         {
511             Iterator<UIComponent> childIterator = parent.getFacets().values().iterator();
512             
513             while (childIterator.hasNext())
514             {
515                 UIComponent component = childIterator.next();
516 
517                 // reset the client id (see spec 3.1.6)
518                 component.setId(component.getId());
519                 if (!component.isTransient())
520                 {
521                     restoreDescendantComponentWithoutRestoreState(component, restoreChildFacets, true);
522                 }
523             }
524         }
525         
526         if (parent.getChildCount() > 0)
527         {
528             for (int i = 0; i < parent.getChildCount(); i++)
529             {
530                 UIComponent component = parent.getChildren().get(i);
531 
532                 // reset the client id (see spec 3.1.6)
533                 component.setId(component.getId());
534                 if (!component.isTransient())
535                 {
536                     restoreDescendantComponentWithoutRestoreState(component, restoreChildFacets, true);
537                 }
538             }
539         }
540     }
541 
542     /**
543      * Walk the tree of child components of this UIData, saving the parts of their state that can vary between rows.
544      * <p>
545      * This is very similar to the process that occurs for normal components when the view is serialized. Transient
546      * components are skipped (no state is saved for them).
547      * <p>
548      * If there are no children then null is returned. If there are one or more children, and all children are transient
549      * then an empty collection is returned; this will happen whenever a table contains only read-only components.
550      * <p>
551      * Otherwise a collection is returned which contains an object for every non-transient child component; that object
552      * may itself contain a collection of the state of that child's child components.
553      */
554     private Collection<Object[]> saveDescendantComponentStates(UIComponent parent, boolean iterateFacets,
555                                                                boolean saveChildFacets)
556     {
557         Collection<Object[]> childStates = null;
558         // Index to indicate how many components has been passed without state to save.
559         int childEmptyIndex = 0;
560         int totalChildCount = 0;
561                 
562         if (iterateFacets && parent.getFacetCount() > 0)
563         {
564             Iterator<UIComponent> childIterator = parent.getFacets().values().iterator();
565 
566             while (childIterator.hasNext())
567             {
568                 UIComponent child = childIterator.next();
569                 if (!child.isTransient())
570                 {
571                     // Add an entry to the collection, being an array of two
572                     // elements. The first element is the state of the children
573                     // of this component; the second is the state of the current
574                     // child itself.
575 
576                     if (child instanceof EditableValueHolder)
577                     {
578                         if (childStates == null)
579                         {
580                             childStates = new ArrayList<Object[]>(
581                                     parent.getFacetCount()
582                                     + parent.getChildCount()
583                                     - totalChildCount
584                                     + childEmptyIndex);
585                             for (int ci = 0; ci < childEmptyIndex; ci++)
586                             {
587                                 childStates.add(LEAF_NO_STATE);
588                             }
589                         }
590                     
591                         childStates.add(child.getChildCount() > 0 ? 
592                                 new Object[]{new SavedState((EditableValueHolder) child),
593                                     saveDescendantComponentStates(child, saveChildFacets, true)} :
594                                 new Object[]{new SavedState((EditableValueHolder) child),
595                                     null});
596                     }
597                     else if (child.getChildCount() > 0 || (saveChildFacets && child.getFacetCount() > 0))
598                     {
599                         Object descendantSavedState = saveDescendantComponentStates(child, saveChildFacets, true);
600                         
601                         if (descendantSavedState == null)
602                         {
603                             if (childStates == null)
604                             {
605                                 childEmptyIndex++;
606                             }
607                             else
608                             {
609                                 childStates.add(LEAF_NO_STATE);
610                             }
611                         }
612                         else
613                         {
614                             if (childStates == null)
615                             {
616                                 childStates = new ArrayList<Object[]>(
617                                         parent.getFacetCount()
618                                         + parent.getChildCount()
619                                         - totalChildCount
620                                         + childEmptyIndex);
621                                 for (int ci = 0; ci < childEmptyIndex; ci++)
622                                 {
623                                     childStates.add(LEAF_NO_STATE);
624                                 }
625                             }
626                             childStates.add(new Object[]{null, descendantSavedState});
627                         }
628                     }
629                     else
630                     {
631                         if (childStates == null)
632                         {
633                             childEmptyIndex++;
634                         }
635                         else
636                         {
637                             childStates.add(LEAF_NO_STATE);
638                         }
639                     }
640                 }
641                 totalChildCount++;
642             }
643         }
644         
645         if (parent.getChildCount() > 0)
646         {
647             for (int i = 0; i < parent.getChildCount(); i++)
648             {
649                 UIComponent child = parent.getChildren().get(i);
650                 if (!child.isTransient())
651                 {
652                     // Add an entry to the collection, being an array of two
653                     // elements. The first element is the state of the children
654                     // of this component; the second is the state of the current
655                     // child itself.
656 
657                     if (child instanceof EditableValueHolder)
658                     {
659                         if (childStates == null)
660                         {
661                             childStates = new ArrayList<Object[]>(
662                                     parent.getFacetCount()
663                                     + parent.getChildCount()
664                                     - totalChildCount
665                                     + childEmptyIndex);
666                             for (int ci = 0; ci < childEmptyIndex; ci++)
667                             {
668                                 childStates.add(LEAF_NO_STATE);
669                             }
670                         }
671                     
672                         childStates.add(child.getChildCount() > 0 ? 
673                                 new Object[]{new SavedState((EditableValueHolder) child),
674                                     saveDescendantComponentStates(child, saveChildFacets, true)} :
675                                 new Object[]{new SavedState((EditableValueHolder) child),
676                                     null});
677                     }
678                     else if (child.getChildCount() > 0 || (saveChildFacets && child.getFacetCount() > 0))
679                     {
680                         Object descendantSavedState = saveDescendantComponentStates(child, saveChildFacets, true);
681                         
682                         if (descendantSavedState == null)
683                         {
684                             if (childStates == null)
685                             {
686                                 childEmptyIndex++;
687                             }
688                             else
689                             {
690                                 childStates.add(LEAF_NO_STATE);
691                             }
692                         }
693                         else
694                         {
695                             if (childStates == null)
696                             {
697                                 childStates = new ArrayList<Object[]>(
698                                         parent.getFacetCount()
699                                         + parent.getChildCount()
700                                         - totalChildCount
701                                         + childEmptyIndex);
702                                 for (int ci = 0; ci < childEmptyIndex; ci++)
703                                 {
704                                     childStates.add(LEAF_NO_STATE);
705                                 }
706                             }
707                             childStates.add(new Object[]{null, descendantSavedState});
708                         }
709                     }
710                     else
711                     {
712                         if (childStates == null)
713                         {
714                             childEmptyIndex++;
715                         }
716                         else
717                         {
718                             childStates.add(LEAF_NO_STATE);
719                         }
720                     }
721                 }
722                 totalChildCount++;
723             }
724         }
725         
726         return childStates;
727     }
728     
729     /**
730      * Returns the rowCount of the underlying DataModel.
731      * @return
732      */
733     public int getRowCount()
734     {
735         if (_emptyModel) // empty model
736         {
737             return (getEnd() - getBegin())/(getStep() <= 0 ? 1 : getStep());
738         }
739         else 
740         {
741             return getDataModel().getRowCount();
742         }
743     }
744     
745     /**
746      * Returns the current index.
747      */
748     public int getIndex()
749     {
750         return _index;
751     }
752     
753     public void setRowIndex(int index)
754     {
755         _setIndex(index);
756     }
757     
758     private void _setIndex(int index)
759     {
760         // save child state
761         //_saveChildState();
762         if (index < -1)
763         {
764             throw new IllegalArgumentException("rowIndex is less than -1");
765         }
766 
767         if (_index == index)
768         {
769             return;
770         }
771 
772         FacesContext facesContext = getFacesContext();
773 
774         if (_index == -1)
775         {
776             if (_initialDescendantComponentState == null)
777             {
778                 // Create a template that can be used to initialise any row
779                 // that we haven't visited before, ie a "saved state" that can
780                 // be pushed to the "restoreState" method of all the child
781                 // components to set them up to represent a clean row.
782                 _initialDescendantComponentState = saveDescendantComponentStates(this, true, true);
783             }
784         }
785         else
786         {
787             // If no initial component state, there are no EditableValueHolder instances,
788             // and that means there is no state to be saved for the current row, so we can
789             // skip row state saving code safely.
790             if (_initialDescendantComponentState != null)
791             {
792                 // We are currently positioned on some row, and are about to
793                 // move off it, so save the (partial) state of the components
794                 // representing the current row. Later if this row is revisited
795                 // then we can restore this state.
796                 Collection<Object[]> savedRowState = saveDescendantComponentStates(this, true, true);
797                 if (savedRowState != null)
798                 {
799                     _rowStates.put(getContainerClientId(facesContext), savedRowState);
800                 }
801             }
802         }
803 
804         _index = index;
805         
806         DataModel<?> localModel = getDataModel();
807         localModel.setRowIndex(index);
808 
809         if (_index != -1)
810         {
811             String var = getVar();
812             if (var != null && (_emptyModel || localModel.isRowAvailable()))
813             {
814                 if (_emptyModel)
815                 {
816                     getFacesContext().getExternalContext().getRequestMap().put(var, _index);
817                 }
818                 else
819                 {
820                     getFacesContext().getExternalContext().getRequestMap().put(var, localModel.getRowData());
821                 }
822             }
823             String varStatus = getVarStatus();
824             if (varStatus != null)
825             {
826                 getFacesContext().getExternalContext().getRequestMap()
827                         .put(varStatus, _getRepeatStatus());
828             }
829         }
830 
831         // restore child state
832         //_restoreChildState();
833         
834         if (_index == -1)
835         {
836             // reset components to initial state
837             // If no initial state, skip row restore state code
838             if (_initialDescendantComponentState != null)
839             {
840                 restoreDescendantComponentStates(this, true, _initialDescendantComponentState, true);
841             }
842             else
843             {
844                 restoreDescendantComponentWithoutRestoreState(this, true, true);
845             }
846         }
847         else
848         {
849             Object rowState = _rowStates.get(getContainerClientId(facesContext));
850             if (rowState == null)
851             {
852                 // We haven't been positioned on this row before, so just
853                 // configure the child components of this component with
854                 // the standard "initial" state
855                 // If no initial state, skip row restore state code
856                 if (_initialDescendantComponentState != null)
857                 {
858                     restoreDescendantComponentStates(this, true, _initialDescendantComponentState, true);
859                 }
860                 else
861                 {
862                     restoreDescendantComponentWithoutRestoreState(this, true, true);
863                 }
864             }
865             else
866             {
867                 // We have been positioned on this row before, so configure
868                 // the child components of this component with the (partial)
869                 // state that was previously saved. Fields not in the
870                 // partial saved state are left with their original values.
871                 restoreDescendantComponentStates(this, true, rowState, true);
872             }
873         }
874     }
875     
876     /**
877      * Calculates the count value for the given index.
878      * @param index
879      * @return
880      */
881     private int _calculateCountForIndex(int index)
882     {
883         return (index - getOffset()) / getStep();
884     }
885 
886     private void _validateAttributes() throws FacesException
887     {
888         
889         int begin = getBegin();
890         int end = getEnd();
891         int size = getSize();
892         _emptyModel = getDataModel() == EMPTY_MODEL && begin != -1 && end != -1;
893         int count = getRowCount();
894         int offset = getOffset();
895         if (begin == -1)
896         {
897             if (size >= 0)
898             {
899                 end = getOffset() + getSize();
900             }
901         }      
902        
903         if (end == -1 && size == -1) 
904         {
905             if (begin == -1) 
906             {
907                 end = getDataModel().getRowCount();
908             } 
909             else 
910             {
911                 end = getDataModel().getRowCount() - 1;
912             }
913         }
914         
915         int step = getStep();
916         boolean sizeIsEnd = _emptyModel;
917         boolean countdown = _emptyModel && end < begin;
918 
919         if (size == -1)
920         {
921             if (begin == -1)
922             {
923                 size =  end;
924                 sizeIsEnd = true;
925             } 
926             else 
927             {
928                 size = countdown ? (begin - end + 1)/step : (end - begin + 1)/step;
929             }     
930         }
931         
932         step = countdown && step > 0 ? -step : step;
933 
934         if (_emptyModel)
935         {
936             if (step > 0 && (end < begin))
937             {
938                 throw new FacesException("on empty models, end cannot be less than begin " +
939                         "when the step is positive");
940             }
941             else if (step < 0 && (end > begin))
942             {
943                 throw new FacesException("on empty models, end cannot be greater than begin " +
944                         "when the step is negative");
945             }
946             setStep(step);
947         }
948         else if (end >= 0)
949         {
950             if (size < 0)
951             {
952                 throw new FacesException("iteration size cannot be less " +
953                         "than zero");
954             }
955             else if (!sizeIsEnd && (begin == -1) && (offset + size) > end)
956             {
957                 throw new FacesException("iteration size cannot be greater " +
958                         "than collection size");
959             }
960             else if (!sizeIsEnd && (begin == -1) && (offset + size) > count)
961             {
962                 throw new FacesException("iteration size cannot be greater " +
963                         "than collection size");
964             }
965             else if (!sizeIsEnd && (begin >= 0) && (begin + size) > end+1)
966             {
967                 throw new FacesException("iteration size cannot be greater " +
968                         "than collection size");
969             }
970             else if(!sizeIsEnd && (begin >= 0) && (end+1 > count))
971             {
972                 throw new FacesException("end cannot be greater " +
973                         "than collection size");
974             }
975             else if(!sizeIsEnd && (begin >= 0) && (begin > count))
976             {
977                 throw new FacesException("begin cannot be greater " +
978                         "than collection size");
979             }
980         }
981         if (!_emptyModel && (begin >= 0) && (begin > end))
982         {
983             throw new FacesException("begin cannot be greater " +
984                     "than end");
985         }
986         if (!_emptyModel && (size > -1) && (offset > end))
987         {
988             throw new FacesException("iteration offset cannot be greater " +
989                     "than collection size");
990         }
991 
992         if (!_emptyModel && step == -1)
993         {
994             setStep(1);
995         }
996 
997         if (!_emptyModel && step < 0)
998         {
999             throw new FacesException("iteration step size cannot be less " +
1000                     "than zero");
1001         }
1002 
1003         else if (step == 0)
1004         {
1005             throw new FacesException("iteration step size cannot be equal " +
1006                     "to zero");
1007         }
1008 
1009         _end = end;
1010         
1011     }
1012 
1013     public void process(FacesContext faces, PhaseId phase)
1014     {
1015         // stop if not rendered
1016         if (!isRendered())
1017         {
1018             return;
1019         }
1020         
1021         // validate attributes
1022         _validateAttributes();
1023         
1024         // reset index
1025         _captureScopeValues();
1026         _setIndex(-1);
1027 
1028         try
1029         {
1030             // has children
1031             if (getChildCount() > 0)
1032             {
1033                 int i = getOffset();               
1034                 
1035                 int begin = getBegin();
1036                 int end = getEnd(); 
1037                 if (begin == -1)
1038                 {
1039                     end = getSize();
1040                     end = (end >= 0) ? i + end - 1 : Integer.MAX_VALUE - 1;
1041                 }
1042                 
1043                 if (begin >= 0) 
1044                 {
1045                     i = begin;
1046                 }
1047                 int step = getStep();
1048                 // grab renderer
1049                 String rendererType = getRendererType();
1050                 Renderer renderer = null;
1051                 if (rendererType != null)
1052                 {
1053                     renderer = getRenderer(faces);
1054                 }
1055                 
1056                 _count = 0;
1057                 
1058                 _setIndex(i);
1059                 
1060                 while (((step > 0 && i <= end) || (step < 0 && i >= end)) && _isIndexAvailable())
1061                 {
1062 
1063                     if (PhaseId.RENDER_RESPONSE.equals(phase) && renderer != null)
1064                     {
1065                         renderer.encodeChildren(faces, this);
1066                     }
1067                     else
1068                     {
1069                         for (int j = 0, childCount = getChildCount(); j < childCount; j++)
1070                         {
1071                             UIComponent child = getChildren().get(j);
1072                             if (PhaseId.APPLY_REQUEST_VALUES.equals(phase))
1073                             {
1074                                 child.processDecodes(faces);
1075                             }
1076                             else if (PhaseId.PROCESS_VALIDATIONS.equals(phase))
1077                             {
1078                                 child.processValidators(faces);
1079                             }
1080                             else if (PhaseId.UPDATE_MODEL_VALUES.equals(phase))
1081                             {
1082                                 child.processUpdates(faces);
1083                             }
1084                             else if (PhaseId.RENDER_RESPONSE.equals(phase))
1085                             {
1086                                 child.encodeAll(faces);
1087                             }
1088                         }
1089                     }
1090                     
1091                     ++_count;
1092                     
1093                     i += step;
1094                     
1095                     _setIndex(i);
1096                 }
1097             }
1098         }
1099         catch (IOException e)
1100         {
1101             throw new FacesException(e);
1102         }
1103         finally
1104         {
1105             _setIndex(-1);
1106             _restoreScopeValues();
1107         }
1108     }
1109 
1110     @Override
1111     public boolean invokeOnComponent(FacesContext context, String clientId,
1112             ContextCallback callback) throws FacesException
1113     {
1114         if (context == null || clientId == null || callback == null)
1115         {
1116             throw new NullPointerException();
1117         }
1118         
1119         final String baseClientId = getClientId(context);
1120 
1121         // searching for this component?
1122         boolean returnValue = baseClientId.equals(clientId);
1123 
1124         boolean isCachedFacesContext = isTemporalFacesContext();
1125         if (!isCachedFacesContext)
1126         {
1127             setTemporalFacesContext(context);
1128         }
1129 
1130         pushComponentToEL(context, this);
1131         try
1132         {
1133             if (returnValue)
1134             {
1135                 try
1136                 {
1137                     callback.invokeContextCallback(context, this);
1138                     return true;
1139                 }
1140                 catch (Exception e)
1141                 {
1142                     throw new FacesException(e);
1143                 }
1144             }
1145     
1146             // Now Look throught facets on this UIComponent
1147             if (this.getFacetCount() > 0)
1148             {
1149                 for (Iterator<UIComponent> it = this.getFacets().values().iterator(); !returnValue && it.hasNext();)
1150                 {
1151                     returnValue = it.next().invokeOnComponent(context, clientId, callback);
1152                 }
1153             }
1154     
1155             if (returnValue)
1156             {
1157                 return returnValue;
1158             }
1159             
1160             // is the component an inner component?
1161             if (clientId.startsWith(baseClientId))
1162             {
1163                 // Check if the clientId for the component, which we 
1164                 // are looking for, has a rowIndex attached
1165                 char separator = context.getNamingContainerSeparatorChar();
1166                 String subId = clientId.substring(baseClientId.length() + 1);
1167                 //If the char next to baseClientId is the separator one and
1168                 //the subId matches the regular expression
1169                 if (clientId.charAt(baseClientId.length()) == separator && 
1170                         subId.matches("[0-9]+"+separator+".*"))
1171                 {
1172                     String clientRow = subId.substring(0, subId.indexOf(separator));
1173         
1174                     // safe the current index, count aside
1175                     final int prevIndex = _index;
1176                     final int prevCount = _count;
1177                     
1178                     try
1179                     {
1180                         int invokeIndex = Integer.parseInt(clientRow);
1181                         // save the current scope values and set the right index
1182                         _captureScopeValues();
1183                         if (invokeIndex != -1)
1184                         {
1185                             // calculate count for RepeatStatus
1186                             _count = _calculateCountForIndex(invokeIndex);
1187                         }
1188                         _setIndex(invokeIndex);
1189                         
1190                         if (!_isIndexAvailable())
1191                         {
1192                             return false;
1193                         }
1194                         
1195                         for (Iterator<UIComponent> it1 = getChildren().iterator(); 
1196                             !returnValue && it1.hasNext();)
1197                         {
1198                             //recursive call to find the component
1199                             returnValue = it1.next().invokeOnComponent(context, clientId, callback);
1200                         }
1201                     }
1202                     finally
1203                     {
1204                         // restore the previous count, index and scope values
1205                         _count = prevCount;
1206                         _setIndex(prevIndex);
1207                         _restoreScopeValues();
1208                     }
1209                 }
1210                 else
1211                 {
1212                     // Searching for this component's children
1213                     if (this.getChildCount() > 0)
1214                     {
1215                         // Searching for this component's children/facets
1216                         for (Iterator<UIComponent> it = this.getChildren().iterator(); !returnValue && it.hasNext();)
1217                         {
1218                             returnValue = it.next().invokeOnComponent(context, clientId, callback);
1219                         }
1220                     }
1221                 }
1222             }
1223         }
1224         finally
1225         {
1226             //all components must call popComponentFromEl after visiting is finished
1227             popComponentFromEL(context);
1228             if (!isCachedFacesContext)
1229             {
1230                 setTemporalFacesContext(null);
1231             }
1232         }
1233 
1234         return returnValue;
1235     }
1236     
1237     @Override
1238     protected FacesContext getFacesContext()
1239     {
1240         if (_facesContext == null)
1241         {
1242             return super.getFacesContext();
1243         }
1244         else
1245         {
1246             return _facesContext;
1247         }
1248     }
1249     
1250     private boolean isTemporalFacesContext()
1251     {
1252         return _facesContext != null;
1253     }
1254     
1255     private void setTemporalFacesContext(FacesContext facesContext)
1256     {
1257         _facesContext = facesContext;
1258     }
1259 
1260     @Override
1261     public boolean visitTree(VisitContext context, VisitCallback callback)
1262     {
1263         // override the behavior from UIComponent to visit
1264         // all children once per "row"
1265 
1266         boolean skipIterationHint = context.getHints().contains(VisitHint.SKIP_ITERATION);
1267         if (skipIterationHint)
1268         {
1269             return super.visitTree(context, callback);
1270         }
1271         // push the Component to EL
1272         pushComponentToEL(context.getFacesContext(), this);
1273         try
1274         {
1275             if (!isVisitable(context))
1276             {
1277                 return false;
1278             }
1279 
1280             // save the current index, count aside
1281             final int prevIndex = _index;
1282             final int prevCount = _count;
1283 
1284             // reset index and save scope values
1285             _captureScopeValues();
1286             _setIndex(-1);
1287 
1288             try
1289             {
1290                 VisitResult res = context.invokeVisitCallback(this, callback);
1291                 switch (res)
1292                 {
1293                 // we are done, nothing has to be processed anymore
1294                 case COMPLETE:
1295                     return true;
1296 
1297                 case REJECT:
1298                     return false;
1299 
1300                 //accept
1301                 default:
1302                     // determine if we need to visit our children
1303                     // Note that we need to do this check because we are a NamingContainer
1304                     Collection<String> subtreeIdsToVisit = context
1305                             .getSubtreeIdsToVisit(this);
1306                     boolean doVisitChildren = subtreeIdsToVisit != null
1307                             && !subtreeIdsToVisit.isEmpty();
1308                     if (doVisitChildren)
1309                     {
1310                         // validate attributes
1311                         _validateAttributes();
1312    
1313                         // visit the facets of the component
1314                         if (getFacetCount() > 0)
1315                         {
1316                             for (UIComponent facet : getFacets().values())
1317                             {
1318                                 if (facet.visitTree(context, callback))
1319                                 {
1320                                     return true;
1321                                 }
1322                             }
1323                         }
1324 
1325                         // visit the children once per "row"
1326                         if (getChildCount() > 0)
1327                         {
1328                             int i = getOffset();
1329                             int end = getSize();
1330                             int step = getStep();
1331                             end = (end >= 0) ? i + end : Integer.MAX_VALUE - 1;
1332                             _count = 0;
1333 
1334                             _setIndex(i);
1335                             while (i < end && _isIndexAvailable())
1336                             {
1337                                 for (int j = 0, childCount = getChildCount(); j < childCount; j++)
1338                                 {
1339                                     UIComponent child = getChildren().get(j);
1340                                     if (child.visitTree(context, callback))
1341                                     {
1342                                         return true;
1343                                     }
1344                                 }
1345 
1346                                 _count++;
1347                                 i += step;
1348 
1349                                 _setIndex(i);
1350                             }
1351                         }
1352                     }
1353                     return false;
1354                 }
1355             }
1356             finally
1357             {
1358 
1359                 // restore the previous count, index and scope values
1360                 _count = prevCount;
1361                 _setIndex(prevIndex);
1362                 _restoreScopeValues();
1363             }
1364         }
1365         finally
1366         {
1367             // pop the component from EL
1368             popComponentFromEL(context.getFacesContext());
1369         }
1370     }
1371 
1372     @Override
1373     public void processDecodes(FacesContext faces)
1374     {
1375         if (!isRendered())
1376         {
1377             return;
1378         }
1379         
1380         process(faces, PhaseId.APPLY_REQUEST_VALUES);
1381         decode(faces);
1382     }
1383 
1384     @Override
1385     public void processUpdates(FacesContext faces)
1386     {
1387         if (!isRendered())
1388         {
1389             return;
1390         }
1391         
1392         process(faces, PhaseId.UPDATE_MODEL_VALUES);
1393         
1394         if (faces.getRenderResponse())
1395         {
1396             _isValidChilds = false;
1397         }
1398     }
1399 
1400     @Override
1401     public void processValidators(FacesContext faces)
1402     {
1403         if (!isRendered())
1404         {
1405             return;
1406         }
1407         
1408         process(faces, PhaseId.PROCESS_VALIDATIONS);
1409         
1410         // check if an validation error forces the render response for our data
1411         if (faces.getRenderResponse())
1412         {
1413             _isValidChilds = false;
1414         }
1415     }
1416 
1417     // from RI
1418     private final static class SavedState implements Serializable
1419     {
1420         private boolean _localValueSet;
1421         private Object _submittedValue;
1422         private boolean _valid = true;
1423         private Object _value;
1424 
1425         private static final long serialVersionUID = 2920252657338389849L;
1426         
1427         public SavedState(EditableValueHolder evh)
1428         {
1429             _value = evh.getLocalValue();
1430             _localValueSet = evh.isLocalValueSet();
1431             _valid = evh.isValid();
1432             _submittedValue = evh.getSubmittedValue();
1433         }        
1434 
1435         Object getSubmittedValue()
1436         {
1437             return (_submittedValue);
1438         }
1439 
1440         void setSubmittedValue(Object submittedValue)
1441         {
1442             _submittedValue = submittedValue;
1443         }
1444 
1445         boolean isValid()
1446         {
1447             return (_valid);
1448         }
1449 
1450         void setValid(boolean valid)
1451         {
1452             _valid = valid;
1453         }
1454 
1455         Object getValue()
1456         {
1457             return _value;
1458         }
1459 
1460         public void setValue(Object value)
1461         {
1462             _value = value;
1463         }
1464 
1465         boolean isLocalValueSet()
1466         {
1467             return _localValueSet;
1468         }
1469 
1470         public void setLocalValueSet(boolean localValueSet)
1471         {
1472             _localValueSet = localValueSet;
1473         }
1474 
1475         @Override
1476         public String toString()
1477         {
1478             return ("submittedValue: " + _submittedValue + " value: " + _value + " localValueSet: " + _localValueSet);
1479         }
1480         
1481         public void restoreState(EditableValueHolder evh)
1482         {
1483             evh.setValue(_value);
1484             evh.setValid(_valid);
1485             evh.setSubmittedValue(_submittedValue);
1486             evh.setLocalValueSet(_localValueSet);
1487         }
1488 
1489         public void populate(EditableValueHolder evh)
1490         {
1491             _value = evh.getLocalValue();
1492             _valid = evh.isValid();
1493             _submittedValue = evh.getSubmittedValue();
1494             _localValueSet = evh.isLocalValueSet();
1495         }
1496 
1497         public void apply(EditableValueHolder evh)
1498         {
1499             evh.setValue(_value);
1500             evh.setValid(_valid);
1501             evh.setSubmittedValue(_submittedValue);
1502             evh.setLocalValueSet(_localValueSet);
1503         }
1504     }
1505 
1506     private final class IndexedEvent extends FacesEvent
1507     {
1508         private final FacesEvent _target;
1509 
1510         private final int _index;
1511 
1512         public IndexedEvent(UIRepeat owner, FacesEvent target, int index)
1513         {
1514             super(owner);
1515             _target = target;
1516             _index = index;
1517         }
1518 
1519         @Override
1520         public PhaseId getPhaseId()
1521         {
1522             return _target.getPhaseId();
1523         }
1524 
1525         @Override
1526         public void setPhaseId(PhaseId phaseId)
1527         {
1528             _target.setPhaseId(phaseId);
1529         }
1530 
1531         @Override
1532         public boolean isAppropriateListener(FacesListener listener)
1533         {
1534             return _target.isAppropriateListener(listener);
1535         }
1536 
1537         @Override
1538         public void processListener(FacesListener listener)
1539         {
1540             UIRepeat owner = (UIRepeat) getComponent();
1541             
1542             // safe the current index, count aside
1543             final int prevIndex = owner._index;
1544             final int prevCount = owner._count;
1545             
1546             try
1547             {
1548                 owner._captureScopeValues();
1549                 if (this._index != -1)
1550                 {
1551                     // calculate count for RepeatStatus
1552                     _count = _calculateCountForIndex(this._index);
1553                 }
1554                 owner._setIndex(this._index);
1555                 if (owner._isIndexAvailable())
1556                 {
1557                     _target.processListener(listener);
1558                 }
1559             }
1560             finally
1561             {
1562                 // restore the previous count, index and scope values
1563                 owner._count = prevCount;
1564                 owner._setIndex(prevIndex);
1565                 owner._restoreScopeValues();
1566             }
1567         }
1568 
1569         public int getIndex()
1570         {
1571             return _index;
1572         }
1573 
1574         public FacesEvent getTarget()
1575         {
1576             return _target;
1577         }
1578 
1579     }
1580 
1581     @Override
1582     public void broadcast(FacesEvent event) throws AbortProcessingException
1583     {
1584         if (event instanceof IndexedEvent)
1585         {
1586             IndexedEvent idxEvent = (IndexedEvent) event;
1587             
1588             // safe the current index, count aside
1589             final int prevIndex = _index;
1590             final int prevCount = _count;
1591             
1592             try
1593             {
1594                 _captureScopeValues();
1595                 if (idxEvent.getIndex() != -1)
1596                 {
1597                     // calculate count for RepeatStatus
1598                     _count = _calculateCountForIndex(idxEvent.getIndex());
1599                 }
1600                 _setIndex(idxEvent.getIndex());
1601                 if (_isIndexAvailable())
1602                 {
1603                     // get the target FacesEvent
1604                     FacesEvent target = idxEvent.getTarget();
1605                     FacesContext facesContext = getFacesContext();
1606                     
1607                     // get the component associated with the target event and push
1608                     // it and its composite component parent, if available, to the
1609                     // component stack to have them available while processing the 
1610                     // event (see also UIViewRoot._broadcastAll()).
1611                     UIComponent targetComponent = target.getComponent();
1612                     UIComponent compositeParent = UIComponent
1613                             .getCompositeComponentParent(targetComponent);
1614                     if (compositeParent != null)
1615                     {
1616                         pushComponentToEL(facesContext, compositeParent);
1617                     }
1618                     pushComponentToEL(facesContext, targetComponent);
1619                     
1620                     try
1621                     {
1622                         // actual event broadcasting
1623                         targetComponent.broadcast(target);
1624                     }
1625                     finally
1626                     {
1627                         // remove the components from the stack again
1628                         popComponentFromEL(facesContext);
1629                         if (compositeParent != null)
1630                         {
1631                             popComponentFromEL(facesContext);
1632                         }
1633                     }
1634                 }
1635             }
1636             finally
1637             {
1638                 // restore the previous count, index and scope values
1639                 _count = prevCount;
1640                 _setIndex(prevIndex);
1641                 _restoreScopeValues();
1642             }
1643         }
1644         else
1645         {
1646             super.broadcast(event);
1647         }
1648     }
1649 
1650     @Override
1651     public void queueEvent(FacesEvent event)
1652     {
1653         super.queueEvent(new IndexedEvent(this, event, _index));
1654     }
1655 
1656     @Override
1657     public void restoreState(FacesContext context, Object state)
1658     {
1659         if (state == null)
1660         {
1661             return;
1662         }
1663         
1664         Object values[] = (Object[]) state;
1665         super.restoreState(context, values[0]);
1666         //Object restoredRowStates = UIComponentBase.restoreAttachedState(context, values[1]);
1667         /*
1668         if (restoredRowStates == null)
1669         {
1670             if (!_rowDeltaStates.isEmpty())
1671             {
1672                 _rowDeltaStates.clear();
1673             }
1674         }
1675         else
1676         {
1677             _rowDeltaStates = (Map<String, Map<String, Object> >) restoredRowStates;
1678         }*/
1679         if (values.length > 2)
1680         {
1681             Object rs = UIComponentBase.restoreAttachedState(context, values[2]);
1682             if (rs == null)
1683             {
1684                 if (!_rowStates.isEmpty())
1685                 {
1686                     _rowStates.clear();
1687                 }
1688             }
1689             else
1690             {
1691                 _rowStates = (Map<String, Collection<Object[]> >) rs;
1692             }
1693         }
1694     }
1695 
1696     @Override
1697     public Object saveState(FacesContext context)
1698     {
1699         if (context.getViewRoot() != null)
1700         {
1701             if (context.getViewRoot().getAttributes().get("oam.view.resetSaveStateMode") == RESET_MODE_SOFT)
1702             {
1703                 _dataModelMap.clear();
1704                 _isValidChilds=true;
1705                 //_rowTransientStates.clear();
1706             }
1707             if (context.getViewRoot().getAttributes().get("oam.view.resetSaveStateMode") == RESET_MODE_HARD)
1708             {
1709                 _dataModelMap.clear();
1710                 _isValidChilds=true;
1711                 //_rowTransientStates.clear();
1712                 _rowStates.clear();
1713                 //_rowDeltaStates.clear();
1714             }
1715         }
1716         if (initialStateMarked())
1717         {
1718             Object parentSaved = super.saveState(context);
1719             if (context.getCurrentPhaseId() != null && 
1720                 !PhaseId.RENDER_RESPONSE.equals(context.getCurrentPhaseId()))
1721             {
1722                 if (parentSaved == null /*&&_rowDeltaStates.isEmpty()*/ && _rowStates.isEmpty())
1723                 {
1724                     return null;
1725                 }
1726                 else
1727                 {
1728                     Object values[] = new Object[3];
1729                     values[0] = super.saveState(context);
1730                     //values[1] = UIComponentBase.saveAttachedState(context, _rowDeltaStates);
1731                     values[1] = null;
1732                     values[2] = UIComponentBase.saveAttachedState(context, _rowStates);
1733                     return values;
1734                 }
1735             }
1736             else
1737             {
1738                 if (parentSaved == null /*&&_rowDeltaStates.isEmpty()*/)
1739                 {
1740                     return null;
1741                 }
1742                 else
1743                 {
1744                     Object values[] = new Object[2];
1745                     values[0] = super.saveState(context);
1746                     //values[1] = UIComponentBase.saveAttachedState(context, _rowDeltaStates);
1747                     values[1] = null;
1748                     return values; 
1749                 }
1750             }
1751         }
1752         else
1753         {
1754             if (context.getCurrentPhaseId() != null && 
1755                 !PhaseId.RENDER_RESPONSE.equals(context.getCurrentPhaseId()))
1756             {
1757                 Object values[] = new Object[3];
1758                 values[0] = super.saveState(context);
1759                 //values[1] = UIComponentBase.saveAttachedState(context, _rowDeltaStates);
1760                 values[1] = null;
1761                 values[2] = UIComponentBase.saveAttachedState(context, _rowStates);
1762                 return values; 
1763             }
1764             else
1765             {
1766                 Object values[] = new Object[2];
1767                 values[0] = super.saveState(context);
1768                 //values[1] = UIComponentBase.saveAttachedState(context, _rowDeltaStates);
1769                 values[1] = null;
1770                 return values;
1771             }
1772         }
1773     }
1774     
1775     @Override
1776     public void encodeBegin(FacesContext context) throws IOException
1777     {
1778         _initialDescendantComponentState = null;
1779         if (_isValidChilds && !hasErrorMessages(context))
1780         {
1781             // Clear the data model so that when rendering code calls
1782             // getDataModel a fresh model is fetched from the backing
1783             // bean via the value-binding.
1784             _dataModelMap.clear();
1785 
1786             // When the data model is cleared it is also necessary to
1787             // clear the saved row state, as there is an implicit 1:1
1788             // relation between objects in the _rowStates and the
1789             // corresponding DataModel element.
1790             _rowStates.clear();
1791         }
1792         super.encodeBegin(context);
1793     }
1794     
1795     private boolean hasErrorMessages(FacesContext context)
1796     {
1797         for (Iterator<FacesMessage> iter = context.getMessages(); iter.hasNext();)
1798         {
1799             FacesMessage message = iter.next();
1800             if (FacesMessage.SEVERITY_ERROR.compareTo(message.getSeverity()) <= 0)
1801             {
1802                 return true;
1803             }
1804         }
1805         return false;
1806     }
1807 
1808     @Override
1809     public void encodeChildren(FacesContext faces) throws IOException
1810     {
1811         if (!isRendered())
1812         {
1813             return;
1814         }
1815         
1816         process(faces, PhaseId.RENDER_RESPONSE);
1817     }
1818 
1819     @Override
1820     public boolean getRendersChildren()
1821     {
1822         if (getRendererType() != null)
1823         {
1824             Renderer renderer = getRenderer(getFacesContext());
1825             if (renderer != null)
1826             {
1827                 return renderer.getRendersChildren();
1828             }
1829         }
1830         
1831         return true;
1832     }
1833     
1834     enum PropertyKeys
1835     {
1836          value
1837         , var
1838         , size
1839         , varStatus
1840         , offset
1841         , step
1842         , begin
1843         , end
1844     }
1845 }