/** Tests the workflow method. */
  @Test
  public void testSimpleParameters() throws IOException, ServletException {
    Action action = new Action();

    Map<String, String[]> values = new HashMap<String, String[]>();
    values.put("user.addresses['home'].city", array("Boulder"));
    values.put("user.age", array("32"));
    values.put("user.inches", array("tall"));
    values.put("user.age@dateFormat", array("MM/dd/yyyy"));
    values.put(
        "user.name",
        array("")); // This should be stripped out and the ExpressionEvaluator never called for it

    final HttpServletRequest request = EasyMock.createStrictMock(HttpServletRequest.class);
    EasyMock.expect(request.getParameterMap()).andReturn(values);
    EasyMock.replay(request);

    ExpressionEvaluator expressionEvaluator = EasyMock.createNiceMock(ExpressionEvaluator.class);
    expressionEvaluator.setValue(
        eq("user.addresses['home'].city"),
        same(action),
        aryEq(array("Boulder")),
        eq(new HashMap<String, String>()));
    expressionEvaluator.setValue(
        eq("user.age"), same(action), aryEq(array("32")), eq(map("dateFormat", "MM/dd/yyyy")));
    expressionEvaluator.setValue(
        eq("user.inches"), same(action), aryEq(array("tall")), eq(new HashMap<String, String>()));
    expectLastCall().andThrow(new ConversionException());
    EasyMock.replay(expressionEvaluator);

    ActionInvocation invocation = EasyMock.createStrictMock(ActionInvocation.class);
    EasyMock.expect(invocation.action()).andReturn(action);
    EasyMock.replay(invocation);

    ActionInvocationStore actionInvocationStore =
        EasyMock.createStrictMock(ActionInvocationStore.class);
    EasyMock.expect(actionInvocationStore.getCurrent()).andReturn(invocation);
    EasyMock.replay(actionInvocationStore);

    MessageStore messageStore = EasyMock.createStrictMock(MessageStore.class);
    messageStore.addConversionError(
        eq("user.inches"),
        eq("org.example.domain.Action"),
        eq(new HashMap<String, String>()),
        eq("tall"));
    EasyMock.replay(messageStore);

    WorkflowChain chain = EasyMock.createStrictMock(WorkflowChain.class);
    chain.continueWorkflow();
    EasyMock.replay(chain);

    DefaultParameterWorkflow workflow =
        new DefaultParameterWorkflow(
            request, actionInvocationStore, messageStore, expressionEvaluator);
    workflow.perform(chain);

    EasyMock.verify(
        request, expressionEvaluator, invocation, actionInvocationStore, messageStore, chain);
  }
  /**
   * Performs validation on the User class by passing the User object from the form submission to
   * the {@link UserService#validate(User,Map,boolean,String,String)} method. In order to accomodate
   * the username and email variations on the {@link DefaultUser} class, this checks the
   * configuration to see if the {@link UserConfiguration#isUsernameSameAsEmail()} method returns
   * true and if it does, it assumes that the form only has a field for the username and copies that
   * value from the username property to the email property.
   */
  @SuppressWarnings("unchecked")
  @ValidateMethod
  public void validate() {
    // It is okay to create the user as a side-effect because it will be empty
    if (user == null) {
      user = new DefaultUser();
    }

    if (userConfiguration.isUsernameSameAsEmail()) {
      user.setUsername(user.getEmail());
    }

    ErrorList errors =
        userService.validate(user, associations, user.getId() != null, password, passwordConfirm);
    if (!errors.isEmpty()) {
      for (net.java.error.Error error : errors) {
        PropertyError pe = (PropertyError) error;
        messageStore.addFieldError(MessageScope.REQUEST, pe.getProperty(), pe.getMessage());
      }
    }
  }