From bcef26dd4a4e0148ace7ab6ef8815a426e7dbbe3 Mon Sep 17 00:00:00 2001 From: Keith Donald Date: Thu, 24 Apr 2008 20:36:57 +0000 Subject: [PATCH] http://jira.springframework.org/browse/SWF-632 --- .../support/ActionExecutingViewFactory.java | 69 +++++++++++++++++-- .../ActionExecutingViewFactoryTests.java | 63 +++++++++++++++++ 2 files changed, 125 insertions(+), 7 deletions(-) create mode 100644 spring-webflow/src/test/java/org/springframework/webflow/engine/support/ActionExecutingViewFactoryTests.java diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/support/ActionExecutingViewFactory.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/support/ActionExecutingViewFactory.java index 35d58533..8b238eb7 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/engine/support/ActionExecutingViewFactory.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/support/ActionExecutingViewFactory.java @@ -15,6 +15,9 @@ */ package org.springframework.webflow.engine.support; +import java.util.Iterator; + +import org.springframework.webflow.core.collection.ParameterMap; import org.springframework.webflow.engine.ActionExecutor; import org.springframework.webflow.execution.Action; import org.springframework.webflow.execution.Event; @@ -53,29 +56,81 @@ public class ActionExecutingViewFactory implements ViewFactory { private Action action; - private RequestContext context; + private RequestContext requestContext; - private ActionExecutingView(Action action, RequestContext context) { + private String eventId; + + private ActionExecutingView(Action action, RequestContext requestContext) { this.action = action; - this.context = context; + this.requestContext = requestContext; } public void render() { if (action != null) { - ActionExecutor.execute(action, context); + ActionExecutor.execute(action, requestContext); } } public void processUserEvent() { - + determineEventId(requestContext); } public boolean hasFlowEvent() { - return context.getExternalContext().getRequestParameterMap().contains("_eventId"); + return eventId != null; } public Event getFlowEvent() { - return new Event(this, context.getExternalContext().getRequestParameterMap().get("_eventId")); + if (!hasFlowEvent()) { + return null; + } + return new Event(this, eventId); + } + + private void determineEventId(RequestContext context) { + eventId = findParameter("_eventId", context.getRequestParameters()); + } + + /** + * Obtain a named parameter from the request parameters. This method will try to obtain a parameter value using + * the following algorithm: + *
    + *
  1. Try to get the parameter value using just the given logical name. This handles parameters of the + * form logicalName = value. For normal parameters, e.g. submitted using a hidden HTML form field, + * this will return the requested value.
  2. + *
  3. Try to obtain the parameter value from the parameter name, where the parameter name in the request is of + * the form logicalName_value = xyz with "_" being the configured delimiter. This deals with + * parameter values submitted using an HTML form submit button.
  4. + *
  5. If the value obtained in the previous step has a ".x" or ".y" suffix, remove that. This handles cases + * where the value was submitted using an HTML form image button. In this case the parameter in the request + * would actually be of the form logicalName_value.x = 123.
  6. + *
+ * @param logicalParameterName the logical name of the request parameter + * @param parameters the available parameter map + * @return the value of the parameter, or null if the parameter does not exist in given request + */ + private String findParameter(String logicalParameterName, ParameterMap parameters) { + // first try to get it as a normal name=value parameter + String value = parameters.get(logicalParameterName); + if (value != null) { + return value; + } + // if no value yet, try to get it as a name_value=xyz parameter + String prefix = logicalParameterName + "_"; + Iterator paramNames = parameters.asMap().keySet().iterator(); + while (paramNames.hasNext()) { + String paramName = (String) paramNames.next(); + if (paramName.startsWith(prefix)) { + String strValue = paramName.substring(prefix.length()); + // support images buttons, which would submit parameters as + // name_value.x=123 + if (strValue.endsWith(".x") || strValue.endsWith(".y")) { + strValue = strValue.substring(0, strValue.length() - 2); + } + return strValue; + } + } + // we couldn't find the parameter value + return null; } } diff --git a/spring-webflow/src/test/java/org/springframework/webflow/engine/support/ActionExecutingViewFactoryTests.java b/spring-webflow/src/test/java/org/springframework/webflow/engine/support/ActionExecutingViewFactoryTests.java new file mode 100644 index 00000000..485abd1b --- /dev/null +++ b/spring-webflow/src/test/java/org/springframework/webflow/engine/support/ActionExecutingViewFactoryTests.java @@ -0,0 +1,63 @@ +package org.springframework.webflow.engine.support; + +import java.io.IOException; + +import junit.framework.TestCase; + +import org.springframework.webflow.execution.TestAction; +import org.springframework.webflow.execution.View; +import org.springframework.webflow.test.MockRequestContext; + +public class ActionExecutingViewFactoryTests extends TestCase { + + public void testGetView() throws Exception { + TestAction action = new TestAction(); + ActionExecutingViewFactory factory = new ActionExecutingViewFactory(action); + MockRequestContext context = new MockRequestContext(); + View view = factory.getView(context); + assertFalse(action.isExecuted()); + view.render(); + assertTrue(action.isExecuted()); + } + + public void testProcessUserEvent() throws IOException { + TestAction action = new TestAction(); + ActionExecutingViewFactory factory = new ActionExecutingViewFactory(action); + MockRequestContext context = new MockRequestContext(); + View view = factory.getView(context); + assertFalse(action.isExecuted()); + view.render(); + assertTrue(action.isExecuted()); + context.putRequestParameter("_eventId", "foo"); + view.processUserEvent(); + assertTrue(view.hasFlowEvent()); + assertEquals("foo", view.getFlowEvent().getId()); + } + + public void testProcessUserEventButton() throws IOException { + TestAction action = new TestAction(); + ActionExecutingViewFactory factory = new ActionExecutingViewFactory(action); + MockRequestContext context = new MockRequestContext(); + View view = factory.getView(context); + assertFalse(action.isExecuted()); + view.render(); + assertTrue(action.isExecuted()); + context.putRequestParameter("_eventId_foo", "doesn't matter"); + view.processUserEvent(); + assertTrue(view.hasFlowEvent()); + assertEquals("foo", view.getFlowEvent().getId()); + } + + public void testProcessUserEventNoEvent() throws IOException { + TestAction action = new TestAction(); + ActionExecutingViewFactory factory = new ActionExecutingViewFactory(action); + MockRequestContext context = new MockRequestContext(); + View view = factory.getView(context); + assertFalse(action.isExecuted()); + view.render(); + assertTrue(action.isExecuted()); + view.processUserEvent(); + assertFalse(view.hasFlowEvent()); + assertNull(view.getFlowEvent()); + } +}