/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package javax.faces.component;

import org.apache.myfaces.core.api.shared.lang.ClassUtils;
import org.apache.myfaces.core.api.shared.ComponentUtils;
import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.el.ValueExpression;
import javax.faces.FacesException;
import javax.faces.application.FacesMessage;
import javax.faces.application.StateManager;
import javax.faces.component.visit.VisitCallback;
import javax.faces.component.visit.VisitContext;
import javax.faces.component.visit.VisitHint;
import javax.faces.component.visit.VisitResult;
import javax.faces.context.FacesContext;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.FacesEvent;
import javax.faces.event.FacesListener;
import javax.faces.event.PhaseId;
import javax.faces.event.PostValidateEvent;
import javax.faces.event.PreValidateEvent;
import javax.faces.model.ArrayDataModel;
import javax.faces.model.CollectionDataModel;
import javax.faces.model.DataModel;
import javax.faces.model.IterableDataModel;
import javax.faces.model.ListDataModel;
import javax.faces.model.ResultDataModel;
import javax.faces.model.ResultSetDataModel;
import javax.faces.model.ScalarDataModel;
import javax.servlet.jsp.jstl.sql.Result;

import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFComponent;
import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFFacet;
import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFProperty;

/**
 * Represents an abstraction of a component which has multiple "rows" of data.
 * <p>
 * The children of this component are expected to be UIColumn components.
 * <p>
 * Note that the same set of child components are reused to implement each row of the table in turn during such phases
 * as apply-request-values and render-response. Altering any of the members of these components therefore affects the
 * attribute for every row, except for the following members:
 * <ul>
 * <li>submittedValue
 * <li>value (where no EL binding is used)
 * <li>valid
 * </ul>
 * <p>
 * This reuse of the child components also means that it is not possible to save a reference to a component during table
 * processing, then access it later and expect it to still represent the same row of the table.
 * <h1>
 * Implementation Notes</h1>
 * <p>
 * Each of the UIColumn children of this component has a few component children of its own to render the contents of the
 * table cell. However there can be a very large number of rows in a table, so it isn't efficient for the UIColumn and
 * all its child objects to be duplicated for each row in the table. Instead the "flyweight" pattern is used where a
 * serialized state is held for each row. When setRowIndex is invoked, the UIColumn objects and their children serialize
 * their current state then reinitialise themselves from the appropriate saved state. This allows a single set of real
 * objects to represent multiple objects which have the same types but potentially different internal state. When a row
 * is selected for the first time, its state is set to a clean "initial" state. Transient components (including any
 * read-only component) do not save their state; they are just reinitialised as required. The state saved/restored when
 * changing rows is not the complete component state, just the fields that are expected to vary between rows:
 * "submittedValue", "value", "isValid".
 * </p>
 * <p>
 * Note that a table is a "naming container", so that components within the table have their ids prefixed with the id of
 * the table. Actually, when setRowIndex has been called on a table with id of "zzz" the table pretends to its children
 * that its ID is "zzz_n" where n is the row index. This means that renderers for child components which call
 * component.getClientId automatically get ids of form "zzz_n:childId" thus ensuring that components in different rows
 * of the table get different ids.
 * </p>
 * <p>
 * When decoding a submitted page, this class iterates over all its possible rowIndex values, restoring the appropriate
 * serialized row state then calling processDecodes on the child components. Because the child components (or their
 * renderers) use getClientId to get the request key to look for parameter data, and because this object pretends to
 * have a different id per row ("zzz_n") a single child component can decode data from each table row in turn without
 * being aware that it is within a table. The table's data model is updated before each call to child.processDecodes, so
 * the child decode method can assume that the data model's rowData points to the model object associated with the row
 * currently being decoded. Exactly the same process applies for the later validation and updateModel phases.
 * </p>
 * <p>
 * When the data model for the table is bound to a backing bean property, and no validation errors have occured during
 * processing of a postback, the data model is refetched at the start of the rendering phase (ie after the update model
 * phase) so that the contents of the data model can be changed as a result of the latest form submission. Because the
 * saved row state must correspond to the elements within the data model, the row state must be discarded whenever a new
 * data model is fetched; not doing this would cause all sorts of inconsistency issues. This does imply that changing
 * the state of any of the members "submittedValue", "value" or "valid" of a component within the table during the
 * invokeApplication phase has no effect on the rendering of the table. When a validation error has occurred, a new
 * DataModel is <i>not</i> fetched, and the saved state of the child components is <i>not</i> discarded.
 * </p>
 * see Javadoc of the <a href="http://java.sun.com/j2ee/javaserverfaces/1.2/docs/api/index.html">JSF Specification</a>
 * for more information.
 */
@JSFComponent(defaultRendererType = "javax.faces.Table")
public class UIData extends UIComponentBase implements NamingContainer, UniqueIdVendor
{
    public static final String COMPONENT_FAMILY = "javax.faces.Data";
    public static final String COMPONENT_TYPE = "javax.faces.Data"; // for unit tests

    private static final String FACES_DATA_MODEL_MANAGER_CLASS_NAME
            = "org.apache.myfaces.cdi.model.FacesDataModelManager";
    private static final Class<?> FACES_DATA_MODEL_MANAGER_CLASS;
    private static final Method FACES_DATA_MODEL_MANAGER_CREATE_DATAMODEL_METHOD;
    
    static
    {
        Class<?> dataModelBuilderClass = null;
        Method createDataModelMethod = null;
        try
        {
            dataModelBuilderClass = ClassUtils.classForName(FACES_DATA_MODEL_MANAGER_CLASS_NAME);
            if (dataModelBuilderClass != null)
            {
                createDataModelMethod = dataModelBuilderClass.getMethod("createDataModel",
                        new Class[]{FacesContext.class, Class.class, Object.class});
            }
        }
        catch(Exception e)
        {
            //No Op
        }
        FACES_DATA_MODEL_MANAGER_CLASS = dataModelBuilderClass;
        FACES_DATA_MODEL_MANAGER_CREATE_DATAMODEL_METHOD = createDataModelMethod;
    }
    
    private static final String FOOTER_FACET_NAME = "footer";
    private static final String HEADER_FACET_NAME = "header";
    private static final Class<Object[]> OBJECT_ARRAY_CLASS = Object[].class;
    private static final int PROCESS_DECODES = 1;
    private static final int PROCESS_VALIDATORS = 2;
    private static final int PROCESS_UPDATES = 3;

    private static final Object[] LEAF_NO_STATE = new Object[]{null,null};

    private int _rowIndex = -1;

    // Holds for each row the states of the child components of this UIData.
    // Note that only "partial" component state is saved: the component fields
    // that are expected to vary between rows.
    private Map<String, Object> _rowStates = new HashMap<>();
    private Map<String, Map<String, Object>> _rowDeltaStates = new HashMap<>();
    private Map<String, Map<String, Object>> _rowTransientStates = new HashMap<>();

    /**
     * Handle case where this table is nested inside another table. See method getDataModel for more details.
     * <p>
     * Key: parentClientId (aka rowId when nested within a parent table) Value: DataModel
     */
    private Map<String, DataModel> _dataModelMap = new HashMap<>(3, 1f);

    // will be set to false if the data should not be refreshed at the beginning of the encode phase
    private boolean _isValidChilds = true;

    private Object _initialDescendantComponentState = null;
    
    private Object _initialDescendantFullComponentState = null;

    private static class FacesEventWrapper extends FacesEvent
    {
        private static final long serialVersionUID = 6648047974065628773L;
        private FacesEvent _wrappedFacesEvent;
        private int _rowIndex;

        public FacesEventWrapper(FacesEvent facesEvent, int rowIndex, UIData redirectComponent)
        {
            super(redirectComponent);
            _wrappedFacesEvent = facesEvent;
            _rowIndex = rowIndex;
        }

        @Override
        public PhaseId getPhaseId()
        {
            return _wrappedFacesEvent.getPhaseId();
        }

        @Override
        public void setPhaseId(PhaseId phaseId)
        {
            _wrappedFacesEvent.setPhaseId(phaseId);
        }

        @Override
        public void queue()
        {
            _wrappedFacesEvent.queue();
        }

        @Override
        public String toString()
        {
            return _wrappedFacesEvent.toString();
        }

        @Override
        public boolean isAppropriateListener(FacesListener faceslistener)
        {
            return _wrappedFacesEvent.isAppropriateListener(faceslistener);
        }

        @Override
        public void processListener(FacesListener faceslistener)
        {
            _wrappedFacesEvent.processListener(faceslistener);
        }

        public FacesEvent getWrappedFacesEvent()
        {
            return _wrappedFacesEvent;
        }

        public int getRowIndex()
        {
            return _rowIndex;
        }
    }

    private static final DataModel EMPTY_DATA_MODEL = new DataModel()
    {
        @Override
        public boolean isRowAvailable()
        {
            return false;
        }

        @Override
        public int getRowCount()
        {
            return 0;
        }

        @Override
        public Object getRowData()
        {
            throw new IllegalArgumentException();
        }

        @Override
        public int getRowIndex()
        {
            return -1;
        }

        @Override
        public void setRowIndex(int i)
        {
            if (i < -1)
            {
                throw new IllegalArgumentException();
            }
        }

        @Override
        public Object getWrappedData()
        {
            return null;
        }

        @Override
        public void setWrappedData(Object obj)
        {
            if (obj == null)
            {
                return; // Clearing is allowed
            }
            throw new UnsupportedOperationException(this.getClass().getName() + " UnsupportedOperationException");
        }
    };

    private static class EditableValueHolderState implements Serializable
    {
        private final Object _value;
        private final boolean _localValueSet;
        private final boolean _valid;
        private final Object _submittedValue;

        public EditableValueHolderState(EditableValueHolder evh)
        {
            _value = evh.getLocalValue();
            _localValueSet = evh.isLocalValueSet();
            _valid = evh.isValid();
            _submittedValue = evh.getSubmittedValue();
        }

        public void restoreState(EditableValueHolder evh)
        {
            evh.setValue(_value);
            evh.setLocalValueSet(_localValueSet);
            evh.setValid(_valid);
            evh.setSubmittedValue(_submittedValue);
        }
    }

    /**
     * Construct an instance of the UIData.
     */
    public UIData()
    {
        setRendererType("javax.faces.Table");
    }

    @Override
    public boolean invokeOnComponent(FacesContext context, String clientId, ContextCallback callback)
        throws FacesException
    {
        if (context == null || clientId == null || callback == null)
        {
            throw new NullPointerException();
        }
        
        final String baseClientId = getClientId(context);

        // searching for this component?
        boolean returnValue = baseClientId.equals(clientId);

        boolean isCachedFacesContext = isCachedFacesContext();
        if (!isCachedFacesContext)
        {
            setCachedFacesContext(context);
        }
        
        pushComponentToEL(context, this);
        try
        {
            if (returnValue)
            {
                try
                {
                    callback.invokeContextCallback(context, this);
                    return true;
                }
                catch (Exception e)
                {
                    throw new FacesException(e);
                }
            }
    
            // Now Look throught facets on this UIComponent
            if (this.getFacetCount() > 0)
            {
                for (Iterator<UIComponent> it = this.getFacets().values().iterator(); !returnValue && it.hasNext();)
                {
                    returnValue = it.next().invokeOnComponent(context, clientId, callback);
                }
            }
    
            if (returnValue)
            {
                return returnValue;
            }
            
            // is the component an inner component?
            if (clientId.startsWith(baseClientId))
            {
                // Check if the clientId for the component, which we 
                // are looking for, has a rowIndex attached
                char separator = context.getNamingContainerSeparatorChar();
                String subId = clientId.substring(baseClientId.length() + 1);
                //If the char next to baseClientId is the separator one and
                //the subId matches the regular expression
                if (clientId.charAt(baseClientId.length()) == separator
                        && subId.matches("[0-9]+" + separator + ".*")) // TODO [perf] precompile pattern
                {
                    String clientRow = subId.substring(0, subId.indexOf(separator));

                    //Now we save the current position
                    int oldRow = this.getRowIndex();
                    
                    // try-finally --> make sure, that the old row index is restored
                    try
                    {
                        //The conversion is safe, because its already checked on the
                        //regular expresion
                        this.setRowIndex(Integer.parseInt(clientRow));
                        
                        // check, if the row is available
                        if (!isRowAvailable())
                        {
                            return false;
                        }
            
                        for (Iterator<UIComponent> it1 = getChildren().iterator(); !returnValue && it1.hasNext();)
                        {
                            //recursive call to find the component
                            returnValue = it1.next().invokeOnComponent(context, clientId, callback);
                        }
                    }
                    finally
                    {
                        //Restore the old position. Doing this prevent
                        //side effects.
                        this.setRowIndex(oldRow);
                    }
                }
                else
                {
                    // MYFACES-2370: search the component in the childrens' facets too.
                    // We have to check the childrens' facets here, because in MyFaces
                    // the rowIndex is not attached to the clientId for the children of
                    // facets of the UIColumns. However, in RI the rowIndex is 
                    // attached to the clientId of UIColumns' Facets' children.
                    for (Iterator<UIComponent> itChildren = this.getChildren().iterator();
                            !returnValue && itChildren.hasNext();)
                    {
                        UIComponent child = itChildren.next();
                        if (child instanceof UIColumn && clientId.equals(child.getClientId(context)))
                        {
                            try
                            {
                                callback.invokeContextCallback(context, child);
                            }
                            catch (Exception e)
                            {
                                throw new FacesException(e);
                            }
                            returnValue = true;
                        }
                        // process the child's facets
                        if (child.getFacetCount() > 0)
                        {
                            for (Iterator<UIComponent> itChildFacets = child.getFacets().values().iterator(); 
                                !returnValue && itChildFacets.hasNext();)
                            {
                                //recursive call to find the component
                                returnValue = itChildFacets.next().invokeOnComponent(context, clientId, callback);
                            }
                        }
                    }
                }
            }
        }
        finally
        {
            //all components must call popComponentFromEl after visiting is finished
            popComponentFromEL(context);
            if (!isCachedFacesContext)
            {
                setCachedFacesContext(null);
            }
        }

        return returnValue;
    }

    public void setFooter(UIComponent footer)
    {
        getFacets().put(FOOTER_FACET_NAME, footer);
    }

    @JSFFacet
    public UIComponent getFooter()
    {
        return getFacets().get(FOOTER_FACET_NAME);
    }

    public void setHeader(UIComponent header)
    {
        getFacets().put(HEADER_FACET_NAME, header);
    }

    @JSFFacet
    public UIComponent getHeader()
    {
        return getFacets().get(HEADER_FACET_NAME);
    }

    public boolean isRowAvailable()
    {
        return getDataModel().isRowAvailable();
    }

    public int getRowCount()
    {
        return getDataModel().getRowCount();
    }

    public Object getRowData()
    {
        return getDataModel().getRowData();
    }

    public int getRowIndex()
    {
        return _rowIndex;
    }

    /**
     * Set the current row index that methods like getRowData use.
     * <p>
     * Param rowIndex can be -1, meaning "no row".
     * <p>
     * 
     * @param rowIndex
     */
    public void setRowIndex(int rowIndex)
    {
        if (isRowStatePreserved())
        {
            setRowIndexPreserveComponentState(rowIndex);
        }
        else
        {
            setRowIndexWithoutPreserveComponentState(rowIndex);
        }
    }

    private void setRowIndexWithoutPreserveComponentState(int rowIndex)
    {
        if (rowIndex < -1)
        {
            throw new IllegalArgumentException("rowIndex is less than -1");
        }

        if (_rowIndex == rowIndex)
        {
            return;
        }

        FacesContext facesContext = getFacesContext();

        if (_rowIndex == -1)
        {
            if (_initialDescendantComponentState == null)
            {
                // Create a template that can be used to initialise any row
                // that we haven't visited before, ie a "saved state" that can
                // be pushed to the "restoreState" method of all the child
                // components to set them up to represent a clean row.
                _initialDescendantComponentState = saveDescendantComponentStates(this, false, false);
            }
        }
        else
        {
            // If no initial component state, there are no EditableValueHolder instances,
            // and that means there is no state to be saved for the current row, so we can
            // skip row state saving code safely.
            if (_initialDescendantComponentState != null)
            {
                // We are currently positioned on some row, and are about to
                // move off it, so save the (partial) state of the components
                // representing the current row. Later if this row is revisited
                // then we can restore this state.
                Collection<Object[]> savedRowState = saveDescendantComponentStates(this, false, false);
                if (savedRowState != null)
                {
                    _rowStates.put(getContainerClientId(facesContext), savedRowState);
                }
            }
        }

        _rowIndex = rowIndex;

        DataModel dataModel = getDataModel();
        dataModel.setRowIndex(rowIndex);

        String var = (String) getStateHelper().get(PropertyKeys.var);
        if (rowIndex == -1)
        {
            if (var != null)
            {
                facesContext.getExternalContext().getRequestMap().remove(var);
            }
        }
        else
        {
            if (var != null)
            {
                if (isRowAvailable())
                {
                    Object rowData = dataModel.getRowData();
                    facesContext.getExternalContext().getRequestMap().put(var, rowData);
                }
                else
                {
                    facesContext.getExternalContext().getRequestMap().remove(var);
                }
            }
        }

        if (_rowIndex == -1)
        {
            // reset components to initial state
            // If no initial state, skip row restore state code
            if (_initialDescendantComponentState != null)
            {
                restoreDescendantComponentStates(this, false, _initialDescendantComponentState, false);
            }
            else
            {
                restoreDescendantComponentWithoutRestoreState(this, false, false);
            }
        }
        else
        {
            Object rowState = _rowStates.get(getContainerClientId(facesContext));
            if (rowState == null)
            {
                // We haven't been positioned on this row before, so just
                // configure the child components of this component with
                // the standard "initial" state
                // If no initial state, skip row restore state code
                if (_initialDescendantComponentState != null)
                {
                    restoreDescendantComponentStates(this, false, _initialDescendantComponentState, false);
                }
                else
                {
                    restoreDescendantComponentWithoutRestoreState(this, false, false);
                }
            }
            else
            {
                // We have been positioned on this row before, so configure
                // the child components of this component with the (partial)
                // state that was previously saved. Fields not in the
                // partial saved state are left with their original values.
                restoreDescendantComponentStates(this, false, rowState, false);
            }
        }
    }

    private void setRowIndexPreserveComponentState(int rowIndex)
    {
        if (rowIndex < -1)
        {
            throw new IllegalArgumentException("rowIndex is less than -1");
        }

        if (_rowIndex == rowIndex)
        {
            return;
        }

        FacesContext facesContext = getFacesContext();

        if (_initialDescendantFullComponentState != null)
        {
            //Just save the row
            Map<String, Object> sm = saveFullDescendantComponentStates(facesContext, null,
                                                                       getChildren().iterator(), false);
            if (sm != null && !sm.isEmpty())
            {
                _rowDeltaStates.put(getContainerClientId(facesContext), sm);
            }
            if (_rowIndex != -1)
            {
                _rowTransientStates.put(getContainerClientId(facesContext),
                        saveTransientDescendantComponentStates(facesContext, null, getChildren().iterator(), false));
            }
        }

        _rowIndex = rowIndex;

        DataModel dataModel = getDataModel();
        dataModel.setRowIndex(rowIndex);

        String var = (String) getStateHelper().get(PropertyKeys.var);
        if (rowIndex == -1)
        {
            if (var != null)
            {
                facesContext.getExternalContext().getRequestMap().remove(var);
            }
        }
        else
        {
            if (var != null)
            {
                if (isRowAvailable())
                {
                    Object rowData = dataModel.getRowData();
                    facesContext.getExternalContext().getRequestMap().put(var, rowData);
                }
                else
                {
                    facesContext.getExternalContext().getRequestMap().remove(var);
                }
            }
        }

        if (_initialDescendantFullComponentState != null)
        {
            Map<String, Object> rowState = _rowDeltaStates.get(getContainerClientId(facesContext));
            if (rowState == null)
            {
                //Restore as original
                restoreFullDescendantComponentStates(facesContext, getChildren().iterator(),
                        _initialDescendantFullComponentState, false);
            }
            else
            {
                //Restore first original and then delta
                restoreFullDescendantComponentDeltaStates(facesContext, getChildren().iterator(),
                        rowState, _initialDescendantFullComponentState, false);
            }
            if (_rowIndex == -1)
            {
                restoreTransientDescendantComponentStates(facesContext, getChildren().iterator(), null, false);
            }
            else
            {
                rowState = _rowTransientStates.get(getContainerClientId(facesContext));
                if (rowState == null)
                {
                    restoreTransientDescendantComponentStates(facesContext, getChildren().iterator(), null, false);
                }
                else
                {
                    restoreTransientDescendantComponentStates(facesContext, getChildren().iterator(), rowState, false);
                }
            }
        }

    }
    

    /**
     * Overwrite the state of the child components of this component with data previously saved by method
     * saveDescendantComponentStates.
     * <p>
     * The saved state info only covers those fields that are expected to vary between rows of a table. Other fields are
     * not modified.
     */
    @SuppressWarnings("unchecked")
    private void restoreDescendantComponentStates(UIComponent parent, boolean iterateFacets, Object state,
                                                  boolean restoreChildFacets)
    {
        int descendantStateIndex = -1;
        List<? extends Object[]> stateCollection = null;
        
        if (iterateFacets && parent.getFacetCount() > 0)
        {
            Iterator<UIComponent> childIterator = parent.getFacets().values().iterator();
            
            while (childIterator.hasNext())
            {
                UIComponent component = childIterator.next();

                // reset the client id (see spec 3.1.6)
                component.setId(component.getId());
                if (!component.isTransient())
                {
                    if (descendantStateIndex == -1)
                    {
                        stateCollection = ((List<? extends Object[]>) state);
                        descendantStateIndex = stateCollection.isEmpty() ? -1 : 0;
                    }
                    
                    if (descendantStateIndex != -1 && descendantStateIndex < stateCollection.size())
                    {
                        Object[] object = stateCollection.get(descendantStateIndex);
                        if (object[0] != null && component instanceof EditableValueHolder)
                        {
                            ((EditableValueHolderState) object[0]).restoreState((EditableValueHolder) component);
                        }

                        // If there is descendant state to restore, call it recursively, otherwise
                        // it is safe to skip iteration.
                        if (object[1] != null)
                        {
                            restoreDescendantComponentStates(component, restoreChildFacets, object[1], true);
                        }
                        else
                        {
                            restoreDescendantComponentWithoutRestoreState(component, restoreChildFacets, true);
                        }
                    }
                    else
                    {
                        restoreDescendantComponentWithoutRestoreState(component, restoreChildFacets, true);
                    }
                    descendantStateIndex++;
                }
            }
        }
        
        if (parent.getChildCount() > 0)
        {
            for (int i = 0; i < parent.getChildCount(); i++)
            {
                UIComponent component = parent.getChildren().get(i);

                // reset the client id (see spec 3.1.6)
                component.setId(component.getId());
                if (!component.isTransient())
                {
                    if (descendantStateIndex == -1)
                    {
                        stateCollection = ((List<? extends Object[]>) state);
                        descendantStateIndex = stateCollection.isEmpty() ? -1 : 0;
                    }
                    
                    if (descendantStateIndex != -1 && descendantStateIndex < stateCollection.size())
                    {
                        Object[] object = stateCollection.get(descendantStateIndex);
                        if (object[0] != null && component instanceof EditableValueHolder)
                        {
                            ((EditableValueHolderState) object[0]).restoreState((EditableValueHolder) component);
                        }

                        // If there is descendant state to restore, call it recursively, otherwise
                        // it is safe to skip iteration.
                        if (object[1] != null)
                        {
                            restoreDescendantComponentStates(component, restoreChildFacets, object[1], true);
                        }
                        else
                        {
                            restoreDescendantComponentWithoutRestoreState(component, restoreChildFacets, true);
                        }
                    }
                    else
                    {
                        restoreDescendantComponentWithoutRestoreState(component, restoreChildFacets, true);
                    }
                    descendantStateIndex++;
                }
            }
        }
    }

    /**
     * Just call component.setId(component.getId()) to reset all client ids and 
     * ensure they will be calculated for the current row, but do not waste time
     * dealing with row state code.
     * 
     * @param parent
     * @param iterateFacets
     * @param restoreChildFacets 
     */
    private void restoreDescendantComponentWithoutRestoreState(UIComponent parent, boolean iterateFacets,
                                                               boolean restoreChildFacets)
    {
        if (iterateFacets && parent.getFacetCount() > 0)
        {
            Iterator<UIComponent> childIterator = parent.getFacets().values().iterator();
            
            while (childIterator.hasNext())
            {
                UIComponent component = childIterator.next();

                // reset the client id (see spec 3.1.6)
                component.setId(component.getId());
                if (!component.isTransient())
                {
                    restoreDescendantComponentWithoutRestoreState(component, restoreChildFacets, true);
                }
            }
        }
        
        if (parent.getChildCount() > 0)
        {
            for (int i = 0; i < parent.getChildCount(); i++)
            {
                UIComponent component = parent.getChildren().get(i);

                // reset the client id (see spec 3.1.6)
                component.setId(component.getId());
                if (!component.isTransient())
                {
                    restoreDescendantComponentWithoutRestoreState(component, restoreChildFacets, true);
                }
            }
        }
    }

    /**
     * Walk the tree of child components of this UIData, saving the parts of their state that can vary between rows.
     * <p>
     * This is very similar to the process that occurs for normal components when the view is serialized. Transient
     * components are skipped (no state is saved for them).
     * <p>
     * If there are no children then null is returned. If there are one or more children, and all children are transient
     * then an empty collection is returned; this will happen whenever a table contains only read-only components.
     * <p>
     * Otherwise a collection is returned which contains an object for every non-transient child component; that object
     * may itself contain a collection of the state of that child's child components.
     */
    private Collection<Object[]> saveDescendantComponentStates(UIComponent parent, boolean iterateFacets,
                                                               boolean saveChildFacets)
    {
        Collection<Object[]> childStates = null;
        // Index to indicate how many components has been passed without state to save.
        int childEmptyIndex = 0;
        int totalChildCount = 0;
                
        if (iterateFacets && parent.getFacetCount() > 0)
        {
            Iterator<UIComponent> childIterator = parent.getFacets().values().iterator();

            while (childIterator.hasNext())
            {
                UIComponent child = childIterator.next();
                if (!child.isTransient())
                {
                    // Add an entry to the collection, being an array of two
                    // elements. The first element is the state of the children
                    // of this component; the second is the state of the current
                    // child itself.
                    if (child instanceof EditableValueHolder)
                    {
                        if (childStates == null)
                        {
                            childStates = new ArrayList<>(
                                    parent.getFacetCount()
                                    + parent.getChildCount()
                                    - totalChildCount
                                    + childEmptyIndex);
                            for (int ci = 0; ci < childEmptyIndex; ci++)
                            {
                                childStates.add(LEAF_NO_STATE);
                            }
                        }
                    
                        childStates.add(child.getChildCount() > 0
                                ? new Object[]{ new EditableValueHolderState((EditableValueHolder) child),
                                    saveDescendantComponentStates(child, saveChildFacets, true) }
                                : new Object[]{ new EditableValueHolderState((EditableValueHolder) child), null });
                    }
                    else if (child.getChildCount() > 0 || (saveChildFacets && child.getFacetCount() > 0))
                    {
                        Object descendantSavedState = saveDescendantComponentStates(child, saveChildFacets, true);
                        
                        if (descendantSavedState == null)
                        {
                            if (childStates == null)
                            {
                                childEmptyIndex++;
                            }
                            else
                            {
                                childStates.add(LEAF_NO_STATE);
                            }
                        }
                        else
                        {
                            if (childStates == null)
                            {
                                childStates = new ArrayList<>(
                                        parent.getFacetCount()
                                        + parent.getChildCount()
                                        - totalChildCount
                                        + childEmptyIndex);
                                for (int ci = 0; ci < childEmptyIndex; ci++)
                                {
                                    childStates.add(LEAF_NO_STATE);
                                }
                            }
                            childStates.add(new Object[]{null, descendantSavedState});
                        }
                    }
                    else
                    {
                        if (childStates == null)
                        {
                            childEmptyIndex++;
                        }
                        else
                        {
                            childStates.add(LEAF_NO_STATE);
                        }
                    }
                }
                totalChildCount++;
            }
        }
        
        if (parent.getChildCount() > 0)
        {
            for (int i = 0; i < parent.getChildCount(); i++)
            {
                UIComponent child = parent.getChildren().get(i);
                if (!child.isTransient())
                {
                    // Add an entry to the collection, being an array of two
                    // elements. The first element is the state of the children
                    // of this component; the second is the state of the current
                    // child itself.

                    if (child instanceof EditableValueHolder)
                    {
                        if (childStates == null)
                        {
                            childStates = new ArrayList<>(
                                    parent.getFacetCount()
                                    + parent.getChildCount()
                                    - totalChildCount
                                    + childEmptyIndex);
                            for (int ci = 0; ci < childEmptyIndex; ci++)
                            {
                                childStates.add(LEAF_NO_STATE);
                            }
                        }
                    
                        childStates.add(child.getChildCount() > 0
                                ? new Object[]{ new EditableValueHolderState((EditableValueHolder) child),
                                    saveDescendantComponentStates(child, saveChildFacets, true) }
                                : new Object[]{ new EditableValueHolderState((EditableValueHolder) child), null });
                    }
                    else if (child.getChildCount() > 0 || (saveChildFacets && child.getFacetCount() > 0))
                    {
                        Object descendantSavedState = saveDescendantComponentStates(child, saveChildFacets, true);
                        if (descendantSavedState == null)
                        {
                            if (childStates == null)
                            {
                                childEmptyIndex++;
                            }
                            else
                            {
                                childStates.add(LEAF_NO_STATE);
                            }
                        }
                        else
                        {
                            if (childStates == null)
                            {
                                childStates = new ArrayList<>(
                                        parent.getFacetCount()
                                        + parent.getChildCount()
                                        - totalChildCount
                                        + childEmptyIndex);
                                for (int ci = 0; ci < childEmptyIndex; ci++)
                                {
                                    childStates.add(LEAF_NO_STATE);
                                }
                            }
                            childStates.add(new Object[]{null, descendantSavedState});
                        }
                    }
                    else
                    {
                        if (childStates == null)
                        {
                            childEmptyIndex++;
                        }
                        else
                        {
                            childStates.add(LEAF_NO_STATE);
                        }
                    }
                }
                totalChildCount++;
            }
        }
        
        return childStates;
    }
    
    
    
    @Override
    public void markInitialState()
    {
        if (isRowStatePreserved() && 
            getFacesContext().getAttributes().containsKey(StateManager.IS_BUILDING_INITIAL_STATE))
        {
            _initialDescendantFullComponentState
                    = saveDescendantInitialComponentStates(getFacesContext(), getChildren().iterator(), false);
        }
        super.markInitialState();
    }

    private void restoreFullDescendantComponentStates(FacesContext facesContext,
            Iterator<UIComponent> childIterator, Object initialState,
            boolean restoreChildFacets)
    {
        Iterator<? extends Object[]> descendantStateIterator = null;
        while (childIterator.hasNext())
        {
            if (descendantStateIterator == null && initialState != null)
            {
                descendantStateIterator = ((Collection<? extends Object[]>) initialState).iterator();
            }
            
            UIComponent component = childIterator.next();
            // reset the client id (see spec 3.1.6)
            component.setId(component.getId());

            if (!component.isTransient())
            {
                Object childState = null;
                Object descendantState = null;
                String childId = null;
                if (descendantStateIterator != null && descendantStateIterator.hasNext())
                {
                    do
                    {
                        Object[] object = descendantStateIterator.next();
                        childState = object[0];
                        descendantState = object[1];
                        childId = (String) object[2];
                    }
                    while(descendantStateIterator.hasNext() && !component.getId().equals(childId));
                    
                    if (!component.getId().equals(childId))
                    {
                        // cannot apply initial state to components correctly.
                        throw new IllegalStateException("Cannot restore row correctly.");
                    }
                }
                
                component.clearInitialState();
                component.restoreState(facesContext, childState);
                component.markInitialState();
                
                Iterator<UIComponent> childsIterator = restoreChildFacets
                        ? component.getFacetsAndChildren()
                        : component.getChildren().iterator();
                restoreFullDescendantComponentStates(facesContext, childsIterator, descendantState, true);
            }
        }
    }

    private Collection<Object[]> saveDescendantInitialComponentStates(FacesContext facesContext,
            Iterator<UIComponent> childIterator, boolean saveChildFacets)
    {
        Collection<Object[]> childStates = null;
        while (childIterator.hasNext())
        {
            UIComponent child = childIterator.next();
            if (!child.isTransient())
            {
                Iterator<UIComponent> childsIterator = saveChildFacets
                        ? child.getFacetsAndChildren()
                        : child.getChildren().iterator();
                Object descendantState = saveDescendantInitialComponentStates(facesContext, childsIterator, true);
                Object state = null;
                if (child.initialStateMarked())
                {
                    child.clearInitialState();
                    state = child.saveState(facesContext); 
                    child.markInitialState();
                }
                else
                {
                    state = child.saveState(facesContext);
                }

                // Add an entry to the collection, being an array of two elements.
                // The first element is the state of the children of this component;
                // the second is the state of the current child itself.
                if (childStates == null)
                {
                    childStates = new ArrayList<>();
                }
                childStates.add(new Object[] { state, descendantState, child.getId()});
            }
        }
        return childStates;
    }
    
    private Map<String,Object> saveFullDescendantComponentStates(FacesContext facesContext, Map<String,Object> stateMap,
            Iterator<UIComponent> childIterator, boolean saveChildFacets)
    {
        while (childIterator.hasNext())
        {
            UIComponent child = childIterator.next();
            if (!child.isTransient())
            {
                // Add an entry to the collection, being an array of two
                // elements. The first element is the state of the children
                // of this component; the second is the state of the current
                // child itself.
                Iterator<UIComponent> childsIterator = saveChildFacets 
                        ? child.getFacetsAndChildren()
                        : child.getChildren().iterator();
                stateMap = saveFullDescendantComponentStates(facesContext, stateMap, childsIterator, true);
                Object state = child.saveState(facesContext);
                if (state != null)
                {
                    if (stateMap == null)
                    {
                        stateMap = new HashMap<>();
                    }
                    stateMap.put(child.getClientId(facesContext), state);
                }
            }
        }
        return stateMap;
    }
    
    private void restoreFullDescendantComponentDeltaStates(FacesContext facesContext,
            Iterator<UIComponent> childIterator, Map<String, Object> state, Object initialState,
            boolean restoreChildFacets)
    {
        Iterator<? extends Object[]> descendantFullStateIterator = null;
        while (childIterator.hasNext())
        {
            if (descendantFullStateIterator == null && initialState != null)
            {
                descendantFullStateIterator = ((Collection<? extends Object[]>) initialState).iterator();
            }

            UIComponent component = childIterator.next();
            // reset the client id (see spec 3.1.6)
            component.setId(component.getId());
            
            if (!component.isTransient())
            {
                Object childInitialState = null;
                Object descendantInitialState = null;
                Object childState = null;
                String childId = null;
                childState = (state == null) ? null : state.get(component.getClientId(facesContext));

                if (descendantFullStateIterator != null && descendantFullStateIterator.hasNext())
                {
                    do
                    {
                        Object[] object = descendantFullStateIterator.next();
                        childInitialState = object[0];
                        descendantInitialState = object[1];
                        childId = (String) object[2];
                    } while(descendantFullStateIterator.hasNext() && !component.getId().equals(childId));
                    
                    if (!component.getId().equals(childId))
                    {
                        // cannot apply initial state to components correctly. State is corrupt
                        throw new IllegalStateException("Cannot restore row correctly.");
                    }
                }
                
                component.clearInitialState();
                if (childInitialState != null)
                {
                    component.restoreState(facesContext, childInitialState);
                    component.markInitialState();
                    component.restoreState(facesContext, childState);
                }
                else
                {
                    component.restoreState(facesContext, childState);
                    component.markInitialState();
                }
                
                Iterator<UIComponent> childsIterator = restoreChildFacets
                        ? component.getFacetsAndChildren()
                        : component.getChildren().iterator();
                restoreFullDescendantComponentDeltaStates(facesContext, childsIterator, state,
                        descendantInitialState , true);
            }
        }
    }
    
    private void restoreTransientDescendantComponentStates(FacesContext facesContext,
                                                           Iterator<UIComponent> childIterator,
                                                           Map<String, Object> state,
                                                           boolean restoreChildFacets)
    {
        while (childIterator.hasNext())
        {
            UIComponent component = childIterator.next();

            // reset the client id (see spec 3.1.6)
            component.setId(component.getId());
            if (!component.isTransient())
            {
                component.restoreTransientState(facesContext,
                        state == null ? null : state.get(component.getClientId(facesContext)));
                
                Iterator<UIComponent> childsIterator = restoreChildFacets
                        ? component.getFacetsAndChildren()
                        : component.getChildren().iterator();
                restoreTransientDescendantComponentStates(facesContext, childsIterator, state, true);
            }
        }

    }
    
    private Map<String, Object> saveTransientDescendantComponentStates(FacesContext facesContext,
                                                                       Map<String, Object> childStates,
                                                                       Iterator<UIComponent> childIterator,
                                                                       boolean saveChildFacets)
    {
        while (childIterator.hasNext())
        {
            UIComponent child = childIterator.next();
            if (!child.isTransient())
            {
                Iterator<UIComponent> childsIterator = saveChildFacets
                        ? child.getFacetsAndChildren()
                        : child.getChildren().iterator();
                childStates = saveTransientDescendantComponentStates(facesContext, childStates, childsIterator, true);
                Object state = child.saveTransientState(facesContext);
                if (state != null)
                {
                    if (childStates == null)
                    {
                        childStates = new HashMap<>();
                    }
                    childStates.put(child.getClientId(facesContext), state);
                }
            }
        }
        return childStates;
    }

    @Override
    public void restoreState(FacesContext context, Object state)
    {
        if (state == null)
        {
            return;
        }
        
        Object values[] = (Object[]) state;
        super.restoreState(context, values[0]);

        Object restoredRowStates = UIComponentBase.restoreAttachedState(context, values[1]);
        if (restoredRowStates == null)
        {
            if (!_rowDeltaStates.isEmpty())
            {
                _rowDeltaStates.clear();
            }
        }
        else
        {
            _rowDeltaStates = (Map<String, Map<String, Object> >) restoredRowStates;
        }

        if (values.length > 2)
        {
            Object rs = UIComponentBase.restoreAttachedState(context, values[2]);
            if (rs == null)
            {
                if (!_rowStates.isEmpty())
                {
                    _rowStates.clear();
                }
            }
            else
            {
                _rowStates = (Map<String, Object>) rs;
            }
        }
        if (values.length > 3)
        {
            Object rs = UIComponentBase.restoreAttachedState(context, values[3]);
            if (rs == null)
            {
                if (!_rowTransientStates.isEmpty())
                {
                    _rowTransientStates.clear();
                }
            }
            else
            {
                _rowTransientStates = (Map<String, Map<String, Object> >) rs;
            }
        }
    }

    @Override
    public Object saveState(FacesContext context)
    {
        if (context.getViewRoot() != null)
        {
            if (context.getViewRoot().getResetSaveStateMode() == RESET_MODE_SOFT)
            {
                _dataModelMap.clear();
                _isValidChilds = true;
                _rowTransientStates.clear();
            }
            if (context.getViewRoot().getResetSaveStateMode() == RESET_MODE_HARD)
            {
                _dataModelMap.clear();
                _isValidChilds = true;
                _rowTransientStates.clear();
                _rowStates.clear();
                _rowDeltaStates.clear();
            }
        }

        if (initialStateMarked())
        {
            Object parentSaved = super.saveState(context);
            if (context.getCurrentPhaseId() != null && 
                !PhaseId.RENDER_RESPONSE.equals(context.getCurrentPhaseId()))
            {
                if (parentSaved == null &&_rowDeltaStates.isEmpty() && _rowStates.isEmpty())
                {
                    return null;
                }
                else
                {
                    Object values[] = new Object[4];
                    values[0] = super.saveState(context);
                    values[1] = UIComponentBase.saveAttachedState(context, _rowDeltaStates);
                    values[2] = UIComponentBase.saveAttachedState(context, _rowStates);
                    values[3] = UIComponentBase.saveAttachedState(context, _rowTransientStates);
                    return values;
                }
            }
            else
            {
                if (parentSaved == null &&_rowDeltaStates.isEmpty())
                {
                    return null;
                }
                else
                {
                    Object values[] = new Object[2];
                    values[0] = super.saveState(context);
                    values[1] = UIComponentBase.saveAttachedState(context, _rowDeltaStates);
                    return values; 
                }
            }
        }
        else
        {
            if (context.getCurrentPhaseId() != null && !PhaseId.RENDER_RESPONSE.equals(context.getCurrentPhaseId()))
            {
                Object values[] = new Object[4];
                values[0] = super.saveState(context);
                values[1] = UIComponentBase.saveAttachedState(context, _rowDeltaStates);
                values[2] = UIComponentBase.saveAttachedState(context, _rowStates);
                values[3] = UIComponentBase.saveAttachedState(context, _rowTransientStates);
                return values; 
            }
            else
            {
                Object values[] = new Object[2];
                values[0] = super.saveState(context);
                values[1] = UIComponentBase.saveAttachedState(context, _rowDeltaStates);
                return values;
            }
        }
    }

    @Override
    public void setValueExpression(String name, ValueExpression binding)
    {
        if (name == null)
        {
            throw new NullPointerException("name");
        }
        else if (name.equals("value"))
        {
            _dataModelMap.clear();
        }
        else if (name.equals("rowIndex"))
        {
            throw new IllegalArgumentException("name " + name);
        }
        super.setValueExpression(name, binding);
    }

    @Override
    public String getContainerClientId(FacesContext context)
    {
        //MYFACES-2744 UIData.getClientId() should not append rowIndex, instead use UIData.getContainerClientId()
        String clientId = super.getContainerClientId(context);
        
        int rowIndex = getRowIndex();
        if (rowIndex == -1)
        {
            return clientId;
        }

        StringBuilder bld = _getSharedStringBuilder(context);
        return bld.append(clientId).append(context.getNamingContainerSeparatorChar()).append(rowIndex).toString();
    }

    /**
     * Modify events queued for any child components so that the UIData state will be correctly configured before the
     * event's listeners are executed.
     * <p>
     * Child components or their renderers may register events against those child components. When the listener for
     * that event is eventually invoked, it may expect the uidata's rowData and rowIndex to be referring to the same
     * object that caused the event to fire.
     * <p>
     * The original queueEvent call against the child component has been forwarded up the chain of ancestors in the
     * standard way, making it possible here to wrap the event in a new event whose source is <i>this</i> component, not
     * the original one. When the event finally is executed, this component's broadcast method is invoked, which ensures
     * that the UIData is set to be at the correct row before executing the original event.
     */
    @Override
    public void queueEvent(FacesEvent event)
    {
        if (event == null)
        {
            throw new NullPointerException("event");
        }
        super.queueEvent(new FacesEventWrapper(event, getRowIndex(), this));
    }

    /**
     * Ensure that before the event's listeners are invoked this UIData component's "current row" is set to the row
     * associated with the event.
     * <p>
     * See queueEvent for more details.
     */
    @Override
    public void broadcast(FacesEvent event) throws AbortProcessingException
    {
        if (event instanceof FacesEventWrapper)
        {
            FacesEvent originalEvent = ((FacesEventWrapper) event).getWrappedFacesEvent();
            int eventRowIndex = ((FacesEventWrapper) event).getRowIndex();
            final int currentRowIndex = getRowIndex();
            UIComponent source = originalEvent.getComponent();
            UIComponent compositeParent = UIComponent.getCompositeComponentParent(source);

            setRowIndex(eventRowIndex);
            if (compositeParent != null)
            {
                pushComponentToEL(getFacesContext(), compositeParent);
            }

            pushComponentToEL(getFacesContext(), source);

            try
            {
                source.broadcast(originalEvent);
            }
            finally
            {
                source.popComponentFromEL(getFacesContext());
                if (compositeParent != null)
                {
                    compositeParent.popComponentFromEL(getFacesContext());
                }
                setRowIndex(currentRowIndex);
            }
        }
        else
        {
            super.broadcast(event);
        }
    }

    /**
     * 
     * {@inheritDoc}
     * 
     * @since 2.0
     */
    @Override
    public String createUniqueId(FacesContext context, String seed)
    {
        StringBuilder bld = _getSharedStringBuilder(context);

        // Generate an identifier for a component. The identifier will be prefixed with UNIQUE_ID_PREFIX,
        // and will be unique within this UIViewRoot.
        if(seed == null)
        {
            Long uniqueIdCounter = (Long) getStateHelper().get(PropertyKeys.uniqueIdCounter);
            uniqueIdCounter = (uniqueIdCounter == null) ? 0 : uniqueIdCounter;
            getStateHelper().put(PropertyKeys.uniqueIdCounter, (uniqueIdCounter+1L));
            return bld.append(UIViewRoot.UNIQUE_ID_PREFIX).append(uniqueIdCounter).toString();    
        }
        // Optionally, a unique seed value can be supplied by component creators
        // which should be included in the generated unique id.
        else
        {
            return bld.append(UIViewRoot.UNIQUE_ID_PREFIX).append(seed).toString();
        }
    }

    /**
     * Perform necessary actions when rendering of this component starts, before delegating to the inherited
     * implementation which calls the associated renderer's encodeBegin method.
     */
    @Override
    public void encodeBegin(FacesContext context) throws IOException
    {
        _initialDescendantComponentState = null;
        if (_isValidChilds && !hasErrorMessages(context))
        {
            // Clear the data model so that when rendering code calls
            // getDataModel a fresh model is fetched from the backing
            // bean via the value-binding.
            _dataModelMap.clear();

            // When the data model is cleared it is also necessary to
            // clear the saved row state, as there is an implicit 1:1
            // relation between objects in the _rowStates and the
            // corresponding DataModel element.
            if (!isRowStatePreserved())
            {
                _rowStates.clear();
            }
        }
        super.encodeBegin(context);
    }

    private boolean hasErrorMessages(FacesContext context)
    {
        // perf: getMessageList() return a RandomAccess instance.
        // See org.apache.myfaces.context.servlet.FacesContextImpl.addMessage
        List<FacesMessage> messageList = context.getMessageList();
        for (int i = 0, size = messageList.size(); i < size;  i++)
        {
            FacesMessage message = messageList.get(i);
            if (FacesMessage.SEVERITY_ERROR.compareTo(message.getSeverity()) <= 0)
            {
                return true;
            }
        }
        return false;
    }

    /**
     * @see javax.faces.component.UIComponentBase#encodeEnd(javax.faces.context.FacesContext)
     */
    @Override
    public void encodeEnd(FacesContext context) throws IOException
    {
        try
        {
            setCachedFacesContext(context);
            setRowIndex(-1);
        }
        finally
        {
            setCachedFacesContext(null);
        }
        super.encodeEnd(context);
    }

    @Override
    public void processDecodes(FacesContext context)
    {
        if (context == null)
        {
            throw new NullPointerException("context");
        }
        try
        {
            setCachedFacesContext(context);
            pushComponentToEL(context, this);
            if (!isRendered())
            {
                return;
            }

            setRowIndex(-1);
            processFacets(context, PROCESS_DECODES);
            processColumnFacets(context, PROCESS_DECODES);
            processColumnChildren(context, PROCESS_DECODES);
            setRowIndex(-1);

            try
            {
                decode(context);
            }
            catch (RuntimeException e)
            {
                context.renderResponse();
                throw e;
            }
        }
        finally
        {
            popComponentFromEL(context);
            setCachedFacesContext(null);
        }
    }

    @Override
    public void processValidators(FacesContext context)
    {
        if (context == null)
        {
            throw new NullPointerException("context");
        }

        try
        {
            setCachedFacesContext(context);
            pushComponentToEL(context, this);
            if (!isRendered())
            {
                return;
            }
            
            //Pre validation event dispatch for component
            context.getApplication().publishEvent(context,  PreValidateEvent.class, getClass(), this);
            
            try
            {
                setRowIndex(-1);
                processFacets(context, PROCESS_VALIDATORS);
                processColumnFacets(context, PROCESS_VALIDATORS);
                processColumnChildren(context, PROCESS_VALIDATORS);
                setRowIndex(-1);
            }
            finally
            {
                context.getApplication().publishEvent(context,  PostValidateEvent.class, getClass(), this);
            }
            
            // check if an validation error forces the render response for our data
            if (context.getRenderResponse())
            {
                _isValidChilds = false;
            }
        }
        finally
        {
            popComponentFromEL(context);
            setCachedFacesContext(null);
        }
    }

    @Override
    public void processUpdates(FacesContext context)
    {
        if (context == null)
        {
            throw new NullPointerException("context");
        }
        try
        {
            setCachedFacesContext(context);
            pushComponentToEL(context, this);
            if (!isRendered())
            {
                return;
            }

            setRowIndex(-1);
            processFacets(context, PROCESS_UPDATES);
            processColumnFacets(context, PROCESS_UPDATES);
            processColumnChildren(context, PROCESS_UPDATES);
            setRowIndex(-1);
    
            if (context.getRenderResponse())
            {
                _isValidChilds = false;
            }
        }
        finally
        {
            popComponentFromEL(context);
            setCachedFacesContext(null);
        }
    }

    private void processFacets(FacesContext context, int processAction)
    {
        if (this.getFacetCount() > 0)
        {
            for (UIComponent facet : getFacets().values())
            {
                process(context, facet, processAction);
            }
        }
    }

    /**
     * Invoke the specified phase on all facets of all UIColumn children of this component. Note that no methods are
     * called on the UIColumn child objects themselves.
     * 
     * @param context
     *            is the current faces context.
     * @param processAction
     *            specifies a JSF phase: decode, validate or update.
     */
    private void processColumnFacets(FacesContext context, int processAction)
    {
        for (int i = 0, childCount = getChildCount(); i < childCount; i++)
        {
            UIComponent child = getChildren().get(i);
            if (child instanceof UIColumn)
            {
                if (!ComponentUtils.isRendered(context, child))
                {
                    // Column is not visible
                    continue;
                }
                
                if (child.getFacetCount() > 0)
                {
                    for (UIComponent facet : child.getFacets().values())
                    {
                        process(context, facet, processAction);
                    }
                }
            }
        }
    }

    /**
     * Invoke the specified phase on all non-facet children of all UIColumn children of this component. Note that no
     * methods are called on the UIColumn child objects themselves.
     * 
     * @param context
     *            is the current faces context.
     * @param processAction
     *            specifies a JSF phase: decode, validate or update.
     */
    private void processColumnChildren(FacesContext context, int processAction)
    {
        int first = getFirst();
        int rows = getRows();
        int last;
        if (rows == 0)
        {
            last = getRowCount();
        }
        else
        {
            last = first + rows;
        }
        for (int rowIndex = first; last == -1 || rowIndex < last; rowIndex++)
        {
            setRowIndex(rowIndex);

            // scrolled past the last row
            if (!isRowAvailable())
            {
                break;
            }
            
            for (int i = 0, childCount = getChildCount(); i < childCount; i++)
            {
                UIComponent child = getChildren().get(i);
                if (child instanceof UIColumn)
                {
                    if (!ComponentUtils.isRendered(context, child))
                    {
                        // Column is not visible
                        continue;
                    }

                    for (int j = 0, columnChildCount = child.getChildCount(); j < columnChildCount; j++)
                    {
                        UIComponent columnChild = child.getChildren().get(j);
                        process(context, columnChild, processAction);
                    }
                }
            }
        }
    }

    private void process(FacesContext context, UIComponent component, int processAction)
    {
        switch (processAction)
        {
            case PROCESS_DECODES:
                component.processDecodes(context);
                break;
            case PROCESS_VALIDATORS:
                component.processValidators(context);
                break;
            case PROCESS_UPDATES:
                component.processUpdates(context);
                break;
            default:
                // do nothing
        }
    }

    /**
     * Return the datamodel for this table, potentially fetching the data from a backing bean via a value-binding if
     * this is the first time this method has been called.
     * <p>
     * This is complicated by the fact that this table may be nested within another table. In this case a different
     * datamodel should be fetched for each row. When nested within a parent table, the parent reference won't change
     * but parent.getContainerClientId() will, as the suffix changes
     * depending upon the current row index. A map object on this
     * component is therefore used to cache the datamodel for each row of the table. In the normal case where this table
     * is not nested inside a component that changes its id (like a table does) then this map only ever has one entry.
     */
    protected DataModel getDataModel()
    {
        DataModel dataModel;
        String clientID = "";

        UIComponent parent = getParent();
        if (parent != null)
        {
            clientID = parent.getContainerClientId(getFacesContext());
        }
        dataModel = _dataModelMap.get(clientID);
        if (dataModel == null)
        {
            dataModel = createDataModel();
            _dataModelMap.put(clientID, dataModel);
        }
        return dataModel;
    }

    protected void setDataModel(DataModel dataModel)
    {
        String clientID = "";

        UIComponent parent = getParent();
        if (parent != null)
        {
            clientID = parent.getContainerClientId(getFacesContext());
        }
        if (dataModel == null)
        {
            _dataModelMap.remove(clientID);
        }
        else
        {
            _dataModelMap.put(clientID, dataModel);
        }
    }

    /**
     * Evaluate this object's value property and convert the result into a DataModel. Normally this object's value
     * property will be a value-binding which will cause the value to be fetched from some backing bean.
     * <p>
     * The result of fetching the value may be a DataModel object, in which case that object is returned directly. If
     * the value is of type List, Array, ResultSet, Result, other object or null then an appropriate wrapper is created
     * and returned.
     * <p>
     * Null is never returned by this method.
     */
    private DataModel createDataModel()
    {
        Object value = getValue();

        if (value == null)
        {
            return EMPTY_DATA_MODEL;
        }
        else if (value instanceof DataModel)
        {
            return (DataModel) value;
        }
        else
        {
            DataModel dataModel = null;
            if (FACES_DATA_MODEL_MANAGER_CLASS != null && value != null)
            {
                try
                {
                    dataModel = (DataModel) FACES_DATA_MODEL_MANAGER_CREATE_DATAMODEL_METHOD.invoke(null,
                            getFacesContext(), value.getClass(), value);
                }
                catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex)
                {
                    //No op
                }
            }

            if (dataModel == null)
            {
                if (value instanceof List)
                {
                    return new ListDataModel((List<?>) value);
                }
                else if (OBJECT_ARRAY_CLASS.isAssignableFrom(value.getClass()))
                {
                    return new ArrayDataModel((Object[]) value);
                }
                else if (value instanceof ResultSet)
                {
                    return new ResultSetDataModel((ResultSet) value);
                }
                else if (value instanceof Result)
                {
                    return new ResultDataModel((Result) value);
                }
                else if (value instanceof Iterable)
                {
                    return new IterableDataModel<>((Iterable<?>) value);
                } 
                else if (value instanceof Map) 
                {
                    return new IterableDataModel<>(((Map<?, ?>) value).entrySet());
                }
                else if (value instanceof Collection)
                {
                    return new CollectionDataModel((Collection) value);
                }
                else
                {
                    return new ScalarDataModel(value);
                }
            }
            else
            {
                return dataModel;
            }
        }
    }

    /**
     * An EL expression that specifies the data model that backs this table.
     * <p>
     * The value referenced by the EL expression can be of any type.
     * </p>
     * <ul>
     * <li>A value of type DataModel is used directly.</li>
     * <li>Array-like parameters of type array-of-Object, java.util.List, java.sql.ResultSet or
     * javax.servlet.jsp.jstl.sql.Result are wrapped in a corresponding DataModel that knows how to iterate over the
     * elements.</li>
     * <li>Other values are wrapped in a DataModel as a single row.</li>
     * </ul>
     * <p>
     * Note in particular that unordered collections, eg Set are not supported. Therefore if the value expression
     * references such an object then the table will be considered to contain just one element - the collection itself.
     * </p>
     */
    @JSFProperty
    public Object getValue()
    {
        return getStateHelper().eval(PropertyKeys.value);
    }

    public void setValue(Object value)
    {
        getStateHelper().put(PropertyKeys.value, value);
        _dataModelMap.clear();
        _rowStates.clear();
        _isValidChilds = true;
    }

    /**
     * Defines the index of the first row to be displayed, starting from 0.
     */
    @JSFProperty
    public int getFirst()
    {
        return (Integer) getStateHelper().eval(PropertyKeys.first,0);
    }

    public void setFirst(int first)
    { 
        if (first < 0)
        {
            throw new IllegalArgumentException("Illegal value for first row: " + first);
        }
        getStateHelper().put(PropertyKeys.first, first );
    }

    /**
     * Defines the maximum number of rows of data to be displayed.
     * <p>
     * Specify zero to display all rows from the "first" row to the end of available data.
     * </p>
     */
    @JSFProperty
    public int getRows()
    {
        return (Integer) getStateHelper().eval(PropertyKeys.rows,0);
    }

    /**
     * Set the maximum number of rows displayed in the table.
     */
    public void setRows(int rows)
    {
        if (rows < 0)
        {
            throw new IllegalArgumentException("rows: " + rows);
        }
        getStateHelper().put(PropertyKeys.rows, rows ); 
    }

    /**
     * Defines the name of the request-scope variable that will hold the current row during iteration.
     * <p>
     * During rendering of child components of this UIData, the variable with this name can be read to learn what the
     * "rowData" object for the row currently being rendered is.
     * </p>
     * <p>
     * This value must be a static value, ie an EL expression is not permitted.
     * </p>
     */
    @JSFProperty(literalOnly = true)
    public String getVar()
    {
        return (String) getStateHelper().get(PropertyKeys.var);
    }

    /**
     * Overrides the behavior in 
     * UIComponent.visitTree(javax.faces.component.visit.VisitContext, javax.faces.component.visit.VisitCallback)
     * to handle iteration correctly.
     * 
     * @param context the visit context which handles the processing details
     * @param callback the callback to be performed
     * @return false if the processing is not done true if we can shortcut
     * the visiting because we are done with everything
     * 
     * @since 2.0
     */
    @Override
    public boolean visitTree(VisitContext context, VisitCallback callback)
    {
        boolean skipIterationHint = context.getHints().contains(VisitHint.SKIP_ITERATION);
        if (skipIterationHint)
        {
            return super.visitTree(context, callback);
        }

        // push the Component to EL
        pushComponentToEL(context.getFacesContext(), this);
        try
        {
            if (!isVisitable(context))
            {
                return false;
            }

            boolean isCachedFacesContext = isCachedFacesContext();
            if (!isCachedFacesContext)
            {
                setCachedFacesContext(context.getFacesContext());
            }

            // save the current row index
            int oldRowIndex = getRowIndex();
            // set row index to -1 to process the facets and to get the rowless clientId
            setRowIndex(-1);
            try
            {
                VisitResult visitResult = context.invokeVisitCallback(this, callback);
                switch (visitResult)
                {
                    case COMPLETE:
                        //we are done nothing has to be processed anymore
                        return true;
                    case REJECT:
                        return false;
                    default:
                        // accept; determine if we need to visit our children
                        Collection<String> subtreeIdsToVisit = context.getSubtreeIdsToVisit(this);
                        boolean doVisitChildren = subtreeIdsToVisit != null && !subtreeIdsToVisit.isEmpty();
                        if (doVisitChildren)
                        {
                            // visit the facets of the component
                            if (getFacetCount() > 0)
                            {
                                for (UIComponent facet : getFacets().values())
                                {
                                    if (facet.visitTree(context, callback))
                                    {
                                        return true;
                                    }
                                }
                            }

                            if (skipIterationHint)
                            {
                                // If SKIP_ITERATION is enabled, do not take into account rows.
                                for (int i = 0, childCount = getChildCount(); i < childCount; i++ )
                                {
                                    UIComponent child = getChildren().get(i);
                                    if (child.visitTree(context, callback))
                                    {
                                        return true;
                                    }
                                }
                            }
                            else
                            {
                                // visit every column directly without visiting its children
                                // (the children of every UIColumn will be visited later for
                                // every row) and also visit the column's facets
                                for (int i = 0, childCount = getChildCount(); i < childCount; i++)
                                {
                                    UIComponent child = getChildren().get(i);
                                    if (child instanceof UIColumn)
                                    {
                                        VisitResult columnResult = context.invokeVisitCallback(child, callback);
                                        if (columnResult == VisitResult.COMPLETE)
                                        {
                                            return true;
                                        }
                                        if (child.getFacetCount() > 0)
                                        {
                                            for (UIComponent facet : child.getFacets().values())
                                            {
                                                if (facet.visitTree(context, callback))
                                                {
                                                    return true;
                                                }
                                            }
                                        }
                                    }
                                }
                                // iterate over the rows
                                int rowsToProcess = getRows();
                                // if getRows() returns 0, all rows have to be processed
                                if (rowsToProcess == 0)
                                {
                                    rowsToProcess = getRowCount();
                                }
                                int rowIndex = getFirst();
                                for (int rowsProcessed = 0; rowsProcessed < rowsToProcess; rowsProcessed++, rowIndex++)
                                {
                                    setRowIndex(rowIndex);
                                    if (!isRowAvailable())
                                    {
                                        return false;
                                    }
                                    // visit the children of every child of the UIData that is an instance of UIColumn
                                    for (int i = 0, childCount = getChildCount(); i < childCount; i++)
                                    {
                                        UIComponent child = getChildren().get(i);
                                        if (child instanceof UIColumn)
                                        {
                                            for (int j = 0, grandChildCount = child.getChildCount();
                                                 j < grandChildCount; j++)
                                            {
                                                UIComponent grandchild = child.getChildren().get(j);
                                                if (grandchild.visitTree(context, callback))
                                                {
                                                    return true;
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                }
            }
            finally
            {
                // restore the old row index
                setRowIndex(oldRowIndex);
                if (!isCachedFacesContext)
                {
                    setCachedFacesContext(null);
                }
            }
        }
        finally
        {
            // pop the component from EL
            popComponentFromEL(context.getFacesContext());
        }
        // Return false to allow the visiting to continue
        return false;
    }

    public void setVar(String var)
    {
        getStateHelper().put(PropertyKeys.var, var ); 
    }
    
    /**
     * Indicates whether the state for a component in each row should not be 
     * discarded before the datatable is rendered again.
     * 
     * This will only work reliable if the datamodel of the 
     * datatable did not change either by sorting, removing or 
     * adding rows. Default: false
     * 
     * @return
     */
    @JSFProperty(literalOnly=true, faceletsOnly=true)
    public boolean isRowStatePreserved()
    {
        Boolean b = (Boolean) getStateHelper().get(PropertyKeys.rowStatePreserved);
        return b == null ? false : b; 
    }
    
    public void setRowStatePreserved(boolean preserveComponentState)
    {
        getStateHelper().put(PropertyKeys.rowStatePreserved, preserveComponentState);
    }

    enum PropertyKeys
    {
        value,
        first,
        rows,
        var,
        uniqueIdCounter,
        rowStatePreserved
    }

    @Override
    public String getFamily()
    {
        return COMPONENT_FAMILY;
    }
}
