Package org.apache.myfaces.custom.crosstable

Source Code of org.apache.myfaces.custom.crosstable.UIColumns$EditableValueHolderState

/*
* Copyright 2004 The Apache Software Foundation.
*
* Licensed 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 org.apache.myfaces.custom.crosstable;

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.faces.component.EditableValueHolder;
import javax.faces.component.UIComponent;
import javax.faces.component.UIData;
import javax.faces.context.FacesContext;
import javax.faces.el.ValueBinding;
import javax.faces.model.ArrayDataModel;
import javax.faces.model.DataModel;
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;

/**
* @author Mathias Broekelmann (latest modification by $Author: mbr $)
* @version $Revision: 290681 $ $Date: 2005-09-21 07:10:54 -0400 (Wed, 21 Sep 2005) $
*/
public class UIColumns extends UIData
{
    public static final String COMPONENT_TYPE = "org.apache.myfaces.Columns";

    private static final Class OBJECT_ARRAY_CLASS = (new Object[0]).getClass();
    private static final int PROCESS_DECODES = 1;
    private static final int PROCESS_VALIDATORS = 2;
    private static final int PROCESS_UPDATES = 3;

    private boolean _isValidChilds = true;

    // holds the the state for each cell of the child components of this UIColumns
    private Map _cellStates = new HashMap();

    private Object _initialDescendantComponentState = null;

    private int _colIndex = -1;
    private UIData _parentUIData;

    private Map _dataModelMap = new HashMap();

    /**
     *
     */
    public UIColumns()
    {
        super();
    }

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

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

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

    public int getRowIndex()
    {
        return _colIndex;
    }

    public void setRowIndex(int colIndex)
    {
        if (colIndex < -1)
        {
            throw new IllegalArgumentException("colIndex is less than -1");
        }

        if (_colIndex == colIndex)
        {
            return;
        }

        FacesContext facesContext = getFacesContext();

        if (_colIndex == -1)
        {
            if (_initialDescendantComponentState == null)
            {
                _initialDescendantComponentState = saveDescendantComponentStates(getFacetsAndChildren());
            }
        }
        else
        {
            _cellStates.put(getClientId(facesContext),
                    saveDescendantComponentStates(getFacetsAndChildren()));
        }

        _colIndex = colIndex;

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

        String var = getVar();
        if (colIndex == -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 (_colIndex == -1)
        {
            restoreDescendantComponentStates(getFacetsAndChildren(),
                    _initialDescendantComponentState);
        }
        else
        {
            Object rowState = _cellStates.get(getClientId(facesContext));
            if (rowState == null)
            {
                restoreDescendantComponentStates(getFacetsAndChildren(),
                        _initialDescendantComponentState);
            }
            else
            {
                restoreDescendantComponentStates(getFacetsAndChildren(),
                        rowState);
            }
        }
    }

    protected void restoreDescendantComponentStates(Iterator childIterator,
            Object state)
    {
        Iterator descendantStateIterator = null;
        while (childIterator.hasNext())
        {
            if (descendantStateIterator == null && state != null)
            {
                descendantStateIterator = ((Collection) state).iterator();
            }
            UIComponent component = (UIComponent) childIterator.next();
            // reset the client id (see spec 3.1.6)
            component.setId(component.getId());
            if (!component.isTransient())
            {
                Object childState = null;
                Object descendantState = null;
                if (descendantStateIterator != null
                        && descendantStateIterator.hasNext())
                {
                    Object[] object = (Object[]) descendantStateIterator.next();
                    childState = object[0];
                    descendantState = object[1];
                }
                if (component instanceof EditableValueHolder)
                {
                    ((EditableValueHolderState) childState)
                            .restoreState((EditableValueHolder) component);
                }
                restoreDescendantComponentStates(component
                        .getFacetsAndChildren(), descendantState);
            }
        }
    }

    protected Object saveDescendantComponentStates(Iterator childIterator)
    {
        Collection childStates = null;
        while (childIterator.hasNext())
        {
            if (childStates == null)
            {
                childStates = new ArrayList();
            }
            UIComponent child = (UIComponent) childIterator.next();
            if (!child.isTransient())
            {
                Object descendantState = saveDescendantComponentStates(child
                        .getFacetsAndChildren());
                Object state = null;
                if (child instanceof EditableValueHolder)
                {
                    state = new EditableValueHolderState(
                            (EditableValueHolder) child);
                }
                childStates.add(new Object[] { state, descendantState });
            }
        }
        return childStates;
    }

    /**
     * @see javax.faces.component.UIData#setValue(java.lang.Object)
     */
    public void setValue(Object value)
    {
        super.setValue(value);
        _dataModelMap.clear();
        _cellStates.clear();
        _isValidChilds = true;
    }

    public void setValueBinding(String name, ValueBinding binding)
    {
        if (name == null)
        {
            throw new NullPointerException("name");
        }
        else if (name.equals("value"))
        {
            _dataModelMap.clear();
        }
        else if (name.equals("var") || name.equals("rowIndex"))
        {
            throw new IllegalArgumentException("name " + name);
        }
        super.setValueBinding(name, binding);
    }

    protected DataModel getDataModel()
    {
        String clientID = getParentUIData().getParent().getClientId(
                getFacesContext());
        DataModel dataModel = (DataModel) _dataModelMap.get(clientID);
        if (dataModel == null)
        {
            dataModel = createDataModel();
            _dataModelMap.put(clientID, dataModel);
        }
        return dataModel;
    }

    protected void setDataModel(DataModel dataModel)
    {
        _dataModelMap.put(getParentUIData().getParent().getClientId(
                getFacesContext()), dataModel);
    }

    /**
     * Creates a new DataModel around the current value.
     */
    protected DataModel createDataModel()
    {
        Object value = getValue();
        if (value == null)
        {
            return EMPTY_DATA_MODEL;
        }
        else if (value instanceof DataModel)
        {
            return (DataModel) value;
        }
        else 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
        {
            return new ScalarDataModel(value);
        }
    }

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

        public int getRowCount()
        {
            return 0;
        }

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

        public int getRowIndex()
        {
            return -1;
        }

        public void setRowIndex(int i)
        {
            if (i < -1)
                throw new IndexOutOfBoundsException("Index < 0 : " + i);
        }

        public Object getWrappedData()
        {
            return null;
        }

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

    /**
     * @see javax.faces.component.UIData#processDecodes(javax.faces.context.FacesContext)
     */
    public void processDecodes(FacesContext context)
    {
        if (context == null)
            throw new NullPointerException("context");
        if (!isRendered())
            return;

        setRowIndex(-1);
        processColumnsFacets(context, PROCESS_DECODES);
        processRows(context, PROCESS_DECODES);
        setRowIndex(-1);

        try
        {
            decode(context);
        }
        catch (RuntimeException e)
        {
            context.renderResponse();
            throw e;
        }
    }

    /**
     * @param context
     * @param process_decodes2
     */
    private void processColumnsFacets(FacesContext context, int processAction)
    {
        int first = getFirst();
        int cols = getRows();
        int last;
        if (cols == 0)
        {
            last = getRowCount();
        }
        else
        {
            last = first + cols;
        }

        for (int colIndex = first; colIndex < last; colIndex++)
        {
            setRowIndex(colIndex);
            if (isRowAvailable())
            {
                for (Iterator facetsIter = getFacets().values().iterator(); facetsIter
                        .hasNext();)
                {
                    UIComponent facet = (UIComponent) facetsIter.next();
                    process(context, facet, processAction);
                }
            }
        }
        setRowIndex(-1);
    }

    /**
     * @param context
     * @param process_decodes2
     */
    private void processRows(FacesContext context, int processAction)
    {
        UIData parentUIData = getParentUIData();
        int first = parentUIData.getFirst();
        int rows = parentUIData.getRows();
        int last;
        if (rows == 0)
        {
            last = parentUIData.getRowCount();
        }
        else
        {
            last = first + rows;
        }

        for (int rowIndex = first; rowIndex < last; rowIndex++)
        {
            parentUIData.setRowIndex(rowIndex);
            if (parentUIData.isRowAvailable())
            {
                processColumns(context, processAction);
            }
        }
    }

    /**
     *
     */
    private UIData getParentUIData()
    {
        if (_parentUIData == null)
        {
            UIComponent parent = getParent();
            if (!(parent instanceof UIData))
            {
                throw new IllegalStateException(
                        "UIColumns component must be a child of a UIData component");
            }
            _parentUIData = (UIData) parent;
        }
        return _parentUIData;
    }

    private void processColumns(FacesContext context, int processAction)
    {
        int first = getFirst();
        int cols = getRows();
        int last;
        if (cols == 0)
        {
            last = getRowCount();
        }
        else
        {
            last = first + cols;
        }

        for (int colIndex = first; colIndex < last; colIndex++)
        {
            setRowIndex(colIndex);
            if (isRowAvailable())
            {
                for (Iterator columnChildIter = getChildren().iterator(); columnChildIter
                        .hasNext();)
                {
                    UIComponent columnChild = (UIComponent) columnChildIter
                            .next();
                    process(context, columnChild, processAction);
                }
            }
        }
        setRowIndex(-1);
    }

    /**
     * @see javax.faces.component.UIData#processValidators(javax.faces.context.FacesContext)
     */
    public void processValidators(FacesContext context)
    {
        if (context == null)
            throw new NullPointerException("context");
        if (!isRendered())
            return;
        setRowIndex(-1);
        processColumnsFacets(context, PROCESS_VALIDATORS);
        processRows(context, PROCESS_VALIDATORS);
        setRowIndex(-1);

        // check if an validation error forces the render response for our data
        if (context.getRenderResponse())
        {
            _isValidChilds = false;
        }
    }

    /**
     * @see javax.faces.component.UIData#processUpdates(javax.faces.context.FacesContext)
     */
    public void processUpdates(FacesContext context)
    {
        if (context == null)
            throw new NullPointerException("context");
        if (!isRendered())
            return;
        setRowIndex(-1);
        processColumnsFacets(context, PROCESS_UPDATES);
        processRows(context, PROCESS_UPDATES);
        setRowIndex(-1);

        // check if an validation error forces the render response for our data
        if (context.getRenderResponse())
        {
            _isValidChilds = false;
        }
    }

    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;
        }
    }

    public void encodeTableBegin(FacesContext context)
    {
        setRowIndex(-1);

        if (_isValidChilds)
        {
            //Refresh DataModel for rendering:
            _dataModelMap.clear();
            _cellStates.clear();
            _initialDescendantComponentState = null;
        }
    }

    public void encodeTableEnd(FacesContext context)
    {
        setRowIndex(-1);
    }

    private class EditableValueHolderState
    {
        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);
        }
    }
}
TOP

Related Classes of org.apache.myfaces.custom.crosstable.UIColumns$EditableValueHolderState

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.