Author: nbelaevski
Date: 2011-02-16 18:04:13 -0500 (Wed, 16 Feb 2011)
New Revision: 21715
Added:
trunk/ui/common/ui/src/main/java/org/richfaces/component/DataAdaptorIterationState.java
trunk/ui/common/ui/src/test/java/org/richfaces/component/SavedStateTest.java
Modified:
trunk/ui/common/ui/src/main/java/org/richfaces/component/SavedState.java
trunk/ui/common/ui/src/main/java/org/richfaces/component/UIDataAdaptor.java
Log:
https://issues.jboss.org/browse/RF-10497
Added:
trunk/ui/common/ui/src/main/java/org/richfaces/component/DataAdaptorIterationState.java
===================================================================
---
trunk/ui/common/ui/src/main/java/org/richfaces/component/DataAdaptorIterationState.java
(rev 0)
+++
trunk/ui/common/ui/src/main/java/org/richfaces/component/DataAdaptorIterationState.java 2011-02-16
23:04:13 UTC (rev 21715)
@@ -0,0 +1,124 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2011, 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.context.FacesContext;
+
+import org.ajax4jsf.model.DataComponentState;
+import org.ajax4jsf.model.ExtendedDataModel;
+
+public final class DataAdaptorIterationState implements StateHolder {
+
+ private DataComponentState componentState;
+
+ private Object savedComponentState;
+
+ private boolean componentStateIsStateHolder;
+
+ private ExtendedDataModel<?> dataModel;
+
+ public DataAdaptorIterationState() {
+ super();
+ }
+
+ public DataAdaptorIterationState(DataComponentState componentState,
ExtendedDataModel<?> dataModel) {
+ super();
+ this.componentState = componentState;
+ this.dataModel = dataModel;
+ }
+
+ public ExtendedDataModel<?> getDataModel() {
+ return dataModel;
+ }
+
+ public DataComponentState getComponentState() {
+ return componentState;
+ }
+
+ /**
+ * @param uiDataAdaptor
+ */
+ public void restoreComponentState(UIDataAdaptor uiDataAdaptor) {
+ if (savedComponentState != null && componentStateIsStateHolder) {
+ componentState = uiDataAdaptor.createComponentState();
+ ((StateHolder)
componentState).restoreState(FacesContext.getCurrentInstance(), savedComponentState);
+ savedComponentState = null;
+ }
+ }
+
+ public void setTransient(boolean newTransientValue) {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean isTransient() {
+ if (componentState instanceof StateHolder) {
+ return ((StateHolder) componentState).isTransient();
+ }
+
+ if (componentState instanceof Serializable) {
+ return false;
+ }
+
+ return true;
+ }
+
+ public Object saveState(FacesContext context) {
+ if (isTransient()) {
+ return null;
+ }
+
+ boolean localComponentStateIsHolder = false;
+ Object localSavedComponentState = null;
+
+ if (componentState instanceof StateHolder) {
+ localComponentStateIsHolder = true;
+
+ StateHolder stateHolder = (StateHolder) componentState;
+ localSavedComponentState = stateHolder.saveState(context);
+ } else if (componentState instanceof Serializable) {
+ localSavedComponentState = componentState;
+ }
+
+ return new Object[] {
+ localComponentStateIsHolder ? Boolean.TRUE : Boolean.FALSE,
+ localSavedComponentState
+ };
+ }
+
+ public void restoreState(FacesContext context, Object stateObject) {
+ if (stateObject != null) {
+ Object[] state = (Object[]) stateObject;
+ componentStateIsStateHolder = Boolean.TRUE.equals(state[0]);
+ Object localSavedComponentState = state[1];
+
+ if (componentStateIsStateHolder) {
+ savedComponentState = localSavedComponentState;
+ } else {
+ componentState = (DataComponentState) localSavedComponentState;
+ }
+ }
+ }
+
+}
\ No newline at end of file
Modified: trunk/ui/common/ui/src/main/java/org/richfaces/component/SavedState.java
===================================================================
--- trunk/ui/common/ui/src/main/java/org/richfaces/component/SavedState.java 2011-02-16
21:38:58 UTC (rev 21714)
+++ trunk/ui/common/ui/src/main/java/org/richfaces/component/SavedState.java 2011-02-16
23:04:13 UTC (rev 21715)
@@ -22,10 +22,11 @@
package org.richfaces.component;
-import java.io.Serializable;
-
import javax.faces.component.EditableValueHolder;
+import javax.faces.component.StateHolder;
+import javax.faces.component.UIComponentBase;
import javax.faces.component.UIForm;
+import javax.faces.context.FacesContext;
import org.ajax4jsf.component.IterationStateHolder;
@@ -37,7 +38,7 @@
*
* @author shura
*/
-final class SavedState implements Serializable {
+public final class SavedState implements StateHolder {
public static final SavedState EMPTY = new SavedState();
@@ -114,6 +115,14 @@
this.iterationState = iterationState;
}
+ boolean isSubmitted() {
+ return submitted;
+ }
+
+ void setSubmitted(boolean submitted) {
+ this.submitted = submitted;
+ }
+
@Override
public String toString() {
if (iterationState != null) {
@@ -138,4 +147,75 @@
public void apply(UIForm form) {
form.setSubmitted(this.submitted);
}
+
+ private boolean isObjectTransient(Object o) {
+ if (o == null) {
+ return true;
+ }
+
+ if (o instanceof StateHolder) {
+ return ((StateHolder) o).isTransient();
+ }
+
+ return false;
+ }
+
+ public void setTransient(boolean newTransientValue) {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean isTransient() {
+ if (iterationState != null) {
+ return isObjectTransient(iterationState);
+ }
+
+ if (!valid) {
+ return false;
+ }
+
+ if (localValueSet || submitted) {
+ return false;
+ }
+
+ return isObjectTransient(submittedValue) && isObjectTransient(value);
+ }
+
+ public Object saveState(FacesContext context) {
+ if (isTransient()) {
+ return null;
+ }
+
+ if (iterationState != null) {
+ return new Object[] {
+ UIComponentBase.saveAttachedState(context, iterationState)
+ };
+ } else {
+ return new Object[] {
+ valid ? Boolean.TRUE : Boolean.FALSE,
+ localValueSet ? Boolean.TRUE : Boolean.FALSE,
+ submitted ? Boolean.TRUE : Boolean.FALSE,
+ UIComponentBase.saveAttachedState(context, submittedValue),
+ UIComponentBase.saveAttachedState(context, value)
+ };
+ }
+ }
+
+ public void restoreState(FacesContext context, Object stateObject) {
+ if (stateObject == null) {
+ return;
+ }
+
+ Object[] state = (Object[]) stateObject;
+
+ if (state.length == 1) {
+ iterationState = UIComponentBase.restoreAttachedState(context, state[0]);
+ } else {
+ valid = Boolean.TRUE.equals(state[0]);
+ localValueSet = Boolean.TRUE.equals(state[1]);
+ submitted = Boolean.TRUE.equals(state[2]);
+ submittedValue = UIComponentBase.restoreAttachedState(context, state[3]);
+ value = UIComponentBase.restoreAttachedState(context, state[4]);
+ }
+ }
+
}
Modified: trunk/ui/common/ui/src/main/java/org/richfaces/component/UIDataAdaptor.java
===================================================================
--- trunk/ui/common/ui/src/main/java/org/richfaces/component/UIDataAdaptor.java 2011-02-16
21:38:58 UTC (rev 21714)
+++ trunk/ui/common/ui/src/main/java/org/richfaces/component/UIDataAdaptor.java 2011-02-16
23:04:13 UTC (rev 21715)
@@ -24,8 +24,6 @@
import static
org.richfaces.component.util.Strings.NamingContainerDataHolder.SEPARATOR_CHAR_JOINER;
-import java.io.IOException;
-import java.io.Serializable;
import java.text.MessageFormat;
import java.util.Collection;
import java.util.Collections;
@@ -95,103 +93,6 @@
*/
public static final String COMPONENT_TYPE = "org.richfaces.Data";
- private static final class IterationState implements Serializable {
-
- private static final long serialVersionUID = -3502645160277416066L;
-
- private DataComponentState componentState;
-
- private Object savedComponentState;
-
- private boolean componentStateIsStateHolder;
-
- private transient ExtendedDataModel<?> dataModel;
-
- public IterationState() {
- super();
- }
-
- public IterationState(DataComponentState componentState,
ExtendedDataModel<?> dataModel) {
- super();
- this.componentState = componentState;
- this.dataModel = dataModel;
- }
-
- public ExtendedDataModel<?> getDataModel() {
- return dataModel;
- }
-
- public DataComponentState getComponentState() {
- return componentState;
- }
-
- /**
- * @param uiDataAdaptor
- */
- public void restoreComponentState(UIDataAdaptor uiDataAdaptor) {
- if (savedComponentState != null && componentStateIsStateHolder) {
- componentState = uiDataAdaptor.createComponentState();
- ((StateHolder)
componentState).restoreState(FacesContext.getCurrentInstance(), savedComponentState);
- savedComponentState = null;
- }
- }
-
- final Object saveState() {
- boolean localComponentStateIsHolder = false;
- Object localSavedComponentState = null;
-
- if (componentState != null) {
- if (componentState instanceof StateHolder) {
- localComponentStateIsHolder = true;
-
- StateHolder stateHolder = (StateHolder) componentState;
- if (!stateHolder.isTransient()) {
- localSavedComponentState =
stateHolder.saveState(FacesContext.getCurrentInstance());
- }
- } else {
- if (componentState instanceof Serializable) {
- localSavedComponentState = componentState;
- }
- }
- }
-
- if (localSavedComponentState != null) {
- return new Object[] {
- localComponentStateIsHolder,
- localSavedComponentState
- };
- } else {
- return null;
- }
- }
-
- final void restoreState(Object stateObject) {
- if (stateObject != null) {
- Object[] state = (Object[]) stateObject;
- componentStateIsStateHolder = Boolean.TRUE.equals(state[0]);
- Object localSavedComponentState = state[1];
-
- if (componentStateIsStateHolder) {
- savedComponentState = localSavedComponentState;
- } else {
- componentState = (DataComponentState) localSavedComponentState;
- }
- }
- }
-
- private void writeObject(java.io.ObjectOutputStream out)
- throws IOException {
-
- out.writeObject(saveState());
- }
-
- private void readObject(java.io.ObjectInputStream in)
- throws IOException, ClassNotFoundException {
-
- restoreState(in.readObject());
- }
- }
-
private static final VisitCallback STUB_CALLBACK = new VisitCallback() {
public VisitResult visit(VisitContext context, UIComponent target) {
@@ -968,7 +869,7 @@
public Object getIterationState() {
assert rowKey == null;
- return new IterationState(this.componentState, this.extendedDataModel);
+ return new DataAdaptorIterationState(this.componentState,
this.extendedDataModel);
}
/*
@@ -982,7 +883,7 @@
// TODO - ?
// restoreChildState(getFacesContext());
if (stateObject != null) {
- IterationState iterationState = (IterationState) stateObject;
+ DataAdaptorIterationState iterationState = (DataAdaptorIterationState)
stateObject;
iterationState.restoreComponentState(this);
this.componentState = iterationState.getComponentState();
@@ -1053,7 +954,7 @@
@Override
public Object saveState(FacesContext context) {
Object parentState = super.saveState(context);
- Object savedComponentState = new IterationState(componentState,
extendedDataModel).saveState();
+ Object savedComponentState = new DataAdaptorIterationState(componentState,
extendedDataModel).saveState(context);
Object converterState = null;
boolean nullDelta = true;
@@ -1112,8 +1013,8 @@
super.restoreState(context, state[0]);
if (state[1] != null) {
- IterationState iterationState = new IterationState();
- iterationState.restoreState(state[1]);
+ DataAdaptorIterationState iterationState = new DataAdaptorIterationState();
+ iterationState.restoreState(context, state[1]);
iterationState.restoreComponentState(this);
// TODO update state model binding
Added: trunk/ui/common/ui/src/test/java/org/richfaces/component/SavedStateTest.java
===================================================================
--- trunk/ui/common/ui/src/test/java/org/richfaces/component/SavedStateTest.java
(rev 0)
+++
trunk/ui/common/ui/src/test/java/org/richfaces/component/SavedStateTest.java 2011-02-16
23:04:13 UTC (rev 21715)
@@ -0,0 +1,218 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2011, 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import javax.faces.component.UIForm;
+import javax.faces.component.UIInput;
+import javax.faces.context.FacesContext;
+
+import org.ajax4jsf.component.IterationStateHolder;
+import org.jboss.test.faces.mock.Mock;
+import org.jboss.test.faces.mock.MockTestRunner;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+(a)RunWith(MockTestRunner.class)
+public class SavedStateTest {
+
+ @Mock
+ private FacesContext facesContext;
+
+ private IterationStateHolder iterationStateHolder;
+
+ private String iterationState;
+
+ @Before
+ public void setUp() throws Exception {
+ iterationStateHolder = new IterationStateHolder() {
+
+ public void setIterationState(Object state) {
+ iterationState = (String) state;
+ }
+
+ public Object getIterationState() {
+ return iterationState;
+ }
+ };
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ iterationStateHolder = null;
+ }
+
+ private void checkDefaultState(SavedState state) {
+
+ assertTrue(state.isValid());
+ assertFalse(state.isLocalValueSet());
+ assertFalse(state.isSubmitted());
+
+ assertNull(state.getIterationState());
+ assertNull(state.getSubmittedValue());
+ assertNull(state.getValue());
+ }
+
+ @Test
+ public void testDefaultValue() throws Exception {
+ SavedState state = new SavedState();
+ checkDefaultState(state);
+
+ SavedState inputState = new SavedState(new UIInput());
+ checkDefaultState(inputState);
+
+ SavedState formState = new SavedState(new UIForm());
+ checkDefaultState(formState);
+
+ SavedState iterationState = new SavedState(iterationStateHolder);
+ checkDefaultState(iterationState);
+ }
+
+ @Test
+ public void testIterationStateHolderConstructor() throws Exception {
+ this.iterationState = "some state";
+ SavedState iterationState = new SavedState(iterationStateHolder);
+
+ assertEquals("some state", iterationState.getIterationState());
+
+ assertFalse(iterationState.isSubmitted());
+ assertTrue(iterationState.isValid());
+ assertNull(iterationState.getSubmittedValue());
+ assertNull(iterationState.getValue());
+ assertFalse(iterationState.isLocalValueSet());
+ }
+
+ @Test
+ public void testIterationStateApply() throws Exception {
+ SavedState iterationState = new SavedState();
+ iterationState.setIterationState("some state");
+ iterationState.apply(iterationStateHolder);
+
+ assertEquals("some state", this.iterationState);
+ }
+
+ @Test
+ public void testFormConstructor() {
+ UIForm form = new UIForm();
+ form.setSubmitted(true);
+
+ SavedState formState = new SavedState(form);
+
+ assertTrue(formState.isSubmitted());
+
+ assertTrue(formState.isValid());
+ assertNull(formState.getSubmittedValue());
+ assertNull(formState.getValue());
+ assertFalse(formState.isLocalValueSet());
+ assertNull(formState.getIterationState());
+ }
+
+ @Test
+ public void testFormApply() {
+ SavedState formState = new SavedState();
+ formState.setSubmitted(true);
+
+ UIForm form = new UIForm();
+ formState.apply(form);
+
+ assertTrue(form.isSubmitted());
+ }
+
+ @Test
+ public void testInputConstructor() {
+ UIInput input = new UIInput();
+
+ input.setValid(false);
+ input.setSubmittedValue("submitted");
+ input.setValue("value");
+ input.setLocalValueSet(true);
+
+ SavedState inputState = new SavedState(input);
+
+ assertFalse(inputState.isValid());
+ assertEquals("submitted", inputState.getSubmittedValue());
+ assertEquals("value", inputState.getValue());
+ assertTrue(inputState.isLocalValueSet());
+
+ assertFalse(inputState.isSubmitted());
+ assertNull(inputState.getIterationState());
+ }
+
+ @Test
+ public void testInputApply() {
+ SavedState state = new SavedState();
+ state.setValid(false);
+ state.setSubmittedValue("submitted");
+ state.setValue("value");
+ state.setLocalValueSet(true);
+
+ UIInput input = new UIInput();
+ state.apply(input);
+
+ assertFalse(input.isValid());
+ assertEquals("submitted", input.getSubmittedValue());
+ assertEquals("value", input.getValue());
+ assertTrue(input.isLocalValueSet());
+ }
+
+ @Test
+ public void testTransient() throws Exception {
+ SavedState defaultState = new SavedState();
+
+ assertTrue(defaultState.isTransient());
+
+ SavedState state = new SavedState();
+ state.setIterationState("something");
+ assertFalse(state.isTransient());
+
+ state = new SavedState();
+ state.setLocalValueSet(true);
+ assertFalse(state.isTransient());
+
+ state = new SavedState();
+ state.setSubmitted(true);
+ assertFalse(state.isTransient());
+
+ state = new SavedState();
+ state.setSubmittedValue("submitted");
+ assertFalse(state.isTransient());
+
+ state = new SavedState();
+ state.setValid(false);
+ assertFalse(state.isTransient());
+
+ state = new SavedState();
+ state.setValue(Integer.MAX_VALUE);
+ assertFalse(state.isTransient());
+ }
+}