diff --git a/spring-binding/src/main/java/org/springframework/binding/message/MessageBuilder.java b/spring-binding/src/main/java/org/springframework/binding/message/MessageBuilder.java
index 656e49aa..2690b6f6 100644
--- a/spring-binding/src/main/java/org/springframework/binding/message/MessageBuilder.java
+++ b/spring-binding/src/main/java/org/springframework/binding/message/MessageBuilder.java
@@ -1,6 +1,10 @@
package org.springframework.binding.message;
+import java.util.ArrayList;
+import java.util.LinkedHashSet;
+import java.util.List;
import java.util.Locale;
+import java.util.Set;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceResolvable;
@@ -14,8 +18,7 @@ import org.springframework.context.MessageSourceResolvable;
* Usage example:
*
*
- * new MessageBuilder().error().source(this).code("mycode").args(new Object[] { arg1, arg2 }).defaultText("Fallback text")
- * .build();
+ * new MessageBuilder().error().source(this).code("mycode").arg(arg1).arg(arg2).defaultText("text").build();
*
*
* @author Keith Donald
@@ -24,45 +27,14 @@ public class MessageBuilder {
private Object source;
- private String[] codes;
+ private Set codes = new LinkedHashSet();
private Severity severity;
- private Object[] args;
+ private List args = new ArrayList();
private String defaultText;
- /**
- * Records that the message being built is from the source provided.
- * @param source the source generating the message
- * @return this, for fluent API usage
- */
- public MessageBuilder source(Object source) {
- this.source = source;
- return this;
- }
-
- /**
- * Records that the message being built should have its text resolved using the code provided.
- * @param code the message code
- * @return this, for fluent API usage
- */
- public MessageBuilder code(String code) {
- codes = new String[] { code };
- return this;
- }
-
- /**
- * Records that the message being built should have its text resolved using the codes provided. The codes are tried
- * in-order until their is a match.
- * @param codes the message codes
- * @return this, for fluent API usage
- */
- public MessageBuilder codes(String[] codes) {
- this.codes = codes;
- return this;
- }
-
/**
* Records that the message being built is an informational message.
* @return this, for fluent API usage
@@ -91,28 +63,53 @@ public class MessageBuilder {
}
/**
- * Records that the message being built has a single argument.
- * @param arg the message argument
+ * Records that the message being built is against the provided source.
+ * @param source the source generating the message
* @return this, for fluent API usage
*/
- public MessageBuilder arg(Object arg) {
- this.args = new Object[] { arg };
+ public MessageBuilder source(Object source) {
+ this.source = source;
return this;
}
/**
- * Records that the message being built has arguments.
- * @param args the message arguments
+ * Records that the message being built should try and resolve its text using the code provided. Adds the code to
+ * the codes list. Successive calls to this method add additional codes. Codes are applied in the order they are
+ * added.
+ * @param code the message code
* @return this, for fluent API usage
*/
- public MessageBuilder args(Object[] args) {
- this.args = args;
+ public MessageBuilder code(String code) {
+ codes.add(code);
+ return this;
+ }
+
+ /**
+ * Records that the message being built has a variable argument. Adds the arg to the args list. Successive calls to
+ * this method add additional args. Args are applied in the order they are added.
+ * @param arg the message argument value
+ * @return this, for fluent API usage
+ */
+ public MessageBuilder arg(Object arg) {
+ args.add(arg);
+ return this;
+ }
+
+ /**
+ * Records that the message being built has a variable argument, whose display value is also
+ * {@link MessageSourceResolvable}. Adds the arg to the args list. Successive calls to this method add additional
+ * resolvable args. Args are applied in the order they are added.
+ * @param arg the resolvable message argument
+ * @return this, for fluent API usage
+ */
+ public MessageBuilder resolvableArg(Object arg) {
+ args.add(new ResolvableArgument(arg));
return this;
}
/**
* Records the fallback text of the message being built. If the message has no codes, this will always be used as
- * the text.
+ * the text. If the message has codes but none can be resolved, this will alway be used as the text.
* @param text the default text
* @return this, for fluent API usage
*/
@@ -133,7 +130,9 @@ public class MessageBuilder {
throw new IllegalArgumentException(
"A message code or the message text is required to build this message resolver");
}
- return new BuiltMessageResolver(source, codes, severity, args, defaultText);
+ String[] codesArray = (String[]) codes.toArray(new String[codes.size()]);
+ Object[] argsArray = args.toArray(new Object[args.size()]);
+ return new BuiltMessageResolver(source, codesArray, severity, argsArray, defaultText);
}
private static class BuiltMessageResolver implements MessageResolver, MessageSourceResolvable {
@@ -170,4 +169,26 @@ public class MessageBuilder {
}
}
+ private static class ResolvableArgument implements MessageSourceResolvable {
+
+ private Object arg;
+
+ public ResolvableArgument(Object arg) {
+ this.arg = arg;
+ }
+
+ public Object[] getArguments() {
+ return null;
+ }
+
+ public String[] getCodes() {
+ return new String[] { arg.toString() };
+ }
+
+ public String getDefaultMessage() {
+ return arg.toString();
+ }
+
+ }
+
}
diff --git a/spring-binding/src/test/java/org/springframework/binding/message/DefaultMessageContextFactoryTests.java b/spring-binding/src/test/java/org/springframework/binding/message/DefaultMessageContextFactoryTests.java
index abf6de0c..a63ab850 100644
--- a/spring-binding/src/test/java/org/springframework/binding/message/DefaultMessageContextFactoryTests.java
+++ b/spring-binding/src/test/java/org/springframework/binding/message/DefaultMessageContextFactoryTests.java
@@ -62,8 +62,8 @@ public class DefaultMessageContextFactoryTests extends TestCase {
public void testResolveMessageWithMultipleCodes() {
MessageContext context = factory.createMessageContext();
- context.addMessage(new MessageBuilder().error().source(this).codes(new String[] { "bogus", "argmessage" })
- .args(new Object[] { "Keith" }).defaultText("Hello world fallback!").build());
+ context.addMessage(new MessageBuilder().error().source(this).code("bogus").code("argmessage").arg("Keith")
+ .defaultText("Hello world fallback!").build());
Message[] messages = context.getMessagesBySource(this);
assertEquals(1, messages.length);
assertEquals("Hello world Keith!", messages[0].getText());
diff --git a/spring-webflow/src/main/java/org/springframework/webflow/mvc/view/MvcView.java b/spring-webflow/src/main/java/org/springframework/webflow/mvc/view/MvcView.java
index 445d3184..a8eb18fa 100644
--- a/spring-webflow/src/main/java/org/springframework/webflow/mvc/view/MvcView.java
+++ b/spring-webflow/src/main/java/org/springframework/webflow/mvc/view/MvcView.java
@@ -206,7 +206,7 @@ class MvcView implements View {
private MessageResolver message(MappingResult error) {
String field = error.getMapping().getTargetExpression().getExpressionString();
String errorCode = error.getResult().getErrorCode();
- return new MessageBuilder().error().source(field).code(errorCode).arg(field).defaultText(
+ return new MessageBuilder().error().source(field).code(errorCode).resolvableArg(field).defaultText(
errorCode + " on " + field).build();
}