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