You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by mb...@apache.org on 2005/07/26 11:20:59 UTC

svn commit: r225266 - in /myfaces: api/trunk/src/java/javax/faces/component/UIData.java tomahawk/trunk/src/java/org/apache/myfaces/component/html/ext/HtmlDataTableHack.java tomahawk/trunk/src/java/org/apache/myfaces/custom/crosstable/UIColumns.java

Author: mbr
Date: Tue Jul 26 02:20:50 2005
New Revision: 225266

URL: http://svn.apache.org/viewcvs?rev=225266&view=rev
Log:
fix for MYFACES-331

Implementation for UIData.setRowIndex(int) now handles 
only the EditableValueHolder components according to the spec.

saveState/restoreState is not needed anymore since  
UIData hold the datamodel in a map which uses the clientId of the 
parent component to determine the current datamodel.

fixes also the formatting according to the specified 
myfaces code-style (see WIKI http://wiki.apache.org/myfaces/MyFaces_Developer_Notes)

Modified:
    myfaces/api/trunk/src/java/javax/faces/component/UIData.java
    myfaces/tomahawk/trunk/src/java/org/apache/myfaces/component/html/ext/HtmlDataTableHack.java
    myfaces/tomahawk/trunk/src/java/org/apache/myfaces/custom/crosstable/UIColumns.java

Modified: myfaces/api/trunk/src/java/javax/faces/component/UIData.java
URL: http://svn.apache.org/viewcvs/myfaces/api/trunk/src/java/javax/faces/component/UIData.java?rev=225266&r1=225265&r2=225266&view=diff
==============================================================================
--- myfaces/api/trunk/src/java/javax/faces/component/UIData.java (original)
+++ myfaces/api/trunk/src/java/javax/faces/component/UIData.java Tue Jul 26 02:20:50 2005
@@ -44,733 +44,702 @@
  */
 public class UIData extends UIComponentBase implements NamingContainer
 {
-	private static final int STATE_SIZE = 6;
-	private static final int SUPER_STATE_INDEX = 0;
-	private static final int FIRST_STATE_INDEX = 1;
-	private static final int ROWS_STATE_INDEX = 2;
-	private static final int VALUE_STATE_INDEX = 3;
-	private static final int VAR_STATE_INDEX = 4;
-	private static final int VALID_CHILDS_STATE_INDEX = 5;
-
-	private static final String FOOTER_FACET_NAME = "footer";
-	private static final String HEADER_FACET_NAME = "header";
-	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 static final Integer INTEGER_MINUS1 = new Integer(-1);
-
-	private int _rowIndex = -1;
-	private String _var = null;
-
-	// holds for each row the states of the child components of this UIData 
-	private Map _rowStates = null;
-
-	// contains the initial row state which is used to initialize each row
-	private Object _initialRowState = null;
-
-	private Map _dataModelMap = new HashMap();
-
-	// will be set to false if the data should not be refreshed at the beginning of the encode phase
-	private boolean _isValidChilds = true;
-
-	public void setFooter(UIComponent footer)
-	{
-		getFacets().put(FOOTER_FACET_NAME, footer);
-	}
-
-	public UIComponent getFooter()
-	{
-		return (UIComponent) getFacets().get(FOOTER_FACET_NAME);
-	}
-
-	public void setHeader(UIComponent header)
-	{
-		getFacets().put(HEADER_FACET_NAME, header);
-	}
-
-	public UIComponent getHeader()
-	{
-		return (UIComponent) 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;
-	}
-
-	public void setRowIndex(int rowIndex)
-	{
-		if(rowIndex < -1)
-		{
-			throw new IllegalArgumentException("rowIndex is less than -1");
-		}
-		
-		if (_rowIndex == rowIndex)
-		{
-			return;
-		}
-
-		FacesContext facesContext = getFacesContext();
-
-		if (_rowIndex != -1)
-		{
-			if (_rowStates == null)
-			{
-				_rowStates = new HashMap();
-			}
-			_rowStates.put(getClientId(facesContext), processSaveRowState(facesContext));
-		}
-		else if (_initialRowState == null)
-		{
-			_initialRowState = processSaveRowState(facesContext);
-		}
-
-		_rowIndex = rowIndex;
-
-		DataModel dataModel = getDataModel();
-		dataModel.setRowIndex(rowIndex);
-
-		String var = getVar();
-		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 && _rowStates != null)
-		{
-			Object state = _rowStates.get(getClientId(facesContext));
-			if (state == null)
-			{
-				state = _initialRowState;
-			}
-			processRestoreRowState(facesContext, state);
-		}
-		else
-		{
-			processRestoreRowState(facesContext, _initialRowState);
-		}
-	}
-
-	private Object processSaveRowState(FacesContext context)
-	{
-		if (isTransient())
-			return null;
-		List childStates = null;
-		int columnCount = getChildCount();
-		if (columnCount > 0)
-		{
-			for (Iterator colIt = getChildren().iterator(); colIt.hasNext();)
-			{
-				UIComponent child = (UIComponent) colIt.next();
-				if (!child.isTransient())
-				{
-					if (childStates == null)
-					{
-						childStates = new ArrayList(columnCount);
-					}
-					if (child instanceof UIColumn)
-					{
-						childStates.add(new Object[] {child.saveState(context),
-										getColumnChildsState(context, child.getChildren().iterator())});
-					}
-					else
-					{
-						childStates.add(child.processSaveState(context));
-					}
-				}
-			}
-		}
-		return childStates;
-	}
-
-	private Object getColumnChildsState(FacesContext context, Iterator compIterator)
-	{
-		List result = null;
-		while (compIterator.hasNext())
-		{
-			UIComponent colChild = (UIComponent) compIterator.next();
-			if (!colChild.isTransient())
-			{
-				if (result == null)
-				{
-					result = new ArrayList();
-				}
-				result.add(colChild.processSaveState(context));
-			}
-		}
-		return result;
-	}
-
-	public void processRestoreRowState(FacesContext context, Object state)
-	{
-		List childrenStates = (List) state;
-		int childCount = getChildCount();
-		if (childrenStates != null && childCount > 0)
-		{
-			int idx = 0;
-			for (Iterator it = getChildren().iterator(); it.hasNext();)
-			{
-				UIComponent child = (UIComponent) it.next();
-				if (!child.isTransient())
-				{
-					Object childState = childrenStates.get(idx++);
-					if (childState != null)
-					{
-						if (child instanceof UIColumn)
-						{
-							Object[] columnState = (Object[]) childState;
-							setColumnChildsState(context, child.getChildren().iterator(), columnState[1]);
-							child.restoreState(context, columnState[0]);
-						}
-						else
-						{
-							child.processRestoreState(context, childState);
-						}
-					}
-					else
-					{
-						context.getExternalContext().log(
-										"No state found to restore child of component " + getId());
-					}
-				}
-			}
-		}
-	}
-
-	private void setColumnChildsState(FacesContext context, Iterator compIterator, Object state)
-	{
-		List childrenList = (List) state;
-		if (childrenList != null)
-		{
-			int idx = 0;
-			while (compIterator.hasNext())
-			{
-				UIComponent child = (UIComponent) compIterator.next();
-				if (!child.isTransient())
-				{
-					Object childState = childrenList.get(idx++);
-					if (childState != null)
-					{
-						child.processRestoreState(context, childState);
-					}
-					else
-					{
-						context.getExternalContext().log(
-										"No state found to restore child of component " + getId());
-					}
-				}
-			}
-		}
-	}
-
-	public void setRows(int rows)
-	{
-		_rows = new Integer(rows);
-		if (rows < 0)
-			throw new IllegalArgumentException("rows: " + rows);
-	}
-
-	public void setVar(String var)
-	{
-		_var = var;
-	}
-
-	public String getVar()
-	{
-		return _var;
-	}
-
-	public void setValueBinding(String name, ValueBinding binding)
-	{
-		if (name == null)
-		{
-			throw new NullPointerException("name");
-		}
-		else if (name.equals("value"))
-		{
-			_dataModelMap.clear();
-			_rowStates = null;
-		}
-		else if (name.equals("var") || name.equals("rowIndex"))
-		{
-			throw new IllegalArgumentException("name " + name);
-		}
-		super.setValueBinding(name, binding);
-	}
-
-	public String getClientId(FacesContext context)
-	{
-		String clientId = super.getClientId(context);
-		int rowIndex = getRowIndex();
-		if (rowIndex == -1)
-		{
-			return clientId;
-		}
-		return clientId + "_" + rowIndex;
-	}
-
-	public void queueEvent(FacesEvent event)
-	{
-		super.queueEvent(new FacesEventWrapper(event, getRowIndex(), this));
-	}
-
-	public void broadcast(FacesEvent event) throws AbortProcessingException
-	{
-		if (event instanceof FacesEventWrapper)
-		{
-			FacesEvent originalEvent = ((FacesEventWrapper) event).getWrappedFacesEvent();
-			int eventRowIndex = ((FacesEventWrapper) event).getRowIndex();
-			int currentRowIndex = getRowIndex();
-			setRowIndex(eventRowIndex);
-			originalEvent.getComponent().broadcast(originalEvent);
-			setRowIndex(currentRowIndex);
-		}
-		else
-		{
-			super.broadcast(event);
-		}
-	}
-
-	public void encodeBegin(FacesContext context) throws IOException
-	{
-		if (_isValidChilds)
-		{
-			//Refresh DataModel for rendering:
-			_dataModelMap.clear();
-			_rowStates = null;
-		}
-		super.encodeBegin(context);
-	}
-
-	/**
-	 * @see javax.faces.component.UIComponentBase#encodeEnd(javax.faces.context.FacesContext)
-	 */
-	public void encodeEnd(FacesContext context) throws IOException
-	{
-		setRowIndex(-1);
-		super.encodeEnd(context);
-	}
-
-	public void processDecodes(FacesContext context)
-	{
-		if (context == null)
-			throw new NullPointerException("context");
-		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;
-		}
-	}
-
-	public void processValidators(FacesContext context)
-	{
-		if (context == null)
-			throw new NullPointerException("context");
-		if (!isRendered())
-			return;
-		setRowIndex(-1);
-		processFacets(context, PROCESS_VALIDATORS);
-		processColumnFacets(context, PROCESS_VALIDATORS);
-		processColumnChildren(context, PROCESS_VALIDATORS);
-		setRowIndex(-1);
-
-		// check if an validation error forces the render response for our data
-		if (context.getRenderResponse())
-		{
-			_isValidChilds = false;
-		}
-	}
-
-	public void processUpdates(FacesContext context)
-	{
-		if (context == null)
-			throw new NullPointerException("context");
-		if (!isRendered())
-			return;
-		setRowIndex(-1);
-		processFacets(context, PROCESS_UPDATES);
-		processColumnFacets(context, PROCESS_UPDATES);
-		processColumnChildren(context, PROCESS_UPDATES);
-		setRowIndex(-1);
-
-		if (context.getRenderResponse())
-		{
-			_isValidChilds = false;
-		}
-	}
-
-	private void processFacets(FacesContext context, int processAction)
-	{
-		for (Iterator it = getFacets().values().iterator(); it.hasNext();)
-		{
-			UIComponent facet = (UIComponent) it.next();
-			process(context, facet, processAction);
-		}
-	}
-
-	private void processColumnFacets(FacesContext context, int processAction)
-	{
-		for (Iterator childIter = getChildren().iterator(); childIter.hasNext();)
-		{
-			UIComponent child = (UIComponent) childIter.next();
-			if (child instanceof UIColumn)
-			{
-				if (!child.isRendered())
-				{
-					//Column is not visible
-					continue;
-				}
-				for (Iterator facetsIter = child.getFacets().values().iterator(); facetsIter.hasNext();)
-				{
-					UIComponent facet = (UIComponent) facetsIter.next();
-					process(context, facet, processAction);
-				}
-			}
-		}
-	}
-
-	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; rowIndex < last; rowIndex++)
-		{
-			setRowIndex(rowIndex);
-			if (isRowAvailable())
-			{
-				for (Iterator it = getChildren().iterator(); it.hasNext();)
-				{
-					UIComponent child = (UIComponent) it.next();
-					if (child instanceof UIColumn)
-					{
-						if (!child.isRendered())
-						{
-							//Column is not visible
-							continue;
-						}
-						for (Iterator columnChildIter = child.getChildren().iterator(); columnChildIter
-										.hasNext();)
-						{
-							UIComponent columnChild = (UIComponent) columnChildIter.next();
-							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;
-		}
-	}
-
-	private DataModel getDataModel()
-	{
-		String clientID = getParent().getClientId(getFacesContext());
-		DataModel dataModel = (DataModel) _dataModelMap.get(clientID);
-		if (dataModel == null)
-		{
-			dataModel = createDataModel();
-			_dataModelMap.put(clientID, dataModel);
-		}
-		return dataModel;
-	}
-
-	/**
-	 * Creates a new DataModel around the current value.
-	 */
-	private 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 (value instanceof Collection)
-		{
-			return new ListDataModel(new ArrayList((Collection) 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 class FacesEventWrapper extends FacesEvent
-	{
-		private FacesEvent _wrappedFacesEvent;
-		private int _rowIndex;
-
-		public FacesEventWrapper(FacesEvent facesEvent, int rowIndex, UIData redirectComponent)
-		{
-			super(redirectComponent);
-			_wrappedFacesEvent = facesEvent;
-			_rowIndex = rowIndex;
-		}
-
-		public PhaseId getPhaseId()
-		{
-			return _wrappedFacesEvent.getPhaseId();
-		}
-
-		public void setPhaseId(PhaseId phaseId)
-		{
-			_wrappedFacesEvent.setPhaseId(phaseId);
-		}
-
-		public void queue()
-		{
-			_wrappedFacesEvent.queue();
-		}
-
-		public String toString()
-		{
-			return _wrappedFacesEvent.toString();
-		}
-
-		public boolean isAppropriateListener(FacesListener faceslistener)
-		{
-			return _wrappedFacesEvent.isAppropriateListener(faceslistener);
-		}
-
-		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()
-	{
-		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 IllegalArgumentException();
-		}
-
-		public Object getWrappedData()
-		{
-			return null;
-		}
-
-		public void setWrappedData(Object obj)
-		{
-			if (obj == null)
-				return; //Clearing is allowed
-			throw new UnsupportedOperationException(this.getClass().getName()
-							+ " UnsupportedOperationException");
-		}
-	};
-
-	public void setValue(Object value)
-	{
-		_value = value;
-		_dataModelMap.clear();
-		_rowStates = null;
-		_isValidChilds = true;
-	}
-
-	public Object saveState(FacesContext context)
-	{
-		Object[] values = new Object[STATE_SIZE];
-		values[SUPER_STATE_INDEX] = super.saveState(context);
-		values[FIRST_STATE_INDEX] = _first;
-		values[ROWS_STATE_INDEX] = _rows;
-		values[VALUE_STATE_INDEX] = _value;
-		values[VAR_STATE_INDEX] = _var;
-		values[VALID_CHILDS_STATE_INDEX] = Boolean.valueOf(_isValidChilds);
-		return values;
-	}
-
-	public void restoreState(FacesContext context, Object state)
-	{
-		Object[] values = (Object[]) state;
-		super.restoreState(context, values[0]);
-		_first = (Integer) values[FIRST_STATE_INDEX];
-		_rows = (Integer) values[ROWS_STATE_INDEX];
-		_value = values[VALUE_STATE_INDEX];
-		_var = (String) values[VAR_STATE_INDEX];
-
-		Boolean validChilds = (Boolean) values[VALID_CHILDS_STATE_INDEX];
-		if (validChilds != null)
-		{
-			_isValidChilds = validChilds.booleanValue();
-		}
-		else
-		{
-			_isValidChilds = true;
-		}
-	}
-
-	//------------------ GENERATED CODE BEGIN (do not modify!) --------------------
-
-	public static final String COMPONENT_TYPE = "javax.faces.Data";
-	public static final String COMPONENT_FAMILY = "javax.faces.Data";
-	private static final String DEFAULT_RENDERER_TYPE = "javax.faces.Table";
-	private static final int DEFAULT_FIRST = 0;
-	private static final int DEFAULT_ROWS = 0;
-
-	private Integer _first = null;
-	private Integer _rows = null;
-	private Object _value = null;
-
-	public UIData()
-	{
-		setRendererType(DEFAULT_RENDERER_TYPE);
-	}
-
-	public String getFamily()
-	{
-		return COMPONENT_FAMILY;
-	}
-
-	public void setFirst(int first)
-	{
-		_first = new Integer(first);
-	}
-
-	public int getFirst()
-	{
-		if (_first != null)
-			return _first.intValue();
-		ValueBinding vb = getValueBinding("first");
-		Integer v = vb != null ? (Integer) vb.getValue(getFacesContext()) : null;
-		return v != null ? v.intValue() : DEFAULT_FIRST;
-	}
-
-	public int getRows()
-	{
-		if (_rows != null)
-			return _rows.intValue();
-		ValueBinding vb = getValueBinding("rows");
-		Integer v = vb != null ? (Integer) vb.getValue(getFacesContext()) : null;
-		return v != null ? v.intValue() : DEFAULT_ROWS;
-	}
-
-	public Object getValue()
-	{
-		if (_value != null)
-			return _value;
-		ValueBinding vb = getValueBinding("value");
-		return vb != null ? (Object) vb.getValue(getFacesContext()) : null;
-	}
+    private static final int STATE_SIZE = 5;
+    private static final int SUPER_STATE_INDEX = 0;
+    private static final int FIRST_STATE_INDEX = 1;
+    private static final int ROWS_STATE_INDEX = 2;
+    private static final int VALUE_STATE_INDEX = 3;
+    private static final int VAR_STATE_INDEX = 4;
+
+    private static final String FOOTER_FACET_NAME = "footer";
+    private static final String HEADER_FACET_NAME = "header";
+    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 static final Integer INTEGER_MINUS1 = new Integer(-1);
+
+    private int _rowIndex = -1;
+    private String _var = null;
+
+    // holds for each row the states of the child components of this UIData 
+    private Map _rowStates = new HashMap();
+
+    private Map _dataModelMap = new HashMap();
+
+    // 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;
+
+    public void setFooter(UIComponent footer)
+    {
+        getFacets().put(FOOTER_FACET_NAME, footer);
+    }
+
+    public UIComponent getFooter()
+    {
+        return (UIComponent) getFacets().get(FOOTER_FACET_NAME);
+    }
+
+    public void setHeader(UIComponent header)
+    {
+        getFacets().put(HEADER_FACET_NAME, header);
+    }
+
+    public UIComponent getHeader()
+    {
+        return (UIComponent) 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;
+    }
+
+    public void setRowIndex(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)
+            {
+                _initialDescendantComponentState = saveDescendantComponentStates(getChildren()
+                                .iterator());
+            }
+        }
+        else
+        {
+            _rowStates.put(getClientId(facesContext),
+                            saveDescendantComponentStates(getChildren()
+                                            .iterator()));
+        }
+
+        _rowIndex = rowIndex;
+
+        DataModel dataModel = getDataModel();
+        dataModel.setRowIndex(rowIndex);
+
+        String var = getVar();
+        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)
+        {
+            restoreDescendantComponentStates(getChildren().iterator(),
+                            _initialDescendantComponentState);
+        }
+        else
+        {
+            Object rowState = _rowStates.get(getClientId(facesContext));
+            if (rowState == null)
+            {
+                restoreDescendantComponentStates(getChildren().iterator(),
+                                _initialDescendantComponentState);
+            }
+            else
+            {
+                restoreDescendantComponentStates(getChildren().iterator(),
+                                rowState);
+            }
+        }
+    }
+
+    private 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());
+            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);
+        }
+    }
+
+    private Object saveDescendantComponentStates(Iterator childIterator)
+    {
+        Collection childStates = null;
+        while (childIterator.hasNext())
+        {
+            if (childStates == null)
+            {
+                childStates = new ArrayList();
+            }
+            UIComponent child = (UIComponent) childIterator.next();
+            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;
+    }
+
+    public void setRows(int rows)
+    {
+        _rows = new Integer(rows);
+        if (rows < 0)
+            throw new IllegalArgumentException("rows: " + rows);
+    }
+
+    public void setVar(String var)
+    {
+        _var = var;
+    }
+
+    public String getVar()
+    {
+        return _var;
+    }
+
+    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);
+    }
+
+    public String getClientId(FacesContext context)
+    {
+        String clientId = super.getClientId(context);
+        int rowIndex = getRowIndex();
+        if (rowIndex == -1)
+        {
+            return clientId;
+        }
+        return clientId + "_" + rowIndex;
+    }
+
+    public void queueEvent(FacesEvent event)
+    {
+        super.queueEvent(new FacesEventWrapper(event, getRowIndex(), this));
+    }
+
+    public void broadcast(FacesEvent event) throws AbortProcessingException
+    {
+        if (event instanceof FacesEventWrapper)
+        {
+            FacesEvent originalEvent = ((FacesEventWrapper) event)
+                            .getWrappedFacesEvent();
+            int eventRowIndex = ((FacesEventWrapper) event).getRowIndex();
+            int currentRowIndex = getRowIndex();
+            setRowIndex(eventRowIndex);
+            originalEvent.getComponent().broadcast(originalEvent);
+            setRowIndex(currentRowIndex);
+        }
+        else
+        {
+            super.broadcast(event);
+        }
+    }
+
+    public void encodeBegin(FacesContext context) throws IOException
+    {
+        if (_isValidChilds)
+        {
+            //Refresh DataModel for rendering:
+            _dataModelMap.clear();
+            _rowStates.clear();
+            _initialDescendantComponentState = null;
+        }
+        super.encodeBegin(context);
+    }
+
+    /**
+     * @see javax.faces.component.UIComponentBase#encodeEnd(javax.faces.context.FacesContext)
+     */
+    public void encodeEnd(FacesContext context) throws IOException
+    {
+        setRowIndex(-1);
+        super.encodeEnd(context);
+    }
+
+    public void processDecodes(FacesContext context)
+    {
+        if (context == null)
+            throw new NullPointerException("context");
+        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;
+        }
+    }
+
+    public void processValidators(FacesContext context)
+    {
+        if (context == null)
+            throw new NullPointerException("context");
+        if (!isRendered())
+            return;
+        setRowIndex(-1);
+        processFacets(context, PROCESS_VALIDATORS);
+        processColumnFacets(context, PROCESS_VALIDATORS);
+        processColumnChildren(context, PROCESS_VALIDATORS);
+        setRowIndex(-1);
+
+        // check if an validation error forces the render response for our data
+        if (context.getRenderResponse())
+        {
+            _isValidChilds = false;
+        }
+    }
+
+    public void processUpdates(FacesContext context)
+    {
+        if (context == null)
+            throw new NullPointerException("context");
+        if (!isRendered())
+            return;
+        setRowIndex(-1);
+        processFacets(context, PROCESS_UPDATES);
+        processColumnFacets(context, PROCESS_UPDATES);
+        processColumnChildren(context, PROCESS_UPDATES);
+        setRowIndex(-1);
+
+        if (context.getRenderResponse())
+        {
+            _isValidChilds = false;
+        }
+    }
+
+    private void processFacets(FacesContext context, int processAction)
+    {
+        for (Iterator it = getFacets().values().iterator(); it.hasNext();)
+        {
+            UIComponent facet = (UIComponent) it.next();
+            process(context, facet, processAction);
+        }
+    }
+
+    private void processColumnFacets(FacesContext context, int processAction)
+    {
+        for (Iterator childIter = getChildren().iterator(); childIter.hasNext();)
+        {
+            UIComponent child = (UIComponent) childIter.next();
+            if (child instanceof UIColumn)
+            {
+                if (!child.isRendered())
+                {
+                    //Column is not visible
+                    continue;
+                }
+                for (Iterator facetsIter = child.getFacets().values()
+                                .iterator(); facetsIter.hasNext();)
+                {
+                    UIComponent facet = (UIComponent) facetsIter.next();
+                    process(context, facet, processAction);
+                }
+            }
+        }
+    }
+
+    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; rowIndex < last; rowIndex++)
+        {
+            setRowIndex(rowIndex);
+            if (isRowAvailable())
+            {
+                for (Iterator it = getChildren().iterator(); it.hasNext();)
+                {
+                    UIComponent child = (UIComponent) it.next();
+                    if (child instanceof UIColumn)
+                    {
+                        if (!child.isRendered())
+                        {
+                            //Column is not visible
+                            continue;
+                        }
+                        for (Iterator columnChildIter = child.getChildren()
+                                        .iterator(); columnChildIter.hasNext();)
+                        {
+                            UIComponent columnChild = (UIComponent) columnChildIter
+                                            .next();
+                            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;
+        }
+    }
+
+    private DataModel getDataModel()
+    {
+        String clientID = getParent().getClientId(getFacesContext());
+        DataModel dataModel = (DataModel) _dataModelMap.get(clientID);
+        if (dataModel == null)
+        {
+            dataModel = createDataModel();
+            _dataModelMap.put(clientID, dataModel);
+        }
+        return dataModel;
+    }
+
+    /**
+     * Creates a new DataModel around the current value.
+     */
+    private 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 (value instanceof Collection)
+        {
+            return new ListDataModel(new ArrayList((Collection) 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 class FacesEventWrapper extends FacesEvent
+    {
+        private FacesEvent _wrappedFacesEvent;
+        private int _rowIndex;
+
+        public FacesEventWrapper(FacesEvent facesEvent, int rowIndex,
+                        UIData redirectComponent)
+        {
+            super(redirectComponent);
+            _wrappedFacesEvent = facesEvent;
+            _rowIndex = rowIndex;
+        }
+
+        public PhaseId getPhaseId()
+        {
+            return _wrappedFacesEvent.getPhaseId();
+        }
+
+        public void setPhaseId(PhaseId phaseId)
+        {
+            _wrappedFacesEvent.setPhaseId(phaseId);
+        }
+
+        public void queue()
+        {
+            _wrappedFacesEvent.queue();
+        }
+
+        public String toString()
+        {
+            return _wrappedFacesEvent.toString();
+        }
+
+        public boolean isAppropriateListener(FacesListener faceslistener)
+        {
+            return _wrappedFacesEvent.isAppropriateListener(faceslistener);
+        }
+
+        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()
+    {
+        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 IllegalArgumentException();
+        }
+
+        public Object getWrappedData()
+        {
+            return null;
+        }
+
+        public void setWrappedData(Object obj)
+        {
+            if (obj == null)
+                return; //Clearing is allowed
+            throw new UnsupportedOperationException(this.getClass().getName()
+                            + " UnsupportedOperationException");
+        }
+    };
+
+    public void setValue(Object value)
+    {
+        _value = value;
+        _dataModelMap.clear();
+        _rowStates = null;
+        _isValidChilds = true;
+    }
+
+    public Object saveState(FacesContext context)
+    {
+        Object[] values = new Object[STATE_SIZE];
+        values[SUPER_STATE_INDEX] = super.saveState(context);
+        values[FIRST_STATE_INDEX] = _first;
+        values[ROWS_STATE_INDEX] = _rows;
+        values[VALUE_STATE_INDEX] = _value;
+        values[VAR_STATE_INDEX] = _var;
+        return values;
+    }
+
+    public void restoreState(FacesContext context, Object state)
+    {
+        Object[] values = (Object[]) state;
+        super.restoreState(context, values[0]);
+        _first = (Integer) values[FIRST_STATE_INDEX];
+        _rows = (Integer) values[ROWS_STATE_INDEX];
+        _value = values[VALUE_STATE_INDEX];
+        _var = (String) values[VAR_STATE_INDEX];
+    }
+
+    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);
+        }
+    }
+
+    //------------------ GENERATED CODE BEGIN (do not modify!) --------------------
+
+    public static final String COMPONENT_TYPE = "javax.faces.Data";
+    public static final String COMPONENT_FAMILY = "javax.faces.Data";
+    private static final String DEFAULT_RENDERER_TYPE = "javax.faces.Table";
+    private static final int DEFAULT_FIRST = 0;
+    private static final int DEFAULT_ROWS = 0;
+
+    private Integer _first = null;
+    private Integer _rows = null;
+    private Object _value = null;
+
+    public UIData()
+    {
+        setRendererType(DEFAULT_RENDERER_TYPE);
+    }
+
+    public String getFamily()
+    {
+        return COMPONENT_FAMILY;
+    }
+
+    public void setFirst(int first)
+    {
+        _first = new Integer(first);
+    }
+
+    public int getFirst()
+    {
+        if (_first != null)
+            return _first.intValue();
+        ValueBinding vb = getValueBinding("first");
+        Integer v = vb != null ? (Integer) vb.getValue(getFacesContext()) : null;
+        return v != null ? v.intValue() : DEFAULT_FIRST;
+    }
+
+    public int getRows()
+    {
+        if (_rows != null)
+            return _rows.intValue();
+        ValueBinding vb = getValueBinding("rows");
+        Integer v = vb != null ? (Integer) vb.getValue(getFacesContext()) : null;
+        return v != null ? v.intValue() : DEFAULT_ROWS;
+    }
+
+    public Object getValue()
+    {
+        if (_value != null)
+            return _value;
+        ValueBinding vb = getValueBinding("value");
+        return vb != null ? (Object) vb.getValue(getFacesContext()) : null;
+    }
 
-	//------------------ GENERATED CODE END ---------------------------------------
+    //------------------ GENERATED CODE END ---------------------------------------
 
 }

Modified: myfaces/tomahawk/trunk/src/java/org/apache/myfaces/component/html/ext/HtmlDataTableHack.java
URL: http://svn.apache.org/viewcvs/myfaces/tomahawk/trunk/src/java/org/apache/myfaces/component/html/ext/HtmlDataTableHack.java?rev=225266&r1=225265&r2=225266&view=diff
==============================================================================
--- myfaces/tomahawk/trunk/src/java/org/apache/myfaces/component/html/ext/HtmlDataTableHack.java (original)
+++ myfaces/tomahawk/trunk/src/java/org/apache/myfaces/component/html/ext/HtmlDataTableHack.java Tue Jul 26 02:20:50 2005
@@ -18,12 +18,13 @@
 import java.io.IOException;
 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.UIColumn;
+import javax.faces.component.EditableValueHolder;
 import javax.faces.component.UIComponent;
 import javax.faces.context.FacesContext;
 import javax.faces.el.ValueBinding;
@@ -42,414 +43,368 @@
  * @author Manfred Geiler (latest modification by $Author$)
  * @version $Revision$ $Date$
  */
-abstract class HtmlDataTableHack extends javax.faces.component.html.HtmlDataTable
+abstract class HtmlDataTableHack extends
+                javax.faces.component.html.HtmlDataTable
 {
-  private Map _dataModelMap = new HashMap();
+    private Map _dataModelMap = new HashMap();
 
-  // will be set to false if the data should not be refreshed at the beginning of the encode phase
-  private boolean _isValidChilds = true;
+    // will be set to false if the data should not be refreshed at the beginning of the encode phase
+    private boolean _isValidChilds = true;
 
-  // holds for each row the states of the child components of this UIData 
-  private Map _rowStates = null;
+    // holds for each row the states of the child components of this UIData 
+    private Map _rowStates = new HashMap();
 
-  // contains the initial row state which is used to initialize each row
-  private Object _initialRowState = null;
+    // contains the initial row state which is used to initialize each row
+    private Object _initialDescendantComponentState = null;
 
-  // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-  // Every field and method from here is identical to UIData !!!!!!!!!
+    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+    // Every field and method from here is identical to UIData !!!!!!!!!
 
-  private static final Class OBJECT_ARRAY_CLASS = (new Object[0]).getClass();
+    private static final Class OBJECT_ARRAY_CLASS = (new Object[0]).getClass();
 
-  private int _rowIndex = -1;
+    private int _rowIndex = -1;
 
-  public boolean isRowAvailable()
-  {
-    return getDataModel().isRowAvailable();
-  }
-
-  public int getRowCount()
-  {
-    return getDataModel().getRowCount();
-  }
-
-  public Object getRowData()
-  {
-    return getDataModel().getRowData();
-  }
-
-  public int getRowIndex()
-  {
-    return _rowIndex;
-  }
-
-  /**
-   * @see javax.faces.component.UIData#processUpdates(javax.faces.context.FacesContext)
-   */
-  public void processUpdates(FacesContext context)
-  {
-    super.processUpdates(context);
-    // check if a update model error forces the render response for our data
-    if (context.getRenderResponse())
+    public boolean isRowAvailable()
     {
-      _isValidChilds = false;
+        return getDataModel().isRowAvailable();
     }
-  }
 
-  /**
-   * @see javax.faces.component.UIData#processValidators(javax.faces.context.FacesContext)
-   */
-  public void processValidators(FacesContext context)
-  {
-    super.processValidators(context);
-    // check if a validation error forces the render response for our data
-    if (context.getRenderResponse())
+    public int getRowCount()
     {
-      _isValidChilds = false;
+        return getDataModel().getRowCount();
     }
-  }
 
-  /**
-   * @see javax.faces.component.UIData#encodeBegin(javax.faces.context.FacesContext)
-   */
-  public void encodeBegin(FacesContext context) throws IOException
-  {
-    if (_isValidChilds)
+    public Object getRowData()
     {
-      //Refresh DataModel for rendering:
-      _dataModelMap.clear();
-      _rowStates = null;
+        return getDataModel().getRowData();
     }
-    super.encodeBegin(context);
-  }
 
-  /**
-   * @see javax.faces.component.UIComponentBase#encodeEnd(javax.faces.context.FacesContext)
-   */
-  public void encodeEnd(FacesContext context) throws IOException
-  {
-    setRowIndex(-1);
-    super.encodeEnd(context);
-  }
+    public int getRowIndex()
+    {
+        return _rowIndex;
+    }
 
-  public void setRowIndex(int rowIndex)
-  {
-		if(rowIndex < -1)
-		{
-			throw new IllegalArgumentException("rowIndex is less than -1");
-		}
-		
-    if (_rowIndex == rowIndex)
+    /**
+     * @see javax.faces.component.UIData#processUpdates(javax.faces.context.FacesContext)
+     */
+    public void processUpdates(FacesContext context)
     {
-      return;
+        super.processUpdates(context);
+        // check if a update model error forces the render response for our data
+        if (context.getRenderResponse())
+        {
+            _isValidChilds = false;
+        }
     }
 
-    FacesContext context = getFacesContext();
+    /**
+     * @see javax.faces.component.UIData#processValidators(javax.faces.context.FacesContext)
+     */
+    public void processValidators(FacesContext context)
+    {
+        super.processValidators(context);
+        // check if a validation error forces the render response for our data
+        if (context.getRenderResponse())
+        {
+            _isValidChilds = false;
+        }
+    }
 
-    if (_rowIndex != -1)
+    /**
+     * @see javax.faces.component.UIData#encodeBegin(javax.faces.context.FacesContext)
+     */
+    public void encodeBegin(FacesContext context) throws IOException
     {
-      if (_rowStates == null)
-      {
-        _rowStates = new HashMap();
-      }
-      _rowStates.put(getClientId(context), processSaveRowState(context));
+        if (_isValidChilds)
+        {
+            //Refresh DataModel for rendering:
+            _dataModelMap.clear();
+            _rowStates.clear();
+            _initialDescendantComponentState = null;
+        }
+        super.encodeBegin(context);
     }
-    else if (_initialRowState == null)
+
+    /**
+     * @see javax.faces.component.UIComponentBase#encodeEnd(javax.faces.context.FacesContext)
+     */
+    public void encodeEnd(FacesContext context) throws IOException
     {
-      _initialRowState = processSaveRowState(context);
+        setRowIndex(-1);
+        super.encodeEnd(context);
     }
 
-    _rowIndex = rowIndex;
+    public void setRowIndex(int rowIndex)
+    {
+        if (rowIndex < -1)
+        {
+            throw new IllegalArgumentException("rowIndex is less than -1");
+        }
 
-    DataModel dataModel = getDataModel();
-    dataModel.setRowIndex(rowIndex);
+        if (_rowIndex == rowIndex)
+        {
+            return;
+        }
 
-    String var = getVar();
-    if (rowIndex == -1)
-    {
-      if (var != null)
-      {
-        context.getExternalContext().getRequestMap().remove(var);
-      }
-    }
-    else
-    {
-      if (var != null)
-      {
-        if (isRowAvailable())
+        FacesContext facesContext = getFacesContext();
+
+        if (_rowIndex == -1)
         {
-          Object rowData = dataModel.getRowData();
-          context.getExternalContext().getRequestMap().put(var, rowData);
+            if (_initialDescendantComponentState == null)
+            {
+                _initialDescendantComponentState = saveDescendantComponentStates(getChildren()
+                                .iterator());
+            }
         }
         else
         {
-          context.getExternalContext().getRequestMap().remove(var);
+            _rowStates.put(getClientId(facesContext),
+                            saveDescendantComponentStates(getChildren()
+                                            .iterator()));
         }
-      }
-    }
 
-    if (_rowIndex != -1 && _rowStates != null)
-    {
-      Object state = _rowStates.get(getClientId(context));
-      if (state == null)
-      {
-        state = _initialRowState;
-      }
-      processRestoreRowState(context, state);
-    }
-    else
-    {
-      processRestoreRowState(context, _initialRowState);
-    }
-  }
-
-  private Object processSaveRowState(FacesContext context)
-  {
-    if (isTransient())
-      return null;
-    List childStates = null;
-    int columnCount = getChildCount();
-    if (columnCount > 0)
-    {
-      for (Iterator colIt = getChildren().iterator(); colIt.hasNext();)
-      {
-        UIComponent child = (UIComponent) colIt.next();
-        if (!child.isTransient())
-        {
-          if (childStates == null)
-          {
-            childStates = new ArrayList(columnCount);
-          }
-          if (child instanceof UIColumn)
-          {
-            childStates.add(new Object[] {child.saveState(context),
-                getColumnChildsState(context, child.getChildren().iterator())});
-          }
-          else
-          {
-            childStates.add(child.processSaveState(context));
-          }
-        }
-      }
-    }
-    return childStates;
-  }
-
-  private Object getColumnChildsState(FacesContext context, Iterator compIterator)
-  {
-    List result = null;
-    while (compIterator.hasNext())
-    {
-      UIComponent colChild = (UIComponent) compIterator.next();
-      if (!colChild.isTransient())
-      {
-        if (result == null)
-        {
-          result = new ArrayList();
-        }
-        result.add(colChild.processSaveState(context));
-      }
-    }
-    return result;
-  }
-
-  public void processRestoreRowState(FacesContext context, Object state)
-  {
-    List childrenStates = (List) state;
-    int childCount = getChildCount();
-    if (childCount > 0)
-    {
-      int idx = 0;
-      for (Iterator it = getChildren().iterator(); it.hasNext();)
-      {
-        UIComponent child = (UIComponent) it.next();
-        if (!child.isTransient())
-        {
-          Object childState = childrenStates.get(idx++);
-          if (childState != null)
-          {
-            if (child instanceof UIColumn)
+        _rowIndex = rowIndex;
+
+        DataModel dataModel = getDataModel();
+        dataModel.setRowIndex(rowIndex);
+
+        String var = getVar();
+        if (rowIndex == -1)
+        {
+            if (var != null)
             {
-              Object[] columnState = (Object[]) childState;
-              setColumnChildsState(context, child.getChildren().iterator(), columnState[1]);
-              child.restoreState(context, columnState[0]);
+                facesContext.getExternalContext().getRequestMap().remove(var);
             }
-            else
+        }
+        else
+        {
+            if (var != null)
             {
-              child.processRestoreState(context, childState);
+                if (isRowAvailable())
+                {
+                    Object rowData = dataModel.getRowData();
+                    facesContext.getExternalContext().getRequestMap().put(var,
+                                    rowData);
+                }
+                else
+                {
+                    facesContext.getExternalContext().getRequestMap().remove(
+                                    var);
+                }
             }
-          }
-          else
-          {
-            context.getExternalContext().log(
-                "No state found to restore child of component " + getId());
-          }
         }
-      }
-    }
-  }
 
-  private void setColumnChildsState(FacesContext context, Iterator compIterator, Object state)
-  {
-    List childrenList = (List) state;
-    if (childrenList != null)
-    {
-      int idx = 0;
-      while (compIterator.hasNext())
-      {
-        UIComponent child = (UIComponent) compIterator.next();
-        if (!child.isTransient())
+        if (_rowIndex == -1)
         {
-          Object childState = childrenList.get(idx++);
-          if (childState != null)
-          {
-            child.processRestoreState(context, childState);
-          }
-          else
-          {
-            context.getExternalContext().log(
-                "No state found to restore child of component " + getId());
-          }
+            restoreDescendantComponentStates(getChildren().iterator(),
+                            _initialDescendantComponentState);
+        }
+        else
+        {
+            Object rowState = _rowStates.get(getClientId(facesContext));
+            if (rowState == null)
+            {
+                restoreDescendantComponentStates(getChildren().iterator(),
+                                _initialDescendantComponentState);
+            }
+            else
+            {
+                restoreDescendantComponentStates(getChildren().iterator(),
+                                rowState);
+            }
         }
-      }
     }
-  }
 
-  public void setValueBinding(String name, ValueBinding binding)
-  {
-    if (name == null)
-    {
-      throw new NullPointerException("name");
-    }
-    else if (name.equals("value"))
-    {
-      _dataModelMap.clear();
-      _rowStates = null;
-    }
-    else if (name.equals("var") || name.equals("rowIndex"))
+    protected void restoreDescendantComponentStates(Iterator childIterator,
+                    Object state)
     {
-      throw new IllegalArgumentException("name " + name);
+        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());
+            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);
+        }
     }
-    super.setValueBinding(name, binding);
-  }
 
-  protected DataModel getDataModel()
-  {
-    String clientID = getParent().getClientId(getFacesContext());
-    DataModel dataModel = (DataModel) _dataModelMap.get(clientID);
-    if (dataModel == null)
+    protected Object saveDescendantComponentStates(Iterator childIterator)
     {
-      dataModel = createDataModel();
-      _dataModelMap.put(clientID, dataModel);
+        Collection childStates = null;
+        while (childIterator.hasNext())
+        {
+            if (childStates == null)
+            {
+                childStates = new ArrayList();
+            }
+            UIComponent child = (UIComponent) childIterator.next();
+            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;
     }
-    return dataModel;
-  }
 
-  protected void setDataModel(DataModel datamodel)
-  {
-    _dataModelMap.put(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)
+    public void setValueBinding(String name, ValueBinding binding)
     {
-      return new ResultDataModel((Result) value);
-    }
-    else
-    {
-      return new ScalarDataModel(value);
+        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);
     }
-  }
 
-  private static final DataModel EMPTY_DATA_MODEL = new DataModel()
-  {
-    public boolean isRowAvailable()
+    protected DataModel getDataModel()
     {
-      return false;
+        String clientID = getParent().getClientId(getFacesContext());
+        DataModel dataModel = (DataModel) _dataModelMap.get(clientID);
+        if (dataModel == null)
+        {
+            dataModel = createDataModel();
+            _dataModelMap.put(clientID, dataModel);
+        }
+        return dataModel;
     }
 
-    public int getRowCount()
+    protected void setDataModel(DataModel datamodel)
     {
-      return 0;
+        _dataModelMap
+                        .put(getParent().getClientId(getFacesContext()),
+                                        datamodel);
     }
 
-    public Object getRowData()
+    /**
+     * Creates a new DataModel around the current value.
+     */
+    protected DataModel createDataModel()
     {
-      throw new IllegalArgumentException();
+        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);
+        }
     }
 
-    public int getRowIndex()
+    private static final DataModel EMPTY_DATA_MODEL = new DataModel()
     {
-      return -1;
-    }
+        public boolean isRowAvailable()
+        {
+            return false;
+        }
 
-    public void setRowIndex(int i)
-    {
-      if (i < -1)
-        throw new IndexOutOfBoundsException("Index < 0 : " + i);
-    }
+        public int getRowCount()
+        {
+            return 0;
+        }
 
-    public Object getWrappedData()
-    {
-      return null;
-    }
+        public Object getRowData()
+        {
+            throw new IllegalArgumentException();
+        }
 
-    public void setWrappedData(Object obj)
-    {
-      if (obj == null)
-        return; //Clearing is allowed
-      throw new UnsupportedOperationException(this.getClass().getName()
-          + " UnsupportedOperationException");
-    }
-  };
+        public int getRowIndex()
+        {
+            return -1;
+        }
 
-  public Object saveState(FacesContext context)
-  {
-    Object values[] = new Object[2];
-    values[0] = super.saveState(context);
-    values[1] = Boolean.valueOf(_isValidChilds);
+        public void setRowIndex(int i)
+        {
+            if (i < -1)
+                throw new IndexOutOfBoundsException("Index < 0 : " + i);
+        }
 
-    return values;
-  }
+        public Object getWrappedData()
+        {
+            return null;
+        }
 
-  public void restoreState(FacesContext context, Object state)
-  {
-    Object values[] = (Object[]) state;
-    super.restoreState(context, values[0]);
+        public void setWrappedData(Object obj)
+        {
+            if (obj == null)
+                return; //Clearing is allowed
+            throw new UnsupportedOperationException(this.getClass().getName()
+                            + " UnsupportedOperationException");
+        }
+    };
 
-    Boolean validChilds = (Boolean) values[1];
-    if (validChilds != null)
+    private class EditableValueHolderState
     {
-      _isValidChilds = validChilds.booleanValue();
-    }
-    else
-    {
-      _isValidChilds = true;
-    }
-  }
+        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);
+        }
+    }
 }

Modified: myfaces/tomahawk/trunk/src/java/org/apache/myfaces/custom/crosstable/UIColumns.java
URL: http://svn.apache.org/viewcvs/myfaces/tomahawk/trunk/src/java/org/apache/myfaces/custom/crosstable/UIColumns.java?rev=225266&r1=225265&r2=225266&view=diff
==============================================================================
--- myfaces/tomahawk/trunk/src/java/org/apache/myfaces/custom/crosstable/UIColumns.java (original)
+++ myfaces/tomahawk/trunk/src/java/org/apache/myfaces/custom/crosstable/UIColumns.java Tue Jul 26 02:20:50 2005
@@ -16,11 +16,14 @@
 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;
@@ -39,485 +42,554 @@
  */
 public class UIColumns extends UIData
 {
-  public static final String COMPONENT_TYPE = "org.apache.myfaces.Columns";
-  public static final String COMPONENT_FAMILY = UIData.COMPONENT_FAMILY;
+    public static final String COMPONENT_TYPE = "org.apache.myfaces.Columns";
+    public static final String COMPONENT_FAMILY = UIData.COMPONENT_FAMILY;
 
-  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 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;
+    private boolean _isValidChilds = true;
 
-  // holds the the state for each cell of the child components of this UIColumns
-  private Map _cellStates = null;
+    // holds the the state for each cell of the child components of this UIColumns
+    private Map _cellStates = new HashMap();
 
-  // contains the initial cell state which is used to initialize each cell
-  private Object _initialCellState = null;
+    private Object _initialDescendantComponentState = null;
 
-  private int _colIndex = -1;
-  private UIData _parentUIData;
+    private int _colIndex = -1;
+    private UIData _parentUIData;
 
-  private Map _dataModelMap = new HashMap();
+    private Map _dataModelMap = new HashMap();
 
-  /**
-   *
-   */
-  public UIColumns()
-  {
-    super();
-  }
-
-  /**
-   * @see javax.faces.component.UIComponentBase#getRendererType()
-   */
-  public String getRendererType()
-  {
-    return null;
-  }
-
-  /**
-   * @see javax.faces.component.UIComponent#getFamily()
-   */
-  public String getFamily()
-  {
-    return COMPONENT_FAMILY;
-  }
-
-  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)
+    /**
+     *
+     */
+    public UIColumns()
     {
-      return;
+        super();
     }
 
-    FacesContext facesContext = getFacesContext();
-
-    int firstColIndex = getFirst();
+    /**
+     * @see javax.faces.component.UIComponentBase#getRendererType()
+     */
+    public String getRendererType()
+    {
+        return null;
+    }
 
-    if (_colIndex != -1)
+    /**
+     * @see javax.faces.component.UIComponent#getFamily()
+     */
+    public String getFamily()
     {
-      if (_cellStates == null)
-      {
-        _cellStates = new HashMap();
-      }
-      _cellStates.put(getClientId(facesContext), processSaveState(facesContext));
+        return COMPONENT_FAMILY;
     }
-    else if (_initialCellState == null)
+
+    public boolean isRowAvailable()
     {
-      _initialCellState = processSaveState(facesContext);
+        return getDataModel().isRowAvailable();
     }
 
-    _colIndex = colIndex;
+    public int getRowCount()
+    {
+        return getDataModel().getRowCount();
+    }
 
-    DataModel dataModel = getDataModel();
-    dataModel.setRowIndex(colIndex);
+    public Object getRowData()
+    {
+        return getDataModel().getRowData();
+    }
 
-    String var = getVar();
-    if (colIndex == -1)
+    public int getRowIndex()
     {
-      if (var != null)
-      {
-        facesContext.getExternalContext().getRequestMap().remove(var);
-      }
+        return _colIndex;
     }
-    else
+
+    public void setRowIndex(int colIndex)
     {
-      if (var != null)
-      {
-        if (isRowAvailable())
+        if (colIndex < -1)
         {
-          Object rowData = dataModel.getRowData();
-          facesContext.getExternalContext().getRequestMap().put(var, rowData);
+            throw new IllegalArgumentException("colIndex is less than -1");
         }
-        else
+
+        if (_colIndex == colIndex)
         {
-          facesContext.getExternalContext().getRequestMap().remove(var);
+            return;
         }
-      }
-    }
 
-    if (_colIndex != -1 && _cellStates != null)
-    {
-      Object state = _cellStates.get(getClientId(facesContext));
-      if (state == null)
-      {
-        state = _initialCellState;
-      }
-      processRestoreState(facesContext, state);
-    }
-    else
-    {
-      processRestoreState(facesContext, _initialCellState);
-    }
-  }
+        FacesContext facesContext = getFacesContext();
 
-  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);
-  }
+        if (_colIndex == -1)
+        {
+            if (_initialDescendantComponentState == null)
+            {
+                _initialDescendantComponentState = saveDescendantComponentStates(getFacetsAndChildren());
+            }
+        }
+        else
+        {
+            _cellStates
+                            .put(
+                                            getClientId(facesContext),
+                                            saveDescendantComponentStates(getFacetsAndChildren()));
+        }
 
-  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;
-  }
+        _colIndex = colIndex;
 
-  protected void setDataModel(DataModel dataModel)
-  {
-    _dataModelMap.put(getParentUIData().getParent().getClientId(getFacesContext()), dataModel);
-  }
+        DataModel dataModel = getDataModel();
+        dataModel.setRowIndex(colIndex);
 
-  /**
-   * 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);
+        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);
+            }
+        }
     }
-  }
 
-  private static final DataModel EMPTY_DATA_MODEL = new DataModel()
-  {
-    public boolean isRowAvailable()
+    protected void restoreDescendantComponentStates(Iterator childIterator,
+                    Object state)
     {
-      return false;
+        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());
+            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);
+        }
     }
 
-    public int getRowCount()
+    protected Object saveDescendantComponentStates(Iterator childIterator)
     {
-      return 0;
+        Collection childStates = null;
+        while (childIterator.hasNext())
+        {
+            if (childStates == null)
+            {
+                childStates = new ArrayList();
+            }
+            UIComponent child = (UIComponent) childIterator.next();
+            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;
     }
 
-    public Object getRowData()
+    public void setValueBinding(String name, ValueBinding binding)
     {
-      throw new IllegalArgumentException();
+        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);
     }
 
-    public int getRowIndex()
+    protected DataModel getDataModel()
     {
-      return -1;
+        String clientID = getParentUIData().getParent().getClientId(
+                        getFacesContext());
+        DataModel dataModel = (DataModel) _dataModelMap.get(clientID);
+        if (dataModel == null)
+        {
+            dataModel = createDataModel();
+            _dataModelMap.put(clientID, dataModel);
+        }
+        return dataModel;
     }
 
-    public void setRowIndex(int i)
+    protected void setDataModel(DataModel dataModel)
     {
-      if (i < -1)
-        throw new IndexOutOfBoundsException("Index < 0 : " + i);
+        _dataModelMap.put(getParentUIData().getParent().getClientId(
+                        getFacesContext()), dataModel);
     }
 
-    public Object getWrappedData()
+    /**
+     * Creates a new DataModel around the current value.
+     */
+    protected DataModel createDataModel()
     {
-      return null;
+        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);
+        }
     }
 
-    public void setWrappedData(Object obj)
+    private static final DataModel EMPTY_DATA_MODEL = new DataModel()
     {
-      if (obj == null)
-        return; //Clearing is allowed
-      throw new UnsupportedOperationException(this.getClass().getName()
-          + " UnsupportedOperationException");
-    }
-  };
+        public boolean isRowAvailable()
+        {
+            return false;
+        }
 
-  public Object saveState(FacesContext context)
-  {
-    Object values[] = new Object[3];
-    values[0] = super.saveState(context);
-    values[1] = Boolean.valueOf(_isValidChilds);
+        public int getRowCount()
+        {
+            return 0;
+        }
 
-    return values;
-  }
+        public Object getRowData()
+        {
+            throw new IllegalArgumentException();
+        }
 
-  public void restoreState(FacesContext context, Object state)
-  {
-    Object values[] = (Object[]) state;
-    super.restoreState(context, values[0]);
+        public int getRowIndex()
+        {
+            return -1;
+        }
 
-    Boolean validChilds = (Boolean) values[2];
-    if (validChilds != null)
-    {
-      _isValidChilds = validChilds.booleanValue();
-    }
-    else
-    {
-      _isValidChilds = true;
-    }
-  }
+        public void setRowIndex(int i)
+        {
+            if (i < -1)
+                throw new IndexOutOfBoundsException("Index < 0 : " + i);
+        }
 
-  /**
-   * @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;
+        public Object getWrappedData()
+        {
+            return null;
+        }
 
-    setRowIndex(-1);
-    processColumnsFacets(context, PROCESS_DECODES);
-    processRows(context, PROCESS_DECODES);
-    setRowIndex(-1);
+        public void setWrappedData(Object obj)
+        {
+            if (obj == null)
+                return; //Clearing is allowed
+            throw new UnsupportedOperationException(this.getClass().getName()
+                            + " UnsupportedOperationException");
+        }
+    };
 
-    try
-    {
-      decode(context);
-    }
-    catch (RuntimeException e)
-    {
-      context.renderResponse();
-      throw e;
-    }
-  }
+    /**
+     * @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);
 
-  /**
-   * @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;
+        try
+        {
+            decode(context);
+        }
+        catch (RuntimeException e)
+        {
+            context.renderResponse();
+            throw e;
+        }
     }
 
-    for (int colIndex = first; colIndex < last; colIndex++)
-    {
-      setRowIndex(colIndex);
-      if (isRowAvailable())
-      {
-        for (Iterator facetsIter = getFacets().values().iterator(); facetsIter.hasNext();)
+    /**
+     * @param context
+     * @param process_decodes2
+     */
+    private void processColumnsFacets(FacesContext context, int processAction)
+    {
+        int first = getFirst();
+        int cols = getRows();
+        int last;
+        if (cols == 0)
         {
-          UIComponent facet = (UIComponent) facetsIter.next();
-          process(context, facet, processAction);
+            last = getRowCount();
+        }
+        else
+        {
+            last = first + cols;
         }
-      }
-    }
-    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 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);
     }
 
-    for (int rowIndex = first; rowIndex < last; rowIndex++)
-    {
-      parentUIData.setRowIndex(rowIndex);
-      if (parentUIData.isRowAvailable())
-      {
-        processColumns(context, processAction);
-      }
-    }
-  }
+    /**
+     * @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;
+        }
 
-  /**
-   * 
-   */
-  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;
+        for (int rowIndex = first; rowIndex < last; rowIndex++)
+        {
+            parentUIData.setRowIndex(rowIndex);
+            if (parentUIData.isRowAvailable())
+            {
+                processColumns(context, processAction);
+            }
+        }
     }
-    return _parentUIData;
-  }
 
-  private void processColumns(FacesContext context, int processAction)
-  {
-    int first = getFirst();
-    int cols = getRows();
-    int last;
-    if (cols == 0)
+    /**
+     * 
+     */
+    private UIData getParentUIData()
     {
-      last = getRowCount();
-    }
-    else
-    {
-      last = first + cols;
+        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;
     }
 
-    for (int colIndex = first; colIndex < last; colIndex++)
+    private void processColumns(FacesContext context, int processAction)
     {
-      setRowIndex(colIndex);
-      if (isRowAvailable())
-      {
-        for (Iterator columnChildIter = getChildren().iterator(); columnChildIter.hasNext();)
+        int first = getFirst();
+        int cols = getRows();
+        int last;
+        if (cols == 0)
         {
-          UIComponent columnChild = (UIComponent) columnChildIter.next();
-          process(context, columnChild, processAction);
+            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);
     }
-    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);
+    /**
+     * @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;
+        // 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);
+    /**
+     * @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())
+        // 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)
     {
-      _isValidChilds = false;
+        switch (processAction)
+        {
+            case PROCESS_DECODES:
+                component.processDecodes(context);
+                break;
+            case PROCESS_VALIDATORS:
+                component.processValidators(context);
+                break;
+            case PROCESS_UPDATES:
+                component.processUpdates(context);
+                break;
+        }
     }
-  }
 
-  private void process(FacesContext context, UIComponent component, int processAction)
-  {
-    switch (processAction)
+    public void encodeTableBegin(FacesContext context)
     {
-      case PROCESS_DECODES:
-        component.processDecodes(context);
-        break;
-      case PROCESS_VALIDATORS:
-        component.processValidators(context);
-        break;
-      case PROCESS_UPDATES:
-        component.processUpdates(context);
-        break;
+        if (_isValidChilds)
+        {
+            //Refresh DataModel for rendering:
+            _dataModelMap.clear();
+            _cellStates.clear();
+            _initialDescendantComponentState = null;
+        }
     }
-  }
 
-  public void encodeTableBegin(FacesContext context)
-  {
-    if (_isValidChilds)
+    public void encodeTableEnd(FacesContext context)
     {
-      //Refresh DataModel for rendering:
-      _dataModelMap.clear();
-      _cellStates = null;
+        setRowIndex(-1);
     }
-  }
 
-  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);
+        }
+    }
 }