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