From 6458d9a84a64cfaf0e7d07770365fa38189825ba Mon Sep 17 00:00:00 2001 From: Keith Donald Date: Sun, 2 Mar 2008 19:11:47 +0000 Subject: [PATCH] javadoc and tests for flow/view variables --- .../webflow/engine/FlowVariable.java | 34 +++++++++--- .../webflow/engine/VariableValueFactory.java | 20 ++++++- .../webflow/engine/ViewVariable.java | 41 ++++++++++++-- .../BeanFactoryVariableValueFactory.java | 27 ++++++++-- .../webflow/engine/FlowTests.java | 5 +- .../webflow/engine/FlowVariableTests.java | 53 ++++++++++++++----- .../BeanFactoryVariableValueFactoryTests.java | 9 +++- 7 files changed, 157 insertions(+), 32 deletions(-) diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/FlowVariable.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/FlowVariable.java index 6ba2bfab..59f98b54 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/engine/FlowVariable.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/FlowVariable.java @@ -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() { diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/VariableValueFactory.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/VariableValueFactory.java index be9fa332..b346833a 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/engine/VariableValueFactory.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/VariableValueFactory.java @@ -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); } diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/ViewVariable.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/ViewVariable.java index 3f7dbdd7..55a325d3 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/engine/ViewVariable.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/ViewVariable.java @@ -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); } } diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/support/BeanFactoryVariableValueFactory.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/support/BeanFactoryVariableValueFactory.java index 0f24fa28..1cad4acd 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/engine/support/BeanFactoryVariableValueFactory.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/support/BeanFactoryVariableValueFactory.java @@ -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(); } } \ No newline at end of file diff --git a/spring-webflow/src/test/java/org/springframework/webflow/engine/FlowTests.java b/spring-webflow/src/test/java/org/springframework/webflow/engine/FlowTests.java index 8d737b20..f979043e 100644 --- a/spring-webflow/src/test/java/org/springframework/webflow/engine/FlowTests.java +++ b/spring-webflow/src/test/java/org/springframework/webflow/engine/FlowTests.java @@ -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()); diff --git a/spring-webflow/src/test/java/org/springframework/webflow/engine/FlowVariableTests.java b/spring-webflow/src/test/java/org/springframework/webflow/engine/FlowVariableTests.java index ecefcbf7..e57a134f 100644 --- a/spring-webflow/src/test/java/org/springframework/webflow/engine/FlowVariableTests.java +++ b/spring-webflow/src/test/java/org/springframework/webflow/engine/FlowVariableTests.java @@ -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); } + } diff --git a/spring-webflow/src/test/java/org/springframework/webflow/engine/support/BeanFactoryVariableValueFactoryTests.java b/spring-webflow/src/test/java/org/springframework/webflow/engine/support/BeanFactoryVariableValueFactoryTests.java index 275ded80..e4ad6342 100644 --- a/spring-webflow/src/test/java/org/springframework/webflow/engine/support/BeanFactoryVariableValueFactoryTests.java +++ b/spring-webflow/src/test/java/org/springframework/webflow/engine/support/BeanFactoryVariableValueFactoryTests.java @@ -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); + } }