javadoc and tests for flow/view variables

This commit is contained in:
Keith Donald
2008-03-02 19:11:47 +00:00
parent 1d92c77d9a
commit 6458d9a84a
7 changed files with 157 additions and 32 deletions

View File

@@ -20,8 +20,9 @@ import org.springframework.util.Assert;
import org.springframework.webflow.execution.RequestContext;
/**
* A value object that defines a specification for a flow variable. Encapsulates information about the variable and the
* behavior necessary to create a new variable instance in a flow execution scope.
* A value object that defines a specification for a flow variable. Such a variable is allocated when a flow starts and
* destroyed when that flow ends. This class encapsulates information about the variable and the behavior necessary to
* allocate the variable instance in flow scope.
*
* @author Keith Donald
*/
@@ -84,8 +85,12 @@ public class FlowVariable extends AnnotatedObject {
return name.hashCode() + valueFactory.hashCode() + local.hashCode();
}
public final void create(RequestContext context) {
Object value = valueFactory.createVariableValue(context);
/**
* Creates this flow variable. This method allocates the variable's value in the correct flow scope.
* @param context the executing flow
*/
public void create(RequestContext context) {
Object value = valueFactory.createInitialValue(context);
if (local == Boolean.TRUE) {
context.getFlowScope().put(name, value);
} else {
@@ -93,14 +98,31 @@ public class FlowVariable extends AnnotatedObject {
}
}
public final Object restore(RequestContext context) {
/**
* Restores this variable's dependencies. This method asks the variable's value factory to restore any references
* the variable has to transient objects.
* @param context the executing flow
*/
public void restore(RequestContext context) {
Object value;
if (local == Boolean.TRUE) {
value = context.getFlowScope().get(name);
} else {
value = context.getConversationScope().get(name);
}
return valueFactory.restoreReferences(value, context);
valueFactory.restoreReferences(value, context);
}
/**
* Destroys this flow variable. This method removes the variable's value in the correct flow scope.
* @param context the executing flow
*/
public Object destroy(RequestContext context) {
if (local == Boolean.TRUE) {
return context.getFlowScope().remove(name);
} else {
return context.getConversationScope().remove(name);
}
}
public String toString() {

View File

@@ -2,8 +2,24 @@ package org.springframework.webflow.engine;
import org.springframework.webflow.execution.RequestContext;
/**
* A strategy that encapsulates the source of a flow variable value.
* @author Keith Donald
*/
public interface VariableValueFactory {
public Object createVariableValue(RequestContext context);
public Object restoreReferences(Object value, RequestContext context);
/**
* Creates the variable's initial value.
* @param context the currently executing flow request
* @return the value
*/
public Object createInitialValue(RequestContext context);
/**
* Restore any references the variable's value needs to other objects. Such references may have been lost during
* deserialization, for example, and need to be restored.
* @param value the current variable value
* @param context the currently executing flow request
*/
public void restoreReferences(Object value, RequestContext context);
}

View File

@@ -2,20 +2,38 @@ package org.springframework.webflow.engine;
import org.springframework.webflow.execution.RequestContext;
/**
* A variable scoped to a particular view. Such a variable is allocated when a view-state is entered and destroyed when
* that view-state exits. The flow scope map is used as the backing variable store.
*
* @author Keith Donald
*/
public class ViewVariable extends AnnotatedObject {
private String name;
private VariableValueFactory valueFactory;
/**
* Creates a new view variable.
* @param name the name of the variable
* @param valueFactory the source for the variable value
*/
public ViewVariable(String name, VariableValueFactory valueFactory) {
this.name = name;
this.valueFactory = valueFactory;
}
/**
* Returns the name of this view variable.
*/
public String getName() {
return name;
}
/**
* Returns the source of the variable's initial value.
*/
public VariableValueFactory getValueFactory() {
return valueFactory;
}
@@ -34,17 +52,30 @@ public class ViewVariable extends AnnotatedObject {
return name.hashCode() + valueFactory.hashCode();
}
public final void create(RequestContext context) {
Object value = valueFactory.createVariableValue(context);
/**
* Creates this view variable. This method allocates the variable's value in flow scope.
* @param context the executing flow
*/
public void create(RequestContext context) {
Object value = valueFactory.createInitialValue(context);
context.getFlowScope().put(name, value);
}
public final Object restore(RequestContext context) {
/**
* Restores this view variable's dependencies. This method asks the variable's value factory to restore any
* references the variable has to transient objects.
* @param context the executing flow
*/
public void restore(RequestContext context) {
Object value = context.getFlowScope().get(name);
return valueFactory.restoreReferences(value, context);
valueFactory.restoreReferences(value, context);
}
public final Object destroy(RequestContext context) {
/**
* Destroy this view variable. This method removes the variable's value in flow scope.
* @param context the executing flow
*/
public Object destroy(RequestContext context) {
return context.getFlowScope().remove(name);
}
}

View File

@@ -16,27 +16,48 @@
package org.springframework.webflow.engine.support;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.core.style.ToStringCreator;
import org.springframework.webflow.engine.VariableValueFactory;
import org.springframework.webflow.execution.RequestContext;
/**
* A bean-factory backed variable value factory. Relies on an autowire-capable bean factory to wire variable value
* dependencies on value creation and restoration.
*
* @author Keith Donald
*/
public class BeanFactoryVariableValueFactory implements VariableValueFactory {
/**
* The class of variable value. Typically a Java bean.
*/
private Class type;
/**
* The backing bean factory that will create and restore variable instances.
*/
private AutowireCapableBeanFactory beanFactory;
/**
* Creates a new bean factory variable factory.
* @param type the variable class
* @param beanFactory the bean factory that will create and restore variable instances.
*/
public BeanFactoryVariableValueFactory(Class type, AutowireCapableBeanFactory beanFactory) {
this.type = type;
this.beanFactory = beanFactory;
}
public Object createVariableValue(RequestContext context) {
public Object createInitialValue(RequestContext context) {
return beanFactory.createBean(type);
}
public Object restoreReferences(Object value, RequestContext context) {
public void restoreReferences(Object value, RequestContext context) {
beanFactory.autowireBean(value);
return value;
}
public String toString() {
return new ToStringCreator(this).append("type").append(type).toString();
}
}

View File

@@ -182,12 +182,11 @@ public class FlowTests extends TestCase {
public void testStartWithVariables() {
MockRequestControlContext context = new MockRequestControlContext(flow);
flow.addVariable(new FlowVariable("var1", new VariableValueFactory() {
public Object createVariableValue(RequestContext context) {
public Object createInitialValue(RequestContext context) {
return new ArrayList();
}
public Object restoreReferences(Object value, RequestContext context) {
return value;
public void restoreReferences(Object value, RequestContext context) {
}
}, true));
flow.start(context, new LocalAttributeMap());

View File

@@ -11,28 +11,41 @@ public class FlowVariableTests extends TestCase {
public void testCreateVariable() {
FlowVariable var = new FlowVariable("foo", new VariableValueFactory() {
public Object createVariableValue(RequestContext context) {
public Object createInitialValue(RequestContext context) {
return "bar";
}
public Object restoreReferences(Object value, RequestContext context) {
return value;
public void restoreReferences(Object value, RequestContext context) {
}
}, true);
MockRequestContext context = new MockRequestContext();
var.create(context);
assertEquals("bar", context.getFlowScope().get("foo"));
}
public void testCreateConversationVariable() {
public void testDestroyVariable() {
FlowVariable var = new FlowVariable("foo", new VariableValueFactory() {
public Object createVariableValue(RequestContext context) {
public Object createInitialValue(RequestContext context) {
return "bar";
}
public Object restoreReferences(Object value, RequestContext context) {
return value;
public void restoreReferences(Object value, RequestContext context) {
}
}, true);
MockRequestContext context = new MockRequestContext();
var.create(context);
assertEquals("bar", context.getFlowScope().get("foo"));
var.destroy(context);
assertFalse(context.getFlowScope().contains("foo"));
}
public void testCreateConversationVariable() {
FlowVariable var = new FlowVariable("foo", new VariableValueFactory() {
public Object createInitialValue(RequestContext context) {
return "bar";
}
public void restoreReferences(Object value, RequestContext context) {
}
}, false);
MockRequestContext context = new MockRequestContext();
@@ -40,16 +53,31 @@ public class FlowVariableTests extends TestCase {
assertEquals("bar", context.getConversationScope().get("foo"));
}
public void testCreateRestoreVariable() {
public void testDestroyConversationVariable() {
FlowVariable var = new FlowVariable("foo", new VariableValueFactory() {
public Object createVariableValue(RequestContext context) {
public Object createInitialValue(RequestContext context) {
return "bar";
}
public Object restoreReferences(Object value, RequestContext context) {
public void restoreReferences(Object value, RequestContext context) {
}
}, false);
MockRequestContext context = new MockRequestContext();
var.create(context);
assertEquals("bar", context.getConversationScope().get("foo"));
var.destroy(context);
assertFalse(context.getConversationScope().contains("foo"));
}
public void testRestoreVariable() {
FlowVariable var = new FlowVariable("foo", new VariableValueFactory() {
public Object createInitialValue(RequestContext context) {
return "bar";
}
public void restoreReferences(Object value, RequestContext context) {
restoreCalled = true;
assertEquals("bar", value);
return value;
}
}, false);
MockRequestContext context = new MockRequestContext();
@@ -58,4 +86,5 @@ public class FlowVariableTests extends TestCase {
assertEquals("bar", context.getConversationScope().get("foo"));
assertTrue(restoreCalled);
}
}

View File

@@ -12,7 +12,14 @@ public class BeanFactoryVariableValueFactoryTests extends TestCase {
public void testCreateValue() {
factory = new BeanFactoryVariableValueFactory(TestBean.class, new DefaultListableBeanFactory());
MockRequestContext context = new MockRequestContext();
Object value = factory.createVariableValue(context);
Object value = factory.createInitialValue(context);
assertTrue(value instanceof TestBean);
}
public void testRestoreValue() {
factory = new BeanFactoryVariableValueFactory(TestBean.class, new DefaultListableBeanFactory());
MockRequestContext context = new MockRequestContext();
TestBean bean = new TestBean();
factory.restoreReferences(bean, context);
}
}