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/05 18:28:02 UTC

svn commit: r209297 - /myfaces/api/trunk/src/java/javax/faces/component/UIData.java

Author: schof
Date: Tue Jul  5 09:28:01 2005
New Revision: 209297

URL: http://svn.apache.org/viewcvs?rev=209297&view=rev
Log:
Patch by Mathias Broekelmann (for MYFACES-228)

Modified:
    myfaces/api/trunk/src/java/javax/faces/component/UIData.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=209297&r1=209296&r2=209297&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  5 09:28:01 2005
@@ -64,21 +64,17 @@
 
 	private int _rowIndex = -1;
 	private String _var = null;
-	//    private Object[] _descendantStates;
-	//    private int _descendantEditableValueHolderCount = -1;
 
-	private UIDataRowState _rowState = new UIDataRowState();
-
-	//init to false, so that no descendant states are saved for a newly created UIData
-	transient private boolean _saveDescendantStates = false;
-
-	//Flag to detect if component is rendered for the first time (restoreState sets it to false)
-	transient private boolean _firstTimeRendered = true;
+	// 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 HashMap _dataModelMap = 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;
 
 	public void setFooter(UIComponent footer)
 	{
@@ -122,7 +118,14 @@
 
 	public void setRowIndex(int rowIndex)
 	{
-		saveDescendantComponentStates(getFacesContext(), this);
+		if (_rowIndex == rowIndex)
+		{
+			return;
+		}
+
+		FacesContext facesContext = getFacesContext();
+
+		saveDescendantComponentStates(facesContext, this);
 
 		_rowIndex = rowIndex;
 
@@ -134,7 +137,7 @@
 		{
 			if (var != null)
 			{
-				getFacesContext().getExternalContext().getRequestMap().remove(var);
+				facesContext.getExternalContext().getRequestMap().remove(var);
 			}
 		}
 		else
@@ -144,349 +147,51 @@
 				if (isRowAvailable())
 				{
 					Object rowData = dataModel.getRowData();
-					getFacesContext().getExternalContext().getRequestMap().put(var, rowData);
+					facesContext.getExternalContext().getRequestMap().put(var, rowData);
 				}
 				else
 				{
-					getFacesContext().getExternalContext().getRequestMap().remove(var);
+					facesContext.getExternalContext().getRequestMap().remove(var);
 				}
 			}
 		}
 
-		restoreDescendantComponentStates(getFacesContext(), this, true);
+		restoreDescendantComponentStates(facesContext, this);
 	}
 
-	//    private int getDescendantStatesRowIndex()
-	//    {
-	//        int rowIndex = getRowIndex();
-	//        if (rowIndex == -1)
-	//        {
-	//            return 0;
-	//        }
-	//        else
-	//        {
-	//            return rowIndex - getFirst() + 1;
-	//        }
-	//    }
-
 	private void saveDescendantComponentStates(FacesContext context, UIComponent component)
 	{
 		for (Iterator i = component.getFacetsAndChildren(); i.hasNext();)
 		{
-			//TODO: what if child is an EditableValueHolder AND a UIData?
-
 			UIComponent child = (UIComponent) i.next();
-			if (child instanceof UIData)
+			if (child.isRendered())
 			{
-				UIData childUIData = (UIData) child;
-				_rowState._clientIdsToChildUIDataStates.put(
-					childUIData.getClientId(context),
-					childUIData._rowState);
-				continue;
-			}
-
-			if (child instanceof EditableValueHolder)
-			{
-				EditableValueHolder childEVH = (EditableValueHolder) child;
-				_rowState._clientIdsToChildEVHStates.put(
-					child.getClientId(context),
-					new EditableValueHolderState(childEVH));
-			}
-
-			saveDescendantComponentStates(context, child);
-		}
-	}
-
-	//    /**
-	//     * The descendant Component states algorithm we implement here is pretty fast
-	//     * but does not support modification of the components tree during the lifecycle.
-	//     * TODO: should we offer an alternative implementation with a clientId based Map ?
-	//     */
-	//    private void saveDescendantComponentStates()
-	//    {
-	//        if (_descendantEditableValueHolderCount == -1)
-	//        {
-	//            //This is the first time we save the descendant components state
-	//            refreshDescendantDataStates();
-	//        }
-	//        else if (_descendantEditableValueHolderCount == 0)
-	//        {
-	//            //There are no EditableValueHolder children
-	//            return;
-	//        }
-	//        else
-	//        {
-	//            int rowIndex = getDescendantStatesRowIndex();
-	//            EditableValueHolderState[] rowState = null;
-	//            // make sure that the underlying data did not change size
-	//            // (i.e. someone added a row to the DataModel)
-	//            // BUG: #925693
-	//            if(rowIndex < _descendantStates.length) {
-	//                rowState = (EditableValueHolderState[])_descendantStates[rowIndex];
-	//            } else {
-	//                // changed size during the lifecycle - should refresh
-	//                refreshDescendantDataStates();
-	//                rowState = (EditableValueHolderState[])_descendantStates[rowIndex];
-	//            }
-	//            if (rowState == null)
-	//            {
-	//                rowState = new EditableValueHolderState[_descendantEditableValueHolderCount];
-	//                _descendantStates[rowIndex] = rowState;
-	//            }
-	//            saveDescendantComponentStates(this, rowState, 0, 0);
-	//        }
-	//    }
-
-	//    private void refreshDescendantDataStates() {
-	//        List list = new ArrayList();
-	//        saveDescendantComponentStates(this, list,0);
-	//        _descendantEditableValueHolderCount = list.size();
-	//        if (_descendantEditableValueHolderCount > 0)
-	//        {
-	//            EditableValueHolderState[] rowState
-	//                    = (EditableValueHolderState[])list.toArray(new EditableValueHolderState[list.size()]);
-	//            int rows = getRows();
-	//            if (rows <= 0)
-	//            {
-	//                rows = getRowCount() - getFirst();
-	//            }
-	//            _descendantStates = new Object[rows + 1];
-	//            int rowIndex = getDescendantStatesRowIndex();
-	//            _descendantStates[rowIndex] = rowState;
-	//        }
-	//    }
-
-	//    private static void saveDescendantComponentStates(UIComponent component, List list, int level)
-	//    {
-	//        for (Iterator it = getChildrenAndOptionalFacetsIterator(level,component); it.hasNext();)
-	//        {
-	//            UIComponent child = (UIComponent)it.next();
-	//            if (child instanceof EditableValueHolder)
-	//            {
-	//                list.add(new EditableValueHolderState((EditableValueHolder)child));
-	//            }
-	//            saveDescendantComponentStates(child, list, level+1);
-	//        }
-	//    }
-
-	//    private static Iterator getChildrenAndOptionalFacetsIterator(int level, UIComponent component)
-	//    {
-	//        Iterator it = null;
-	//
-	//        if(level>1)
-	//        {
-	//            it = component.getFacetsAndChildren();
-	//        }
-	//        else
-	//        {
-	//            it = component.getChildren().iterator();
-	//        }
-	//        return it;
-	//    }
-
-	//    private static int saveDescendantComponentStates(UIComponent component,
-	//                                                      EditableValueHolderState[] states,
-	//                                                      int counter, int level)
-	//    {
-	//
-	//        for (Iterator it = getChildrenAndOptionalFacetsIterator(level, component); it.hasNext();)
-	//        {
-	//            UIComponent child = (UIComponent)it.next();
-	//            if (child instanceof EditableValueHolder)
-	//            {
-	//                states[counter++] = new EditableValueHolderState((EditableValueHolder)child);
-	//            }
-	//            counter = saveDescendantComponentStates(child, states, counter,level+1);
-	//        }
-	//        return counter;
-	//    }
-
-	private static String getInitialClientId(FacesContext context, UIComponent component)
-	{
-		/*
-		 * The initialized value of oldRowIndex doesn't matter.  If we dont' find a
-		 * parentUIData, we'll throw an exception, and the value won't be used.
-		 * If we do find it, the value will be set to the parentUIData's rowIndex.
-		 * This is just to satisfy the compiler.
-		 */
-		int oldRowIndex = 0;
-		UIData parentUIData = null;
-
-		for (UIComponent parent = component.getParent(); parent != null; parent = parent.getParent())
-		{
-			if (parent instanceof UIData)
-			{
-				parentUIData = (UIData) parent;
-				oldRowIndex = parentUIData._rowIndex;
-				parentUIData._rowIndex = -1;
-				break;
+				_rowState.put(child.getClientId(context), new ChildStateHolder(context, child));
+				saveDescendantComponentStates(context, child);
 			}
 		}
-
-		if (parentUIData == null)
-		{
-			throw new IllegalStateException(
-				"Couldn't find a parent UIData for " + component.getClientId(context));
-		}
-
-		//TODO: Hack?  This assumes that the component's internal clientId cache will be flushed.
-		component.setId(component.getId());
-		String clientId = component.getClientId(context);
-
-		parentUIData._rowIndex = oldRowIndex;
-
-		component.setId(component.getId());
-
-		return clientId;
 	}
 
-	private void restoreDescendantComponentStates(
-		FacesContext context,
-		UIComponent component,
-		boolean saveState)
+	private void restoreDescendantComponentStates(FacesContext context, UIComponent component)
 	{
 		for (Iterator i = component.getFacetsAndChildren(); i.hasNext();)
 		{
 			UIComponent child = (UIComponent) i.next();
-			//clear this descendant's clientId:
+			//reset clientId to null
 			child.setId(child.getId());
-			//HACK: This assumes that setId always clears the cached clientId. Can we be sure?
-
-			if (saveState)
+			if (child.isRendered())
 			{
-				//see saveDescendantComponentStates(UIComponent)
-				if (child instanceof UIData)
+				String clientId = child.getClientId(context);
+				ChildStateHolder childStateHolder = (ChildStateHolder) _rowState.get(clientId);
+				if (childStateHolder != null)
 				{
-					UIData childUIData = (UIData) child;
-					Object state =
-						_rowState._clientIdsToChildUIDataStates.get(
-							childUIData.getClientId(context));
-					if (state == null)
-					{
-						UIDataRowState initialState =
-							(UIDataRowState) _rowState._clientIdsToChildUIDataStates.get(getInitialClientId(context, child));
-
-						if (initialState == null)
-						{
-							throw new IllegalStateException(
-								"No initial state defined for clientId: " + child.getClientId(context));
-						}
-
-						state = new UIDataRowState(initialState);
-					}
-
-
-
-					childUIData._rowState = (UIDataRowState) state;
-
-					restoreDescendantComponentStates(context, component, false);
-					continue;
-				}
-
-				if (!_firstTimeRendered && child instanceof EditableValueHolder)
-				{
-					EditableValueHolder childEVH = (EditableValueHolder) child;
-					Object state =
-						_rowState._clientIdsToChildEVHStates.get(child.getClientId(context));
-					if (state == null)
-					{
-						state =
-							_rowState._clientIdsToChildEVHStates.get(
-								getInitialClientId(context, child));
-					}
-					((EditableValueHolderState) state).restore(childEVH);
+					childStateHolder.restoreState(context, child);
 				}
+				restoreDescendantComponentStates(context, child);
 			}
-
-			restoreDescendantComponentStates(context, child, saveState);
 		}
 	}
 
-	//    private void restoreDescendantComponentStates()
-	//    {
-	//        if (_descendantEditableValueHolderCount == -1)
-	//        {
-	//            throw new IllegalStateException("saveDescendantComponentStates not called yet?");
-	//        }
-	//        else if (_descendantEditableValueHolderCount > 0)
-	//        {
-	//            // There is at least one descendant component to be restored
-	//
-	//            // Get zero-based index (instead of -1 based UIData zeroBasedRowIdx):
-	//            int zeroBasedRowIdx = getDescendantStatesRowIndex();
-	//
-	//            // Is there a reason to restore the state of a new descendant?
-	//            // BUG: 925693
-	//            // manolito: Yes, descendants for a row not yet saved, must be
-	//            //           reset to initial row state!
-	//            int stateRowsCount = _descendantStates.length;
-	//
-	//            EditableValueHolderState[] initialStates = null;
-	//            if (stateRowsCount > 0)
-	//            {
-	//                // No state saved yet for this row, let's restore initial values:
-	//                initialStates = (EditableValueHolderState[]) _descendantStates[0];
-	//            }
-	//
-	//            if (zeroBasedRowIdx < stateRowsCount)
-	//            {
-	//                // There is a saved state for this row, so restore these values:
-	//                EditableValueHolderState[] rowState =
-	//                    (EditableValueHolderState[]) _descendantStates[zeroBasedRowIdx];
-	//                restoreDescendantComponentStates(this, rowState, initialStates, 0, 0);
-	//            }
-	//            else
-	//            {
-	//                // No state saved yet for this row, let's restore initial values:
-	//                restoreDescendantComponentStates(this, initialStates, initialStates, 0, 0);
-	//            }
-	//        }
-	//        else
-	//        {
-	//            // There are no states to restore, so only recurse to set the
-	//            // right clientIds for all descendants
-	//            restoreDescendantComponentStates(this, null, null, 0, 0);
-	//        }
-	//    }
-
-	//    private static int restoreDescendantComponentStates(UIComponent component,
-	//                                                        EditableValueHolderState[] states,
-	//                                                        EditableValueHolderState[] initialStates,
-	//                                                        int counter, int level)
-	//    {
-	//
-	//        for (Iterator it = getChildrenAndOptionalFacetsIterator(level, component); it.hasNext();)
-	//        {
-	//            UIComponent child = (UIComponent)it.next();
-	//            //clear this descendant's clientId:
-	//            child.setId(child.getId()); //HACK: This assumes that setId always clears the cached clientId. Can we be sure?
-	//            if (child instanceof EditableValueHolder)
-	//            {
-	//                if (states != null)
-	//                {
-	//                    states[counter].restore((EditableValueHolder)child);
-	//                }
-	//                else if (initialStates != null)
-	//                {
-	//                    initialStates[counter].restore((EditableValueHolder)child);
-	//                }
-	//                else
-	//                {
-	//                    // No state saved yet and no initial state !?
-	//                    // Should never be possible, but let's reset the component
-	//                    // state to null values
-	//                    ((EditableValueHolder)child).setValue(null);
-	//                    ((EditableValueHolder)child).setLocalValueSet(false);
-	//                    ((EditableValueHolder)child).setValid(true);
-	//                    ((EditableValueHolder)child).setSubmittedValue(null);
-	//                }
-	//                counter++;
-	//            }
-	//            counter = restoreDescendantComponentStates(child, states, initialStates, counter, level+1);
-	//        }
-	//        return counter;
-	//    }
-
 	public void setRows(int rows)
 	{
 		_rows = new Integer(rows);
@@ -559,19 +264,13 @@
 
 	public void encodeBegin(FacesContext context) throws IOException
 	{
-		if (_firstTimeRendered || isAllChildrenAndFacetsValid())
+		if (_isValidChilds)
 		{
-			_saveDescendantStates = false; // no need to save children states
 			//Refresh DataModel for rendering:
 			_dataModel = null;
 			if (_dataModelMap != null)
 				_dataModelMap.clear();
 		}
-		else
-		{
-			_saveDescendantStates = true;
-			// save children states (valid flag, submittedValues, etc.)
-		}
 		super.encodeBegin(context);
 	}
 
@@ -582,58 +281,6 @@
 		super.encodeEnd(context);
 	}
 
-    private boolean isAllChildrenAndFacetsValid()
-    {
-        int first = getFirst();
-        int rows = getRows();
-        int last;
-        if (rows == 0)
-        {
-            last = getRowCount();
-        }
-        else
-        {
-            last = first + rows;
-        }
-        int setRowIndex = getRowIndex();
-        try
-        {
-            for (int rowIndex = first; rowIndex < last; rowIndex++)
-            {
-                setRowIndex(rowIndex);
-                if (isRowAvailable())
-                {
-                    if (!isAllEditableValueHoldersValidRecursive(getFacetsAndChildren()))
-                    {
-                        return false;
-                    }
-                }
-            }
-        }
-        finally
-        {
-            setRowIndex(setRowIndex);
-        }
-        return true;
-    }
-
-	private boolean isAllEditableValueHoldersValidRecursive(Iterator facetsAndChildrenIterator)
-	{
-		while (facetsAndChildrenIterator.hasNext())
-		{
-			UIComponent c = (UIComponent) facetsAndChildrenIterator.next();
-			if (c instanceof EditableValueHolder && !((EditableValueHolder) c).isValid())
-			{
-				return false;
-			}
-			if (!isAllEditableValueHoldersValidRecursive(c.getFacetsAndChildren()))
-			{
-				return false;
-			}
-		}
-		return true;
-	}
-
 	public void processDecodes(FacesContext context)
 	{
 		if (context == null)
@@ -667,6 +314,12 @@
 		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)
@@ -680,6 +333,11 @@
 		processColumnFacets(context, PROCESS_UPDATES);
 		processColumnChildren(context, PROCESS_UPDATES);
 		setRowIndex(-1);
+
+		if (context.getRenderResponse())
+		{
+			_isValidChilds = false;
+		}
 	}
 
 	private void processFacets(FacesContext context, int processAction)
@@ -703,9 +361,7 @@
 					//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);
@@ -742,9 +398,8 @@
 							//Column is not visible
 							continue;
 						}
-						for (Iterator columnChildIter = child.getChildren().iterator();
-							columnChildIter.hasNext();
-							)
+						for (Iterator columnChildIter = child.getChildren().iterator(); columnChildIter
+										.hasNext();)
 						{
 							UIComponent columnChild = (UIComponent) columnChildIter.next();
 							process(context, columnChild, processAction);
@@ -759,13 +414,13 @@
 	{
 		switch (processAction)
 		{
-			case PROCESS_DECODES :
+			case PROCESS_DECODES:
 				component.processDecodes(context);
 				break;
-			case PROCESS_VALIDATORS :
+			case PROCESS_VALIDATORS:
 				component.processValidators(context);
 				break;
-			case PROCESS_UPDATES :
+			case PROCESS_UPDATES:
 				component.processUpdates(context);
 				break;
 		}
@@ -785,8 +440,7 @@
 			{
 				_dataModelMap = new HashMap();
 			}
-			String embeddingClientId =
-				embeddingUIData.getClientId(FacesContext.getCurrentInstance());
+			String embeddingClientId = embeddingUIData.getClientId(FacesContext.getCurrentInstance());
 			DataModel dataModel = (DataModel) _dataModelMap.get(embeddingClientId);
 			if (dataModel == null)
 			{
@@ -988,69 +642,24 @@
 		{
 			if (obj == null)
 				return; //Clearing is allowed
-			throw new UnsupportedOperationException(
-				this.getClass().getName() + " UnsupportedOperationException");
+			throw new UnsupportedOperationException(this.getClass().getName()
+							+ " UnsupportedOperationException");
 		}
 	};
 
-	private static class UIDataRowState implements Cloneable, Serializable
-	{
-		private HashMap _clientIdsToChildUIDataStates = new HashMap();
-		private HashMap _clientIdsToChildEVHStates = new HashMap();
-
-		public UIDataRowState()
-		{
-		}
-
-		public UIDataRowState(UIDataRowState initial)
-		{
-			for (Iterator i = initial._clientIdsToChildEVHStates.entrySet().iterator(); i.hasNext();)
-			{
-				Map.Entry entry = (Map.Entry) i.next();
-				EditableValueHolderState initialState = (EditableValueHolderState) entry.getValue();
-				_clientIdsToChildEVHStates.put(entry.getKey(), new EditableValueHolderState(initialState));
-			}
-
-			for (Iterator i = initial._clientIdsToChildUIDataStates.entrySet().iterator(); i.hasNext();)
-			{
-				Map.Entry entry = (Map.Entry) i.next();
-				UIDataRowState initialState = (UIDataRowState) entry.getValue();
-				_clientIdsToChildEVHStates.put(entry.getKey(), new UIDataRowState(initialState));
-			}
-		}
-	}
-
-	private static class EditableValueHolderState implements Serializable
+	private static class ChildStateHolder implements Serializable
 	{
-		private Object _localValue;
-		private boolean _localValueSet;
-		private boolean _valid;
-		private Object _submittedValue;
+		private final Object _state;
 
-		public EditableValueHolderState(EditableValueHolder vh)
+		public ChildStateHolder(FacesContext context, StateHolder stateHolder)
 		{
-			_localValue = vh.getLocalValue();
-			_localValueSet = vh.isLocalValueSet();
-			_valid = vh.isValid();
-			_submittedValue = vh.getSubmittedValue();
+			_state = stateHolder.saveState(context);
 		}
 
-		public EditableValueHolderState(EditableValueHolderState state)
+		public void restoreState(FacesContext context, StateHolder stateHolder)
 		{
-			_localValue = state._localValue;
-			_localValueSet = state._localValueSet;
-			_valid = state._valid;
-			_submittedValue = state._submittedValue;
+			stateHolder.restoreState(context, _state);
 		}
-
-		public void restore(EditableValueHolder vh)
-		{
-			vh.setValue(_localValue);
-			vh.setLocalValueSet(_localValueSet);
-			vh.setValid(_valid);
-			vh.setSubmittedValue(_submittedValue);
-		}
-
 	}
 
 	public void setValue(Object value)
@@ -1067,7 +676,10 @@
 		values[ROWS_INDEX] = _rows;
 		values[VALUE_INDEX] = _value;
 		values[VAR_INDEX] = _var;
-		values[ROW_STATE_INDEX] = _rowState;
+		if (!_isValidChilds)
+		{
+			values[ROW_STATE_INDEX] = _rowState;
+		}
 		return ((Object) (values));
 	}
 
@@ -1079,10 +691,11 @@
 		_rows = (Integer) values[ROWS_INDEX];
 		_value = (Object) values[VALUE_INDEX];
 		_var = (String) values[VAR_INDEX];
-		_rowState = (UIDataRowState) values[ROW_STATE_INDEX];
-
-		// restore state means component was already rendered at least once:
-		_firstTimeRendered = false;
+		Map rowState = (Map) values[ROW_STATE_INDEX];
+		if (rowState != null)
+		{
+			_rowState = rowState;
+		}
 	}
 
 	//------------------ GENERATED CODE BEGIN (do not modify!) --------------------