You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by sc...@apache.org on 2005/07/08 00:03:01 UTC

svn commit: r209659 - in /myfaces: api/trunk/src/java/javax/faces/component/ examples/trunk/simple/ examples/trunk/simple/WEB-INF/ examples/trunk/standard/src/java/org/apache/myfaces/examples/listexample/ tomahawk/trunk/src/java/org/apache/myfaces/comp...

Author: schof
Date: Thu Jul  7 15:03:00 2005
New Revision: 209659

URL: http://svn.apache.org/viewcvs?rev=209659&view=rev
Log:
UIData fix by Mathias Broekelmann

Modified:
    myfaces/api/trunk/src/java/javax/faces/component/UIData.java
    myfaces/examples/trunk/simple/WEB-INF/   (props changed)
    myfaces/examples/trunk/simple/pagedSortTable.jsp
    myfaces/examples/trunk/standard/src/java/org/apache/myfaces/examples/listexample/OpenDataList.java
    myfaces/examples/trunk/standard/src/java/org/apache/myfaces/examples/listexample/PagedSortableCarList.java
    myfaces/tomahawk/trunk/src/java/org/apache/myfaces/component/html/ext/HtmlDataTable.java
    myfaces/tomahawk/trunk/src/java/org/apache/myfaces/component/html/ext/HtmlDataTableHack.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=209659&r1=209658&r2=209659&view=diff
==============================================================================
--- myfaces/api/trunk/src/java/javax/faces/component/UIData.java (original)
+++ myfaces/api/trunk/src/java/javax/faces/component/UIData.java Thu Jul  7 15:03:00 2005
@@ -45,13 +45,15 @@
  */
 public class UIData extends UIComponentBase implements NamingContainer
 {
-	private static final int STATE_SIZE = 6;
+	private static final int STATE_SIZE = 8;
 	private static final int SUPER_STATE_INDEX = 0;
-	private static final int FIRST_INDEX = 1;
-	private static final int ROWS_INDEX = 2;
-	private static final int VALUE_INDEX = 3;
-	private static final int VAR_INDEX = 4;
+	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 ROW_STATE_INDEX = 5;
+	private static final int DATAMODEL_STATE_INDEX = 6;
+	private static final int VALID_CHILDS_STATE_INDEX = 7;
 
 	private static final String FOOTER_FACET_NAME = "footer";
 	private static final String HEADER_FACET_NAME = "header";
@@ -68,14 +70,14 @@
 	// holds the states of the child components of this UIData 
 	private Map _rowState = new HashMap();
 
-	private Boolean _isEmbeddedUIData = null;
-	private UIData _embeddingUIData = null;
 	private DataModel _dataModel = null;
-	private Map _dataModelMap = null;
 
 	// 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 _rowstate and _datamodel should not be saved
+	private boolean _processUIDataState = true;
+
 	public void setFooter(UIComponent footer)
 	{
 		getFacets().put(FOOTER_FACET_NAME, footer);
@@ -167,7 +169,10 @@
 			if (!child.isTransient())
 			{
 				_rowState.put(child.getClientId(context), new ChildStateHolder(context, child));
-				saveDescendantComponentStates(context, child.getFacetsAndChildren());
+				if (!(child instanceof UIData))
+				{
+					saveDescendantComponentStates(context, child.getFacetsAndChildren());
+				}
 			}
 		}
 	}
@@ -177,7 +182,7 @@
 		while (childIterator.hasNext())
 		{
 			UIComponent child = (UIComponent) childIterator.next();
-			//reset clientId to null
+			// the spec 1.1 (3.1.6) says: setting the id will recalculate the clientid  
 			child.setId(child.getId());
 			if (!child.isTransient())
 			{
@@ -187,7 +192,10 @@
 				{
 					childStateHolder.restoreState(context, child);
 				}
-				restoreDescendantComponentStates(context, child.getFacetsAndChildren());
+				if (!(child instanceof UIData))
+				{
+					restoreDescendantComponentStates(context, child.getFacetsAndChildren());
+				}
 			}
 		}
 	}
@@ -234,10 +242,7 @@
 		{
 			return clientId;
 		}
-		else
-		{
-			return clientId + "_" + rowIndex;
-		}
+		return clientId + "_" + rowIndex;
 	}
 
 	public void queueEvent(FacesEvent event)
@@ -268,8 +273,6 @@
 		{
 			//Refresh DataModel for rendering:
 			_dataModel = null;
-			if (_dataModelMap != null)
-				_dataModelMap.clear();
 		}
 		super.encodeBegin(context);
 	}
@@ -277,7 +280,6 @@
 	public void encodeEnd(FacesContext context) throws IOException
 	{
 		setRowIndex(-1);
-
 		super.encodeEnd(context);
 	}
 
@@ -361,7 +363,8 @@
 					//Column is not visible
 					continue;
 				}
-				for (Iterator facetsIter = child.getFacets().values().iterator(); facetsIter.hasNext();)
+				for (Iterator facetsIter = child.getFacets().values().iterator(); facetsIter
+								.hasNext();)
 				{
 					UIComponent facet = (UIComponent) facetsIter.next();
 					process(context, facet, processAction);
@@ -428,37 +431,11 @@
 
 	private DataModel getDataModel()
 	{
-		UIData embeddingUIData = getEmbeddingUIData();
-		if (embeddingUIData != null)
+		if (_dataModel == null)
 		{
-			//This UIData is nested in another UIData, so we must not
-			//do simple caching of the current DataModel. We must associate
-			//the DataModel that we want to cache with the clientId of the
-			//embedding UIData. This clientId will be different for every
-			//row of the embedding UIData.
-			if (_dataModelMap == null)
-			{
-				_dataModelMap = new HashMap();
-			}
-			String embeddingClientId = embeddingUIData.getClientId(FacesContext.getCurrentInstance());
-			DataModel dataModel = (DataModel) _dataModelMap.get(embeddingClientId);
-			if (dataModel == null)
-			{
-				dataModel = createDataModel();
-				_dataModelMap.put(embeddingClientId, dataModel);
-			}
-			return dataModel;
-		}
-		else
-		{
-			//This UIData is not nested within another UIData. So there
-			//is no need for the DataModel Map.
-			if (_dataModel == null)
-			{
-				_dataModel = createDataModel();
-			}
-			return _dataModel;
+			_dataModel = createDataModel();
 		}
+		return _dataModel;
 	}
 
 	/**
@@ -501,57 +478,6 @@
 		}
 	}
 
-	/**
-	 * Looks for an embedding UIData component
-	 * @return the embedding UIData or null
-	 */
-	private UIData getEmbeddingUIData()
-	{
-		if (_isEmbeddedUIData == null)
-		{
-			UIComponent findParentUIData = getParent();
-			while (findParentUIData != null && !(findParentUIData instanceof UIData))
-			{
-				findParentUIData = findParentUIData.getParent();
-			}
-			if (findParentUIData != null)
-			{
-				_embeddingUIData = (UIData) findParentUIData;
-				_isEmbeddedUIData = Boolean.TRUE;
-			}
-			else
-			{
-				_isEmbeddedUIData = Boolean.FALSE;
-			}
-		}
-
-		if (_isEmbeddedUIData.booleanValue())
-		{
-			return _embeddingUIData;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	private static class UIDataRowIndexState
-	{
-		private UIData _uiData;
-		private int _rowIndex;
-
-		public UIDataRowIndexState(UIData uiData)
-		{
-			_uiData = uiData;
-			_rowIndex = _uiData._rowIndex;
-		}
-
-		public void restore()
-		{
-			_uiData._rowIndex = _rowIndex;
-		}
-	}
-
 	private static class FacesEventWrapper extends FacesEvent
 	{
 		private FacesEvent _wrappedFacesEvent;
@@ -668,34 +594,80 @@
 		_dataModel = null;
 	}
 
+	/**
+	 * @see javax.faces.component.UIComponentBase#processSaveState(javax.faces.context.FacesContext)
+	 */
+	public Object processSaveState(FacesContext context)
+	{
+		// state of uidata will not be processed
+		_processUIDataState = false;
+		Object state = super.processSaveState(context);
+		_processUIDataState = true;
+		return state;
+	}
+
+	/**
+	 * @see javax.faces.component.UIComponentBase#processRestoreState(javax.faces.context.FacesContext, java.lang.Object)
+	 */
+	public void processRestoreState(FacesContext context, Object state)
+	{
+		_processUIDataState = false;
+		super.processRestoreState(context, state);
+		_processUIDataState = true;
+	}
+
 	public Object saveState(FacesContext context)
 	{
 		Object[] values = new Object[STATE_SIZE];
 		values[SUPER_STATE_INDEX] = super.saveState(context);
-		values[FIRST_INDEX] = _first;
-		values[ROWS_INDEX] = _rows;
-		values[VALUE_INDEX] = _value;
-		values[VAR_INDEX] = _var;
-//		if (!_isValidChilds)
-//		{
-//			values[ROW_STATE_INDEX] = _rowState;
-//		}
-		return ((Object) (values));
+		values[FIRST_STATE_INDEX] = _first;
+		values[ROWS_STATE_INDEX] = _rows;
+		values[VALUE_STATE_INDEX] = _value;
+		values[VAR_STATE_INDEX] = _var;
+
+		if (_processUIDataState)
+		{
+			values[ROW_STATE_INDEX] = _rowState;
+			values[DATAMODEL_STATE_INDEX] = _dataModel;
+			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_INDEX];
-		_rows = (Integer) values[ROWS_INDEX];
-		_value = (Object) values[VALUE_INDEX];
-		_var = (String) values[VAR_INDEX];
-//		Map rowState = (Map) values[ROW_STATE_INDEX];
-//		if (rowState != null)
-//		{
-//			_rowState = rowState;
-//		}
+		_first = (Integer) values[FIRST_STATE_INDEX];
+		_rows = (Integer) values[ROWS_STATE_INDEX];
+		_value = (Object) values[VALUE_STATE_INDEX];
+		_var = (String) values[VAR_STATE_INDEX];
+
+		if (_processUIDataState)
+		{
+			Map rowState = (Map) values[ROW_STATE_INDEX];
+			if (rowState != null)
+			{
+				_rowState = rowState;
+			}
+			else
+			{
+				_rowState.clear();
+			}
+
+			_dataModel = (DataModel) values[DATAMODEL_STATE_INDEX];
+
+			Boolean validChilds = (Boolean) values[VALID_CHILDS_STATE_INDEX];
+			if (validChilds != null)
+			{
+				_isValidChilds = validChilds.booleanValue();
+			}
+			else
+			{
+				// defaults to true
+				_isValidChilds = true;
+			}
+		}
 	}
 
 	//------------------ GENERATED CODE BEGIN (do not modify!) --------------------

Propchange: myfaces/examples/trunk/simple/WEB-INF/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Thu Jul  7 15:03:00 2005
@@ -1 +1,4 @@
 lib
+classes
+lib
+*.xml

Modified: myfaces/examples/trunk/simple/pagedSortTable.jsp
URL: http://svn.apache.org/viewcvs/myfaces/examples/trunk/simple/pagedSortTable.jsp?rev=209659&r1=209658&r2=209659&view=diff
==============================================================================
--- myfaces/examples/trunk/simple/pagedSortTable.jsp (original)
+++ myfaces/examples/trunk/simple/pagedSortTable.jsp Thu Jul  7 15:03:00 2005
@@ -34,7 +34,7 @@
 <f:view>
 
     <f:loadBundle basename="org.apache.myfaces.examples.resource.example_messages" var="example_messages"/>
-
+	<h:form>
      <x:dataTable id="data"
                   styleClass="scrollerTable"
                   headerClass="standardTable_Header"
@@ -54,7 +54,7 @@
         </h:column>
         <h:column>
             <f:facet name="header">
-                <x:commandSortHeader columnName="type" arrow="true">
+                <x:commandSortHeader columnName="type" arrow="true" immediate="false">
                     <h:outputText value="#{example_messages['sort_cartype']}" />
                 </x:commandSortHeader>
             </f:facet>
@@ -62,11 +62,13 @@
         </h:column>
         <h:column>
             <f:facet name="header">
-                <x:commandSortHeader columnName="color" arrow="true">
+                <x:commandSortHeader columnName="color" arrow="true" immediate="false">
                     <h:outputText value="#{example_messages['sort_carcolor']}" />
                 </x:commandSortHeader>
             </f:facet>
-            <h:outputText value="#{car.color}" />
+            <h:inputText value="#{car.color}" >
+            	<f:validateLength maximum="10"/>
+            </h:inputText>
         </h:column>
     </x:dataTable>
 
@@ -81,6 +83,7 @@
                         paginatorMaxPages="9"
                         paginatorTableClass="paginator"
                         paginatorActiveColumnStyle="font-weight:bold;">
+            <f:actionListener type="org.apache.myfaces.examples.listexample.DataScrollerActionListener"/>
             <f:facet name="first" >
                 <h:graphicImage url="images/arrow-first.gif" border="1" />
             </f:facet>
@@ -102,7 +105,7 @@
         </x:dataScroller>
 
     </h:panelGrid>
-
+	</h:form>
 </f:view>
 
 <%@include file="inc/page_footer.jsp" %>

Modified: myfaces/examples/trunk/standard/src/java/org/apache/myfaces/examples/listexample/OpenDataList.java
URL: http://svn.apache.org/viewcvs/myfaces/examples/trunk/standard/src/java/org/apache/myfaces/examples/listexample/OpenDataList.java?rev=209659&r1=209658&r2=209659&view=diff
==============================================================================
--- myfaces/examples/trunk/standard/src/java/org/apache/myfaces/examples/listexample/OpenDataList.java (original)
+++ myfaces/examples/trunk/standard/src/java/org/apache/myfaces/examples/listexample/OpenDataList.java Thu Jul  7 15:03:00 2005
@@ -44,6 +44,12 @@
         sort(getSort(), isAscending());
         return data;
     }
+    
+    void setData(DataModel datamodel)
+    {
+    	System.out.println("preserved datamodel updated");
+    	// just here to see if the datamodel is updated if preservedatamodel=true
+    }
 
     public DataModel getColumnHeaders()
     {

Modified: myfaces/examples/trunk/standard/src/java/org/apache/myfaces/examples/listexample/PagedSortableCarList.java
URL: http://svn.apache.org/viewcvs/myfaces/examples/trunk/standard/src/java/org/apache/myfaces/examples/listexample/PagedSortableCarList.java?rev=209659&r1=209658&r2=209659&view=diff
==============================================================================
--- myfaces/examples/trunk/standard/src/java/org/apache/myfaces/examples/listexample/PagedSortableCarList.java (original)
+++ myfaces/examples/trunk/standard/src/java/org/apache/myfaces/examples/listexample/PagedSortableCarList.java Thu Jul  7 15:03:00 2005
@@ -16,56 +16,80 @@
 
 package org.apache.myfaces.examples.listexample;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
 
 public class PagedSortableCarList extends SortableList
 {
-    private List cars = new ArrayList();
+	private List cars = new ArrayList();
 
-    public PagedSortableCarList()
-    {
-        super("type");
-        for (int i = 100; i < 900; i++)
-        {
-            cars.add(new SimpleCar(i, "Car Type " + i, (i%2==0) ? "blue" : "green"));
-        }
-    }
-
-    public List getCars()
-    {
-        sort(getSort(), isAscending());
-        return cars;
-    }
-
-    protected boolean isDefaultAscending(String sortColumn)
-    {
-        return true;
-    }
-
-    protected void sort(final String column, final boolean ascending)
-    {
-        Comparator comparator = new Comparator()
-        {
-            public int compare(Object o1, Object o2)
-            {
-                SimpleCar c1 = (SimpleCar)o1;
-                SimpleCar c2 = (SimpleCar)o2;
-                if (column == null)
-                {
-                    return 0;
-                }
-                if (column.equals("type"))
-                {
-                    return ascending ? c1.getType().compareTo(c2.getType()) : c2.getType().compareTo(c1.getType());
-                }
-                else if (column.equals("color"))
-                {
-                    return ascending ? c1.getColor().compareTo(c2.getColor()) : c2.getColor().compareTo(c1.getColor());
-                }
-                else return 0;
-            }
-        };
-        Collections.sort(cars, comparator);
-    }
+	private Map carMap = new HashMap();
 
+	public PagedSortableCarList()
+	{
+		super("type");
+		for (int i = 100; i < 900; i++)
+		{
+			Object car = new SimpleCar(i, "Car Type " + i, (i % 2 == 0) ? "blue" : "green");
+			cars.add(car);
+			carMap.put(new Integer(i), car);
+		}
+	}
+
+	public List getCars()
+	{
+		sort(getSort(), isAscending());
+		return cars;
+	}
+
+	public void setCars(List cars)
+	{
+		// update the cars from the provided list
+		for (Iterator iter = cars.iterator(); iter.hasNext();)
+		{
+			SimpleCar car = (SimpleCar) iter.next();
+			SimpleCar oldCar = (SimpleCar) carMap.get(new Integer(car.getId()));
+			oldCar.setType(car.getType());
+			oldCar.setColor(car.getColor());
+		}
+	}
+
+	protected boolean isDefaultAscending(String sortColumn)
+	{
+		return true;
+	}
+
+	protected void sort(final String column, final boolean ascending)
+	{
+		Comparator comparator = new Comparator()
+		{
+			public int compare(Object o1, Object o2)
+			{
+				SimpleCar c1 = (SimpleCar) o1;
+				SimpleCar c2 = (SimpleCar) o2;
+				if (column == null)
+				{
+					return 0;
+				}
+				if (column.equals("type"))
+				{
+					return ascending ? c1.getType().compareTo(c2.getType()) : c2.getType()
+									.compareTo(c1.getType());
+				}
+				else if (column.equals("color"))
+				{
+					return ascending ? c1.getColor().compareTo(c2.getColor()) : c2.getColor()
+									.compareTo(c1.getColor());
+				}
+				else
+					return 0;
+			}
+		};
+		Collections.sort(cars, comparator);
+	}
 }

Modified: myfaces/tomahawk/trunk/src/java/org/apache/myfaces/component/html/ext/HtmlDataTable.java
URL: http://svn.apache.org/viewcvs/myfaces/tomahawk/trunk/src/java/org/apache/myfaces/component/html/ext/HtmlDataTable.java?rev=209659&r1=209658&r2=209659&view=diff
==============================================================================
--- myfaces/tomahawk/trunk/src/java/org/apache/myfaces/component/html/ext/HtmlDataTable.java (original)
+++ myfaces/tomahawk/trunk/src/java/org/apache/myfaces/component/html/ext/HtmlDataTable.java Thu Jul  7 15:03:00 2005
@@ -214,7 +214,8 @@
 					for (int i = 0, size = columns.getRowCount(); i < size; i++)
 					{
 						columns.setRowIndex(i);
-						for (Iterator facetsIter = child.getFacets().values().iterator(); facetsIter.hasNext();)
+						for (Iterator facetsIter = child.getFacets().values().iterator(); facetsIter
+										.hasNext();)
 						{
 							UIComponent facet = (UIComponent) facetsIter.next();
 							process(context, facet, processAction);
@@ -356,6 +357,8 @@
 				}
 			}
 		}
+		_dataModel = null;
+		_isDataModelRestored = false;
 	}
 
 	/**

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=209659&r1=209658&r2=209659&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 Thu Jul  7 15:03:00 2005
@@ -30,363 +30,360 @@
  */
 abstract class HtmlDataTableHack extends javax.faces.component.html.HtmlDataTable
 {
-  protected DataModel _dataModel = null;
-  protected HashMap _dataModelMap = null;
+	protected DataModel _dataModel = null;
 
-  // 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;
 
-  private Map _rowState = new HashMap();
+	private Map _rowState = new HashMap();
 
-  // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-  // Every field and method from here is identical to UIData !!!!!!!!!
-
-  private static final Class OBJECT_ARRAY_CLASS = (new Object[0]).getClass();
-
-  private static final Integer INTEGER_MINUS1 = new Integer(-1);
-
-  private int _rowIndex = -1;
-
-  private Boolean _isEmbeddedUIData = null;
-  private UIData _embeddingUIData = null;
-
-  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#processValidators(javax.faces.context.FacesContext)
-   */
-  public void processValidators(FacesContext context)
-  {
-    super.processValidators(context);
-    // 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)
-  {
-    super.processUpdates(context);
-    // check if an validation error forces the render response for our data
-    if (context.getRenderResponse())
-    {
-      _isValidChilds = false;
-    }
-  }
-
-  /**
-   * @see javax.faces.component.UIData#encodeBegin(javax.faces.context.FacesContext)
-   */
-  public void encodeBegin(FacesContext context) throws IOException
-  {
-    // TODO Auto-generated method stub
-    if (_isValidChilds)
-    {
-      //Refresh DataModel for rendering:
-      _dataModel = null;
-      if (_dataModelMap != null)
-        _dataModelMap.clear();
-    }
-    super.encodeBegin(context);
-  }
-
-  public void setRowIndex(int rowIndex)
-  {
-    if (_rowIndex == rowIndex)
-    {
-      return;
-    }
-
-    FacesContext context = getFacesContext();
-
-    saveDescendantComponentStates(context, getFacetsAndChildren());
-
-    _rowIndex = rowIndex;
-
-    DataModel dataModel = getDataModel();
-    dataModel.setRowIndex(rowIndex);
-
-    String var = getVar();
-    if (rowIndex == -1)
-    {
-      if (var != null)
-      {
-        context.getExternalContext().getRequestMap().remove(var);
-      }
-    }
-    else
-    {
-      if (var != null)
-      {
-        if (isRowAvailable())
-        {
-          Object rowData = dataModel.getRowData();
-          context.getExternalContext().getRequestMap().put(var, rowData);
-        }
-        else
-        {
-          context.getExternalContext().getRequestMap().remove(var);
-        }
-      }
-    }
-
-    restoreDescendantComponentStates(context, getFacetsAndChildren());
-  }
-
-  private void saveDescendantComponentStates(FacesContext context, Iterator childIterator)
-  {
-    while (childIterator.hasNext())
-    {
-      UIComponent child = (UIComponent) childIterator.next();
-      if (!child.isTransient())
-      {
-        saveDescendantComponentStates(context, child.getFacetsAndChildren());
-        _rowState.put(child.getClientId(context), new ChildStateHolder(context, child));
-      }
-    }
-  }
-
-  private void restoreDescendantComponentStates(FacesContext context, Iterator childIterator)
-  {
-    while (childIterator.hasNext())
-    {
-      UIComponent child = (UIComponent) childIterator.next();
-      //reset clientId to null
-      child.setId(child.getId());
-      if (!child.isTransient())
-      {
-        String clientId = child.getClientId(context);
-        ChildStateHolder childStateHolder = (ChildStateHolder) _rowState.get(clientId);
-        if (childStateHolder != null)
-        {
-          childStateHolder.restoreState(context, child);
-        }
-        restoreDescendantComponentStates(context, child.getFacetsAndChildren());
-      }
-    }
-  }
-
-  public void setValueBinding(String name, ValueBinding binding)
-  {
-    if (name == null)
-    {
-      throw new NullPointerException("name");
-    }
-    else if (name.equals("value"))
-    {
-      _dataModel = null;
-    }
-    else if (name.equals("var") || name.equals("rowIndex"))
-    {
-      throw new IllegalArgumentException("name " + name);
-    }
-    super.setValueBinding(name, binding);
-  }
-
-  private DataModel getDataModel()
-  {
-    UIData embeddingUIData = getEmbeddingUIData();
-    if (embeddingUIData != null)
-    {
-      //This UIData is nested in another UIData, so we must not
-      //do simple caching of the current DataModel. We must associate
-      //the DataModel that we want to cache with the clientId of the
-      //embedding UIData. This clientId will be different for every
-      //row of the embedding UIData.
-      if (_dataModelMap == null)
-      {
-        _dataModelMap = new HashMap();
-      }
-      String embeddingClientId = embeddingUIData.getClientId(FacesContext.getCurrentInstance());
-      DataModel dataModel = (DataModel) _dataModelMap.get(embeddingClientId);
-      if (dataModel == null)
-      {
-        dataModel = createDataModel();
-        _dataModelMap.put(embeddingClientId, dataModel);
-      }
-      return dataModel;
-    }
-    else
-    {
-      //This UIData is not nested within another UIData. So there
-      //is no need for the DataModel Map.
-      if (_dataModel == null)
-      {
-        _dataModel = createDataModel();
-      }
-      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 (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);
-    }
-  }
-
-  /**
-   * Looks for an embedding UIData component
-   * @return the embedding UIData or null
-   */
-  private UIData getEmbeddingUIData()
-  {
-    if (_isEmbeddedUIData == null)
-    {
-      UIComponent findParentUIData = getParent();
-      while (findParentUIData != null && !(findParentUIData instanceof UIData))
-      {
-        findParentUIData = findParentUIData.getParent();
-      }
-      if (findParentUIData != null)
-      {
-        _embeddingUIData = (UIData) findParentUIData;
-        _isEmbeddedUIData = Boolean.TRUE;
-      }
-      else
-      {
-        _isEmbeddedUIData = Boolean.FALSE;
-      }
-    }
-
-    if (_isEmbeddedUIData.booleanValue())
-    {
-      return _embeddingUIData;
-    }
-    else
-    {
-      return null;
-    }
-  }
-
-  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");
-    }
-  };
-
-  private static class ChildStateHolder implements Serializable
-  {
-    private final Object _state;
-
-    public ChildStateHolder(FacesContext context, StateHolder stateHolder)
-    {
-      _state = stateHolder.saveState(context);
-    }
-
-    public void restoreState(FacesContext context, StateHolder stateHolder)
-    {
-      stateHolder.restoreState(context, _state);
-    }
-  }
-
-  public Object saveState(FacesContext context)
-  {
-    Object values[] = new Object[2];
-    values[0] = super.saveState(context);
-//    if (!_isValidChilds)
-//    {
-//      values[1] = _rowState;
-//    }
-    return values;
-  }
-
-  public void restoreState(FacesContext context, Object state)
-  {
-    Object values[] = (Object[]) state;
-    super.restoreState(context, values[0]);
-//    Map rowState = (Map) values[1];
-//    if (rowState != null)
-//    {
-//      _rowState = rowState;
-//    }
-  }
+	// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+	// Every field and method from here is identical to UIData !!!!!!!!!
+
+	private static final Class OBJECT_ARRAY_CLASS = (new Object[0]).getClass();
+
+	private static final Integer INTEGER_MINUS1 = new Integer(-1);
+
+	private int _rowIndex = -1;
+
+	// will be set to false if the _rowstate and _datamodel should not be saved
+	private boolean _processUIDataState = true;
+
+	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())
+		{
+			_isValidChilds = false;
+		}
+	}
+
+	/**
+	 * @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;
+		}
+	}
+
+	/**
+	 * @see javax.faces.component.UIData#encodeBegin(javax.faces.context.FacesContext)
+	 */
+	public void encodeBegin(FacesContext context) throws IOException
+	{
+		if (_isValidChilds)
+		{
+			//Refresh DataModel for rendering:
+			_dataModel = null;
+		}
+		super.encodeBegin(context);
+	}
+
+	/**
+	 * @see javax.faces.component.UIData#encodeEnd(javax.faces.context.FacesContext)
+	 */
+	public void encodeEnd(FacesContext context) throws IOException
+	{
+		setRowIndex(-1);
+		super.encodeEnd(context);
+	}
+
+	public void setRowIndex(int rowIndex)
+	{
+		if (_rowIndex == rowIndex)
+		{
+			return;
+		}
+
+		FacesContext context = getFacesContext();
+
+		saveDescendantComponentStates(context, getFacetsAndChildren());
+
+		_rowIndex = rowIndex;
+
+		DataModel dataModel = getDataModel();
+		dataModel.setRowIndex(rowIndex);
+
+		String var = getVar();
+		if (rowIndex == -1)
+		{
+			if (var != null)
+			{
+				context.getExternalContext().getRequestMap().remove(var);
+			}
+		}
+		else
+		{
+			if (var != null)
+			{
+				if (isRowAvailable())
+				{
+					Object rowData = dataModel.getRowData();
+					context.getExternalContext().getRequestMap().put(var, rowData);
+				}
+				else
+				{
+					context.getExternalContext().getRequestMap().remove(var);
+				}
+			}
+		}
+
+		restoreDescendantComponentStates(context, getFacetsAndChildren());
+	}
+
+	private void saveDescendantComponentStates(FacesContext context, Iterator childIterator)
+	{
+		while (childIterator.hasNext())
+		{
+			UIComponent child = (UIComponent) childIterator.next();
+			if (!child.isTransient())
+			{
+				_rowState.put(child.getClientId(context), new ChildStateHolder(context, child));
+				if (!(child instanceof UIData))
+				{
+					saveDescendantComponentStates(context, child.getFacetsAndChildren());
+				}
+			}
+		}
+	}
+
+	private void restoreDescendantComponentStates(FacesContext context, Iterator childIterator)
+	{
+		while (childIterator.hasNext())
+		{
+			UIComponent child = (UIComponent) childIterator.next();
+			// the spec 1.1 (3.1.6) says: setting the id will recalculate the clientid  
+			child.setId(child.getId());
+			if (!child.isTransient())
+			{
+				String clientId = child.getClientId(context);
+				ChildStateHolder childStateHolder = (ChildStateHolder) _rowState.get(clientId);
+				if (childStateHolder != null)
+				{
+					childStateHolder.restoreState(context, child);
+				}
+				if (!(child instanceof UIData))
+				{
+					restoreDescendantComponentStates(context, child.getFacetsAndChildren());
+				}
+			}
+		}
+	}
+
+	public void setValueBinding(String name, ValueBinding binding)
+	{
+		if (name == null)
+		{
+			throw new NullPointerException("name");
+		}
+		else if (name.equals("value"))
+		{
+			_dataModel = null;
+		}
+		else if (name.equals("var") || name.equals("rowIndex"))
+		{
+			throw new IllegalArgumentException("name " + name);
+		}
+		super.setValueBinding(name, binding);
+	}
+
+	private DataModel getDataModel()
+	{
+		if (_dataModel == null)
+		{
+			_dataModel = createDataModel();
+		}
+		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 (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");
+		}
+	};
+
+	private static class ChildStateHolder implements Serializable
+	{
+		private final Object _state;
+
+		public ChildStateHolder(FacesContext context, StateHolder stateHolder)
+		{
+			_state = stateHolder.saveState(context);
+		}
+
+		public void restoreState(FacesContext context, StateHolder stateHolder)
+		{
+			stateHolder.restoreState(context, _state);
+		}
+	}
+
+	/**
+	 * @see javax.faces.component.UIComponentBase#processSaveState(javax.faces.context.FacesContext)
+	 */
+	public Object processSaveState(FacesContext context)
+	{
+		// state of uidata will not be processed
+		_processUIDataState = false;
+		Object state = super.processSaveState(context);
+		_processUIDataState = true;
+		return state;
+	}
+
+	/**
+	 * @see javax.faces.component.UIComponentBase#processRestoreState(javax.faces.context.FacesContext, java.lang.Object)
+	 */
+	public void processRestoreState(FacesContext context, Object state)
+	{
+		_processUIDataState = false;
+		super.processRestoreState(context, state);
+		_processUIDataState = true;
+	}
+
+	public Object saveState(FacesContext context)
+	{
+		Object values[] = new Object[4];
+		values[0] = super.saveState(context);
+
+		if (_processUIDataState)
+		{
+			values[1] = _rowState;
+			values[2] = _dataModel;
+			values[3] = Boolean.valueOf(_isValidChilds);
+		}
+		return values;
+	}
+
+	public void restoreState(FacesContext context, Object state)
+	{
+		Object values[] = (Object[]) state;
+		super.restoreState(context, values[0]);
+
+		if (_processUIDataState)
+		{
+			Map rowState = (Map) values[1];
+			if (rowState != null)
+			{
+				_rowState = rowState;
+			}
+			else
+			{
+				_rowState.clear();
+			}
+
+			_dataModel = (DataModel) values[2];
+
+			Boolean validChilds = (Boolean) values[3];
+			if (validChilds != null)
+			{
+				_isValidChilds = validChilds.booleanValue();
+			}
+			else
+			{
+				// defaults to true
+				_isValidChilds = true;
+			}
+		}
+	}
 
 }