Author: nbelaevski
Date: 2010-03-29 09:56:12 -0400 (Mon, 29 Mar 2010)
New Revision: 16681
Added:
root/framework/trunk/impl/src/main/java/org/richfaces/component/DataAdaptorStateHelper.java
Modified:
root/framework/trunk/api/src/main/java/org/ajax4jsf/component/IterationStateHolder.java
root/framework/trunk/impl/src/main/java/org/richfaces/component/SavedState.java
root/framework/trunk/impl/src/main/java/org/richfaces/component/UIDataAdaptor.java
root/framework/trunk/impl/src/test/java/org/richfaces/component/DataAdaptorTestCase.java
Log:
Fixed state saving for nested UIDataAdaptor components
Several updates for UIDataAdaptor
Modified:
root/framework/trunk/api/src/main/java/org/ajax4jsf/component/IterationStateHolder.java
===================================================================
---
root/framework/trunk/api/src/main/java/org/ajax4jsf/component/IterationStateHolder.java 2010-03-29
09:25:57 UTC (rev 16680)
+++
root/framework/trunk/api/src/main/java/org/ajax4jsf/component/IterationStateHolder.java 2010-03-29
13:56:12 UTC (rev 16681)
@@ -23,6 +23,8 @@
package org.ajax4jsf.component;
+import javax.faces.context.FacesContext;
+
/**
* In the original {@link javax.faces.component.UIData} component, only state for a
* {@link javax.faces.component.EditableValueHolder} component saved for an iteration.
@@ -35,15 +37,18 @@
/**
* Get component state for a current iteration.
+ * @param context current {@link FacesContext}
* @return request-scope component state. Details are subject for a component
implementation
*/
- public Object getIterationState();
+ public Object getIterationState(FacesContext context);
/**
* Set component state for the next iteration. State can be either previously saved
iteration state
* or <code>null</code> value. In the second case component should reset
its state to the initial.
+ *
+ * @param context current {@link FacesContext}
* @param state request-scope component state or <code>null</code>.
Details are subject for a component
* implementation
*/
- public void setIterationState(Object state);
+ public void setIterationState(FacesContext context, Object state);
}
Added:
root/framework/trunk/impl/src/main/java/org/richfaces/component/DataAdaptorStateHelper.java
===================================================================
---
root/framework/trunk/impl/src/main/java/org/richfaces/component/DataAdaptorStateHelper.java
(rev 0)
+++
root/framework/trunk/impl/src/main/java/org/richfaces/component/DataAdaptorStateHelper.java 2010-03-29
13:56:12 UTC (rev 16681)
@@ -0,0 +1,137 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.component;
+
+import java.io.Serializable;
+
+import javax.faces.component.StateHolder;
+import javax.faces.component.UIComponentBase;
+import javax.faces.context.FacesContext;
+
+import org.ajax4jsf.model.DataComponentState;
+import org.ajax4jsf.model.ExtendedDataModel;
+import org.ajax4jsf.model.SerializableDataModel;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public final class DataAdaptorStateHelper implements StateHolder {
+
+ private boolean tranzient = false;
+
+ private boolean componentStateIsStateHolder = false;
+
+ private Object savedComponentState;
+
+ private DataComponentState dataComponentState;
+
+ private ExtendedDataModel<?> extendedDataModel;
+
+ public DataAdaptorStateHelper() {
+ }
+
+ DataAdaptorStateHelper(DataComponentState dataComponentState,
ExtendedDataModel<?> extendedDataModel) {
+ super();
+ this.dataComponentState = dataComponentState;
+ this.extendedDataModel = extendedDataModel;
+ }
+
+ public DataComponentState getDataComponentState() {
+ return dataComponentState;
+ }
+
+ public ExtendedDataModel<?> getExtendedDataModel() {
+ return extendedDataModel;
+ }
+
+ public boolean isTransient() {
+ return tranzient;
+ }
+
+ public void setTransient(boolean newTransientValue) {
+ tranzient = newTransientValue;
+ }
+
+ public Object saveState(FacesContext context) {
+ //TODO - save only encoded states (see UIDataAdaptor#getEncodedIds())?
+
+ if (dataComponentState != null) {
+ if (dataComponentState instanceof StateHolder) {
+ componentStateIsStateHolder = true;
+
+ StateHolder stateHolder = (StateHolder) dataComponentState;
+ if (!stateHolder.isTransient()) {
+ savedComponentState = stateHolder.saveState(context);
+ }
+ } else {
+ componentStateIsStateHolder = false;
+
+ if (dataComponentState instanceof Serializable) {
+ savedComponentState = dataComponentState;
+ }
+ }
+ }
+
+ Object savedSerializableModel = null;
+
+ if (dataComponentState != null && extendedDataModel != null) {
+ // TODO handle model serialization - "execute" model
+ savedSerializableModel =
extendedDataModel.getSerializableModel(dataComponentState.getRange());
+ }
+
+ if (savedComponentState != null || savedSerializableModel != null) {
+ return new Object[] {
+ componentStateIsStateHolder ? Boolean.TRUE : Boolean.FALSE,
+ savedComponentState,
+ savedSerializableModel
+ };
+ } else {
+ return null;
+ }
+ }
+
+ public void restoreState(FacesContext context, Object stateObject) {
+ if (stateObject != null) {
+ Object[] state = (Object[]) stateObject;
+
+ componentStateIsStateHolder = Boolean.TRUE.equals(state[0]);
+
+ if (componentStateIsStateHolder) {
+ savedComponentState = state[1];
+ } else {
+ dataComponentState = (DataComponentState)
UIComponentBase.restoreAttachedState(context,
+ savedComponentState);
+ }
+
+ extendedDataModel = (SerializableDataModel)
UIComponentBase.restoreAttachedState(context, state[2]);
+ }
+ }
+
+ void restoreComponentState(FacesContext context, UIDataAdaptor dataAdaptor) {
+ if (savedComponentState != null && componentStateIsStateHolder) {
+ dataComponentState = dataAdaptor.createComponentState();
+ ((StateHolder) dataComponentState).restoreState(context,
savedComponentState);
+ savedComponentState = null;
+ }
+ }
+}
Modified: root/framework/trunk/impl/src/main/java/org/richfaces/component/SavedState.java
===================================================================
---
root/framework/trunk/impl/src/main/java/org/richfaces/component/SavedState.java 2010-03-29
09:25:57 UTC (rev 16680)
+++
root/framework/trunk/impl/src/main/java/org/richfaces/component/SavedState.java 2010-03-29
13:56:12 UTC (rev 16681)
@@ -22,12 +22,14 @@
package org.richfaces.component;
-import org.ajax4jsf.component.IterationStateHolder;
-
import javax.faces.component.EditableValueHolder;
+import javax.faces.component.StateHolder;
+import javax.faces.component.UIComponentBase;
import javax.faces.component.UIForm;
-import java.io.Serializable;
+import javax.faces.context.FacesContext;
+import org.ajax4jsf.component.IterationStateHolder;
+
//from RI
/**
@@ -36,9 +38,11 @@
*
* @author shura
*/
-final class SavedState implements Serializable {
+public final class SavedState implements StateHolder {
+
public static final SavedState EMPTY = new SavedState();
- private static final long serialVersionUID = 2920252657338389849L;
+
+ private boolean tranzient = false;
private boolean valid = true;
private Object iterationState;
private boolean localValueSet;
@@ -58,9 +62,9 @@
this.localValueSet = evh.isLocalValueSet();
}
- public SavedState(IterationStateHolder ish) {
+ public SavedState(FacesContext context, IterationStateHolder ish) {
super();
- this.iterationState = ish.getIterationState();
+ this.iterationState = ish.getIterationState(context);
}
public SavedState(UIForm form) {
@@ -125,11 +129,40 @@
evh.setLocalValueSet(this.localValueSet);
}
- public void apply(IterationStateHolder ish) {
- ish.setIterationState(this.iterationState);
+ public void apply(FacesContext context, IterationStateHolder ish) {
+ ish.setIterationState(context, this.iterationState);
}
public void apply(UIForm form) {
form.setSubmitted(this.submitted);
}
+
+ public boolean isTransient() {
+ return tranzient;
+ }
+
+ public void restoreState(FacesContext context, Object stateObject) {
+ Object[] state = (Object[]) stateObject;
+ iterationState = UIComponentBase.restoreAttachedState(context, state[0]);
+ localValueSet = Boolean.TRUE.equals(state[1]);
+ submitted = Boolean.TRUE.equals(state[2]);
+ submittedValue = state[3];
+ value = state[4];
+ valid = Boolean.TRUE.equals(state[5]);
+ }
+
+ public Object saveState(FacesContext context) {
+ return new Object[] {
+ UIComponentBase.saveAttachedState(context, iterationState),
+ localValueSet ? Boolean.TRUE : Boolean.FALSE,
+ submitted ? Boolean.TRUE : Boolean.FALSE,
+ submittedValue,
+ value,
+ valid ? Boolean.TRUE : Boolean.FALSE
+ };
+ }
+
+ public void setTransient(boolean newTransientValue) {
+ tranzient = newTransientValue;
+ }
}
Modified:
root/framework/trunk/impl/src/main/java/org/richfaces/component/UIDataAdaptor.java
===================================================================
---
root/framework/trunk/impl/src/main/java/org/richfaces/component/UIDataAdaptor.java 2010-03-29
09:25:57 UTC (rev 16680)
+++
root/framework/trunk/impl/src/main/java/org/richfaces/component/UIDataAdaptor.java 2010-03-29
13:56:12 UTC (rev 16681)
@@ -23,23 +23,20 @@
package org.richfaces.component;
import java.io.IOException;
-import java.io.Serializable;
import java.text.MessageFormat;
import java.util.Collection;
import java.util.Collections;
-import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.el.ValueExpression;
import javax.faces.FacesException;
+import javax.faces.application.Application;
import javax.faces.application.FacesMessage;
import javax.faces.component.ContextCallback;
import javax.faces.component.EditableValueHolder;
import javax.faces.component.NamingContainer;
-import javax.faces.component.StateHelper;
-import javax.faces.component.StateHolder;
import javax.faces.component.UIComponent;
import javax.faces.component.UIComponentBase;
import javax.faces.component.UIForm;
@@ -53,12 +50,12 @@
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;
import javax.faces.event.AbortProcessingException;
-import javax.faces.event.ActionEvent;
-import javax.faces.event.BehaviorEvent;
import javax.faces.event.FacesEvent;
+import javax.faces.event.PhaseId;
+import javax.faces.event.PostValidateEvent;
+import javax.faces.event.PreValidateEvent;
import javax.faces.render.Renderer;
-import org.ajax4jsf.component.AjaxDataEncoder;
import org.ajax4jsf.component.IterationStateHolder;
import org.ajax4jsf.model.DataComponentState;
import org.ajax4jsf.model.DataVisitResult;
@@ -70,17 +67,14 @@
import org.slf4j.Logger;
/**
- * Base class for iterable components, like dataTable, Tomahawk dataList,
- * Facelets repeat, tree etc., with support for partial rendering on AJAX
- * responces for one or more selected iterations.
+ * Base class for iterable components, like dataTable, Tomahawk dataList, Facelets
repeat, tree etc., with support for
+ * partial rendering on AJAX responces for one or more selected iterations.
*
* @author shura
*/
+public abstract class UIDataAdaptor extends UIComponentBase implements NamingContainer,
+ UniqueIdVendor, IterationStateHolder {
-//TODO check AjaxDataEncoder
-public abstract class UIDataAdaptor extends UIComponentBase
- implements AjaxDataEncoder, NamingContainer, UniqueIdVendor, IterationStateHolder {
-
/**
* <p>The standard component family for this component.</p>
*/
@@ -123,7 +117,6 @@
}
};
- private Object ajaxRowKey = null;
private DataComponentState componentState = null;
private ExtendedDataModel<?> extendedDataModel = null;
private Object rowKey = null;
@@ -133,19 +126,19 @@
/**
* @author Nick Belaevski
- *
+ *
*/
private final class DataVisitorForVisitTree implements DataVisitor {
/**
- *
+ *
*/
private final VisitCallback callback;
/**
- *
+ *
*/
private final VisitContext visitContext;
/**
- *
+ *
*/
private boolean visitResult;
@@ -177,14 +170,14 @@
return DataVisitResult.CONTINUE;
}
-
+
public boolean getVisitResult() {
return visitResult;
}
}
private enum PropertyKeys {
- ajaxKeys, lastId, var, rowKeyVar, stateVar, childState, rowKeyConverter
+ lastId, var, rowKeyVar, stateVar, childState, rowKeyConverter
}
public UIDataAdaptor() {
@@ -194,7 +187,7 @@
protected Map<String, Object> getVariablesMap(FacesContext facesContext) {
return facesContext.getExternalContext().getRequestMap();
}
-
+
/*
* (non-Javadoc)
* @see javax.faces.component.UIComponent#getFamily()
@@ -205,33 +198,8 @@
}
/*
- * (non-Javadoc)
- * @see org.ajax4jsf.component.AjaxDataEncoder#getAjaxKeys()
- */
- @SuppressWarnings("unchecked")
- public Set<Object> getAjaxKeys() {
- Set<Object> defaultAjaxKeys = null;
-
- if (ajaxRowKey != null) {
-
- // cannot use Collections.singleton() because ajaxKeys set should be
modifiable
- defaultAjaxKeys = new HashSet<Object>(1);
- defaultAjaxKeys.add(ajaxRowKey);
- }
-
- return (Set<Object>) getStateHelper().eval(PropertyKeys.ajaxKeys,
defaultAjaxKeys);
- }
-
- /*
- * (non-Javadoc)
- * @see org.ajax4jsf.component.AjaxDataEncoder#setAjaxKeys(java.util.Set)
- */
- public void setAjaxKeys(Set<Object> ajaxKeys) {
- getStateHelper().put(PropertyKeys.ajaxKeys, ajaxKeys);
- }
-
- /*
- * (non-Javadoc)
+ * (non-Javadoc)
+ *
* @see
org.ajax4jsf.component.AjaxChildrenEncoder#encodeAjaxChild(javax.faces.context.FacesContext,
* java.lang.String, java.util.Set, java.util.Set)
*/
@@ -314,7 +282,7 @@
if (component instanceof IterationStateHolder) {
IterationStateHolder ish = (IterationStateHolder) component;
- state = new SavedState(ish);
+ state = new SavedState(facesContext, ish);
} else if (component instanceof EditableValueHolder) {
EditableValueHolder evh = (EditableValueHolder) component;
@@ -385,8 +353,9 @@
component.setId(id); // Forces client id to be reset
SavedState savedState = null;
- @SuppressWarnings("unchecked") Map<String, SavedState>
savedStatesMap =
- (Map<String, SavedState>)
getStateHelper().get(PropertyKeys.childState);
+ @SuppressWarnings("unchecked")
+ Map<String, SavedState> savedStatesMap = (Map<String, SavedState>)
getStateHelper()
+ .get(PropertyKeys.childState);
if (savedStatesMap != null) {
savedState = savedStatesMap.get(component.getClientId(facesContext));
@@ -399,7 +368,7 @@
if (component instanceof IterationStateHolder) {
IterationStateHolder ish = (IterationStateHolder) component;
- savedState.apply(ish);
+ savedState.apply(facesContext, ish);
} else if (component instanceof EditableValueHolder) {
EditableValueHolder evh = (EditableValueHolder) component;
@@ -427,28 +396,12 @@
setRowKey(getFacesContext(), rowKey);
}
- protected boolean isAjaxKeyEvent(FacesEvent event) {
- return (event instanceof ActionEvent) || (event instanceof BehaviorEvent);
- }
-
- protected void addAjaxKeyEvent(FacesEvent event) {
- Object eventRowKey = getRowKey();
-
- if (null != eventRowKey) {
- this.ajaxRowKey = eventRowKey;
- }
- }
-
/*
* (non-Javadoc)
* @see
javax.faces.component.UIComponentBase#queueEvent(javax.faces.event.FacesEvent)
*/
@Override
public void queueEvent(FacesEvent event) {
- if (isAjaxKeyEvent(event)) {
- addAjaxKeyEvent(event);
- }
-
super.queueEvent(new RowKeyContextEventWrapper(this, event, getRowKey()));
}
@@ -472,7 +425,7 @@
RowKeyContextEventWrapper revent = (RowKeyContextEventWrapper) event;
Object oldRowKey = getRowKey();
- setRowKey(revent.getRowKey());
+ setRowKey(context, revent.getRowKey());
FacesEvent rowEvent = revent.getFacesEvent();
UIComponent source = rowEvent.getComponent();
@@ -497,7 +450,7 @@
}
}
- setRowKey(oldRowKey);
+ setRowKey(context, oldRowKey);
}
/**
@@ -688,7 +641,7 @@
// Store converter for a invokeOnComponents call.
if (null != rowKeyConverter) {
- //TODO - review
+ // TODO - review
setRowKeyConverter(rowKeyConverter);
}
}
@@ -840,7 +793,7 @@
getExtendedDataModel().walk(faces, visitor, range, argument);
- setRowKey(key);
+ setRowKey(faces, key);
restoreOrigValue(faces);
}
@@ -849,8 +802,11 @@
return;
}
+ pushComponentToEL(faces, this);
+ preDecode(faces);
this.iterate(faces, decodeVisitor);
this.decode(faces);
+ popComponentFromEL(faces);
}
public void processValidators(FacesContext faces) {
@@ -858,7 +814,13 @@
return;
}
+ pushComponentToEL(faces, this);
+ Application app = faces.getApplication();
+ app.publishEvent(faces, PreValidateEvent.class, this);
+ preValidate(faces);
this.iterate(faces, validateVisitor);
+ app.publishEvent(faces, PostValidateEvent.class, this);
+ popComponentFromEL(faces);
}
public void processUpdates(FacesContext faces) {
@@ -866,6 +828,8 @@
return;
}
+ pushComponentToEL(faces, this);
+ preUpdate(faces);
this.iterate(faces, updateVisitor);
ExtendedDataModel<?> dataModel = getExtendedDataModel();
@@ -877,6 +841,8 @@
serializableModel.update();
}
+
+ popComponentFromEL(faces);
}
@Override
@@ -889,54 +855,66 @@
* (non-Javadoc)
* @see org.ajax4jsf.component.IterationStateHolder#getIterationState()
*/
- public Object getIterationState() {
+ public Object getIterationState(FacesContext context) {
assert rowKey == null;
- StateHelper stateHelper = getStateHelper();
-
- return new Object[]{stateHelper.get(PropertyKeys.childState),
this.componentState, this.ajaxRowKey,
- this.extendedDataModel,};
+ return new DataAdaptorStateHelper(this.componentState, this.extendedDataModel);
}
/*
- * (non-Javadoc)
+ * (non-Javadoc)
+ *
* @see
org.ajax4jsf.component.IterationStateHolder#setIterationState(java.lang.Object)
*/
- public void setIterationState(Object stateObject) {
+ public void setIterationState(FacesContext context, Object stateObject) {
assert rowKey == null;
// TODO - ?
// restoreChildState(getFacesContext());
- StateHelper stateHelper = getStateHelper();
-
if (stateObject != null) {
- Object[] state = (Object[]) stateObject;
+ DataAdaptorStateHelper stateHelper = (DataAdaptorStateHelper) stateObject;
+ stateHelper.restoreComponentState(context, this);
- stateHelper.put(PropertyKeys.childState, state[0]);
- this.componentState = (DataComponentState) state[1];
- this.ajaxRowKey = state[2];
- this.extendedDataModel = (ExtendedDataModel<?>) state[3];
+ this.componentState = stateHelper.getDataComponentState();
+ this.extendedDataModel = stateHelper.getExtendedDataModel();
} else {
- stateHelper.remove(PropertyKeys.childState);
this.componentState = null;
- this.ajaxRowKey = null;
this.extendedDataModel = null;
}
}
- protected void resetDataModel(FacesContext context) {
+ protected void resetDataModel() {
this.extendedDataModel = null;
}
- protected void resetChildState(FacesContext context) {
+ protected void resetChildState() {
getStateHelper().remove(PropertyKeys.childState);
}
+ protected void preDecode(FacesContext context) {
+ resetDataModel();
+
+ Object savedChildState = getStateHelper().get(PropertyKeys.childState);
+ // TODO - verify the check for null: savedChildState == null
+ if (savedChildState == null || !keepSaved(context)) {
+ resetChildState();
+ }
+ }
+
+ // TODO - do we need this method?
+ protected void preValidate(FacesContext context) {
+ }
+
+ // TODO - do we need this method?
+ protected void preUpdate(FacesContext context) {
+ }
+
protected void preEncodeBegin(FacesContext context) {
- resetDataModel(context);
+ resetDataModel();
if (!keepSaved(context)) {
- resetChildState(context);
+ //TODO - this also resets state for the nested iteration components - is it
correct?
+ resetChildState();
}
}
@@ -953,32 +931,16 @@
@Override
public Object saveState(FacesContext context) {
- // TODO handle model serialization - "execute" model
- Boolean componentStateIsStateHolder = null;
- Object savedComponentState = null;
-
// TODO - partial state saving handling
- if (componentState instanceof StateHolder) {
- componentStateIsStateHolder = Boolean.TRUE;
-
- StateHolder stateHolder = (StateHolder) componentState;
-
- if (!stateHolder.isTransient()) {
- savedComponentState = stateHolder.saveState(context);
- }
- } else {
- componentStateIsStateHolder = Boolean.FALSE;
-
- if (componentState instanceof Serializable) {
- savedComponentState = componentState;
- }
- }
-
- return new Object[]{super.saveState(context), savedComponentState,
componentStateIsStateHolder};
+ return new Object[] {
+ super.saveState(context),
+ new DataAdaptorStateHelper(componentState,
extendedDataModel).saveState(context)
+ };
}
/*
- * (non-Javadoc)
+ * (non-Javadoc)
+ *
* @see
javax.faces.component.UIComponentBase#restoreState(javax.faces.context.FacesContext,
java.lang.Object)
*/
@Override
@@ -988,19 +950,14 @@
// TODO Auto-generated method stub
super.restoreState(context, state[0]);
- Object savedComponentState = state[1];
+ if (state[1] != null) {
+ DataAdaptorStateHelper dataAdaptorStateHelper = new
DataAdaptorStateHelper();
+ dataAdaptorStateHelper.restoreState(context, state[1]);
+ dataAdaptorStateHelper.restoreComponentState(context, this);
- if (savedComponentState != null) {
- boolean componentStateIsStateHolder = ((Boolean) state[2]).booleanValue();
-
- if (componentStateIsStateHolder) {
- componentState = createComponentState();
- ((StateHolder) componentState).restoreState(context,
savedComponentState);
- } else {
- componentState = (DataComponentState) restoreAttachedState(context,
savedComponentState);
- }
-
// TODO update state model binding
+ componentState = dataAdaptorStateHelper.getDataComponentState();
+ extendedDataModel = dataAdaptorStateHelper.getExtendedDataModel();
}
}
@@ -1112,28 +1069,41 @@
// Tests whether we need to visit our children as part of
// a tree visit
- private boolean doVisitChildren(VisitContext context) {
+ private boolean doVisitChildren(VisitContext context, boolean visitRows) {
// Just need to check whether there are any ids under this
- // subtree. Make sure row index is cleared out since
+ // subtree. Make sure row index is cleared out since
// getSubtreeIdsToVisit() needs our row-less client id.
- setRowKey(null);
+ // TODO check this
+ if (visitRows) {
+ setRowKey(context.getFacesContext(), null);
+ }
+
+ // TODO optimize for returned IDs
Collection<String> idsToVisit = context.getSubtreeIdsToVisit(this);
assert idsToVisit != null;
+ if (idsToVisit == VisitContext.ALL_IDS) {
+ // TODO
+ }
+
// All ids or non-empty collection means we need to visit our children.
return !idsToVisit.isEmpty();
}
- private boolean visitFixedChildren(VisitContext visitContext, VisitCallback callback)
{
- Iterator<UIComponent> fixedChildrenItr = fixedChildren();
+ private boolean visitComponents(Iterator<UIComponent> components, VisitContext
context, VisitCallback callback,
+ boolean resetKeyBeforeVisit) {
- while (fixedChildrenItr.hasNext()) {
- UIComponent fixedChild = fixedChildrenItr.next();
+ if (resetKeyBeforeVisit) {
+ setRowKey(context.getFacesContext(), null);
+ }
- if (fixedChild.visitTree(visitContext, callback)) {
+ while (components.hasNext()) {
+ UIComponent nextChild = components.next();
+
+ if (nextChild.visitTree(context, callback)) {
return true;
}
}
@@ -1141,19 +1111,29 @@
return false;
}
- private boolean visitDataChildren(final VisitContext visitContext, final
VisitCallback callback) {
- FacesContext facesContext = visitContext.getFacesContext();
+ protected boolean visitFixedChildren(VisitContext visitContext, VisitCallback
callback, boolean resetKeyBeforeVisit) {
- DataVisitorForVisitTree dataVisitor = new DataVisitorForVisitTree(callback,
visitContext);
- this.walk(facesContext, dataVisitor, null);
+ return visitComponents(fixedChildren(), visitContext, callback,
resetKeyBeforeVisit);
+ }
- return dataVisitor.getVisitResult();
+ protected boolean visitDataChildren(VisitContext visitContext, VisitCallback
callback, boolean resetKeyBeforeVisit) {
+
+ if (resetKeyBeforeVisit) {
+ FacesContext facesContext = visitContext.getFacesContext();
+
+ DataVisitorForVisitTree dataVisitor = new DataVisitorForVisitTree(callback,
visitContext);
+ this.walk(facesContext, dataVisitor, null);
+
+ return dataVisitor.getVisitResult();
+ } else {
+ return visitComponents(dataChildren(), visitContext, callback, false);
+ }
}
@Override
public boolean visitTree(VisitContext visitContext, VisitCallback callback) {
- // First check to see whether we are visitable. If not
+ // First check to see whether we are visitable. If not
// short-circuit out of this subtree, though allow the
// visit to proceed through to other subtrees.
if (!isVisitable(visitContext)) {
@@ -1164,18 +1144,23 @@
// we start from a clean slate.
FacesContext facesContext = visitContext.getFacesContext();
- captureOrigValue(facesContext);
+ // NOTE: that the visitRows local will be obsolete once the
+ // appropriate visit hints have been added to the API
+ boolean visitRows = requiresRowIteration(facesContext);
- Object oldRowKey = getRowKey();
+ Object oldRowKey = null;
+ if (visitRows) {
+ captureOrigValue(facesContext);
+ oldRowKey = getRowKey();
+ setRowKey(facesContext, null);
+ }
- setRowKey(facesContext, null);
-
// Push ourselves to EL
pushComponentToEL(facesContext, null);
try {
- // Visit ourselves. Note that we delegate to the
+ // Visit ourselves. Note that we delegate to the
// VisitContext to actually perform the visit.
VisitResult result = visitContext.invokeVisitCallback(this, callback);
@@ -1185,12 +1170,14 @@
}
// Visit children, short-circuiting as necessary
- if ((result == VisitResult.ACCEPT) && doVisitChildren(visitContext))
{
- if (visitFixedChildren(visitContext, callback)) {
+ if ((result == VisitResult.ACCEPT) && doVisitChildren(visitContext,
visitRows)) {
+
+ if (visitFixedChildren(visitContext, callback, visitRows)) {
return true;
}
- if (visitDataChildren(visitContext, callback)) {
+ // TODO check doVisitChildren() once again
+ if (visitDataChildren(visitContext, callback, visitRows)) {
return true;
}
}
@@ -1199,13 +1186,15 @@
// Clean up - pop EL and restore old row index
popComponentFromEL(facesContext);
- try {
- setRowKey(oldRowKey);
- restoreOrigValue(facesContext);
- } catch (Exception e) {
+ if (visitRows) {
+ try {
+ setRowKey(facesContext, oldRowKey);
+ restoreOrigValue(facesContext);
+ } catch (Exception e) {
- // TODO: handle exception
- LOG.error(e.getMessage(), e);
+ // TODO: handle exception
+ LOG.error(e.getMessage(), e);
+ }
}
}
@@ -1214,18 +1203,25 @@
}
/**
+ * @param facesContext
+ * @return
+ */
+ private boolean requiresRowIteration(FacesContext context) {
+ return (!PhaseId.RESTORE_VIEW.equals(context.getCurrentPhaseId()));
+ }
+
+ /**
* @param context
* @param substring
* @return
*/
- //TODO review!
+ // TODO review!
protected String extractKeySegment(FacesContext context, String substring) {
return null;
}
/**
- * Base class for visit data model at phases decode, validation and update
- * model
+ * Base class for visit data model at phases decode, validation and update model
*
* @author shura
*/
Modified:
root/framework/trunk/impl/src/test/java/org/richfaces/component/DataAdaptorTestCase.java
===================================================================
---
root/framework/trunk/impl/src/test/java/org/richfaces/component/DataAdaptorTestCase.java 2010-03-29
09:25:57 UTC (rev 16680)
+++
root/framework/trunk/impl/src/test/java/org/richfaces/component/DataAdaptorTestCase.java 2010-03-29
13:56:12 UTC (rev 16681)
@@ -54,7 +54,7 @@
/**
* @author Nick Belaevski
- *
+ *
*/
public class DataAdaptorTestCase extends AbstractFacesTest {
@@ -220,59 +220,59 @@
form.getChildren().add(input);
form.getFacets().put("facet", stateHolder);
- mockDataAdaptor.setRowKey(Integer.valueOf(0));
+ mockDataAdaptor.setRowKey(facesContext, Integer.valueOf(0));
assertFalse(form.isSubmitted());
assertNull(input.getSubmittedValue());
assertNull(input.getLocalValue());
assertTrue(input.isValid());
assertFalse(input.isLocalValueSet());
- assertNull(stateHolder.getIterationState());
+ assertNull(stateHolder.getIterationState(facesContext));
form.setSubmitted(true);
input.setSubmittedValue("user input");
input.setValue("component value");
input.setValid(false);
input.setLocalValueSet(true);
- stateHolder.setIterationState("state");
+ stateHolder.setIterationState(facesContext, "state");
- mockDataAdaptor.setRowKey(Integer.valueOf(1));
+ mockDataAdaptor.setRowKey(facesContext, Integer.valueOf(1));
assertFalse(form.isSubmitted());
assertNull(input.getSubmittedValue());
assertNull(input.getLocalValue());
assertTrue(input.isValid());
assertFalse(input.isLocalValueSet());
- assertNull(stateHolder.getIterationState());
+ assertNull(stateHolder.getIterationState(facesContext));
input.setSubmittedValue("another input from user");
input.setValue("123");
assertTrue(input.isLocalValueSet());
- stateHolder.setIterationState("456");
+ stateHolder.setIterationState(facesContext, "456");
- mockDataAdaptor.setRowKey(Integer.valueOf(0));
+ mockDataAdaptor.setRowKey(facesContext, Integer.valueOf(0));
assertTrue(form.isSubmitted());
assertEquals("user input", input.getSubmittedValue());
assertEquals("component value", input.getLocalValue());
assertFalse(input.isValid());
assertTrue(input.isLocalValueSet());
- assertEquals("state", stateHolder.getIterationState());
+ assertEquals("state", stateHolder.getIterationState(facesContext));
- mockDataAdaptor.setRowKey(Integer.valueOf(1));
+ mockDataAdaptor.setRowKey(facesContext, Integer.valueOf(1));
assertFalse(form.isSubmitted());
assertEquals("another input from user", input.getSubmittedValue());
assertEquals("123", input.getLocalValue());
assertTrue(input.isValid());
assertTrue(input.isLocalValueSet());
- assertEquals("456", stateHolder.getIterationState());
+ assertEquals("456", stateHolder.getIterationState(facesContext));
- mockDataAdaptor.setRowKey(null);
+ mockDataAdaptor.setRowKey(facesContext, null);
assertFalse(form.isSubmitted());
assertNull(input.getSubmittedValue());
assertNull(input.getLocalValue());
assertTrue(input.isValid());
assertFalse(input.isLocalValueSet());
- assertNull(stateHolder.getIterationState());
+ assertNull(stateHolder.getIterationState(facesContext));
}
public void testSaveRestoreChildrenStateNestedDataAdaptors() throws Exception {
@@ -287,8 +287,8 @@
Integer rowKey = Integer.valueOf(2);
Integer childKey = Integer.valueOf(1);
- mockDataAdaptor.setRowKey(rowKey);
- childAdaptor.setRowKey(childKey);
+ mockDataAdaptor.setRowKey(facesContext, rowKey);
+ childAdaptor.setRowKey(facesContext, childKey);
assertNull(input.getSubmittedValue());
assertNull(input.getLocalValue());
@@ -298,17 +298,17 @@
input.setSubmittedValue("submittedValue");
input.setValue("value");
- childAdaptor.setRowKey(null);
- mockDataAdaptor.setRowKey(Integer.valueOf(3));
- childAdaptor.setRowKey(Integer.valueOf(0));
+ childAdaptor.setRowKey(facesContext, null);
+ mockDataAdaptor.setRowKey(facesContext, Integer.valueOf(3));
+ childAdaptor.setRowKey(facesContext, Integer.valueOf(0));
assertNull(input.getSubmittedValue());
assertNull(input.getLocalValue());
assertFalse(input.isLocalValueSet());
- childAdaptor.setRowKey(null);
- mockDataAdaptor.setRowKey(rowKey);
- childAdaptor.setRowKey(childKey);
+ childAdaptor.setRowKey(facesContext, null);
+ mockDataAdaptor.setRowKey(facesContext, rowKey);
+ childAdaptor.setRowKey(facesContext, childKey);
assertEquals("submittedValue", input.getSubmittedValue());
assertEquals("value", input.getLocalValue());
@@ -329,11 +329,11 @@
});
mockDataAdaptor.getChildren().add(input);
- mockDataAdaptor.setRowKey(Integer.valueOf(1));
+ mockDataAdaptor.setRowKey(facesContext, Integer.valueOf(1));
assertEquals(data.get(1), getVarValue());
new ValueChangeEvent(input, null, "testValue").queue();
- mockDataAdaptor.setRowKey(null);
+ mockDataAdaptor.setRowKey(facesContext, null);
facesContext.getViewRoot().broadcastEvents(facesContext,
PhaseId.PROCESS_VALIDATIONS);
assertEquals(1, testCallback.get());
@@ -492,11 +492,11 @@
return "test.Component";
}
- public Object getIterationState() {
+ public Object getIterationState(FacesContext context) {
return iterationState;
}
- public void setIterationState(Object state) {
+ public void setIterationState(FacesContext context, Object state) {
iterationState = state;
}