diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/ExpressionParser.java b/spring-binding/src/main/java/org/springframework/binding/expression/ExpressionParser.java
index 44477d27..9906f075 100644
--- a/spring-binding/src/main/java/org/springframework/binding/expression/ExpressionParser.java
+++ b/spring-binding/src/main/java/org/springframework/binding/expression/ExpressionParser.java
@@ -24,33 +24,7 @@ package org.springframework.binding.expression;
public interface ExpressionParser {
/**
- * Is the provided expression string an "eval" expression: meaning an expression that validates to a dynamic value,
- * and not a literal expression? "Eval" expressions are normally enclosed in delimiters like #{}, where literal
- * expressions are not delimited.
- *
- * TODO - candidate for removal in a future milestone: is this really needed?
- * @param string the string
- * @return true if the expression is an eval expression string, false otherwise.
- */
- public boolean isEvalExpressionString(String string);
-
- /**
- * Parse the raw string into an "eval" expression string that when parsed produces a dynamic value when evaluated
- * against a target object. For example, the raw expression string "person.id" might become #{person.id}. If the
- * string is already an eval expression string, the string argument is returned unchanged. If the string is an
- * composite expression string that mixes eval and literal expressions, a parser exception is thrown.
- *
- * TODO - candidate for removal in a future milestone: is this really needed?
- * @param string the raw string to be transformed into a parseable eval expression string
- * @return the eval expression spring
- * @throws ParserException an exception occurred during parsing
- */
- public String parseEvalExpressionString(String string) throws ParserException;
-
- /**
- * Parse the provided expression string, returning an expression evaluator capable of evaluating it. The expression
- * string may be a literal expression string like "foo", an eval-expression string like #{foo}, or a
- * composite-expression string like "foo#{foo}bar#{bar}".
+ * Parse the provided expression string, returning an expression evaluator capable of evaluating it.
* @param expressionString the parseable expression string; cannot be null
* @param expressionTargetType the class of target object this expression can successfully evaluate; for example,
* Map.class for an expression that is expected to evaluate against Maps.
@@ -58,8 +32,8 @@ public interface ExpressionParser {
* example, Boolean.class for an expression that is expected to get or set a boolean value. Typically
* used to facilitate type conversion by the expression evaluator; for example, if a evaluated expression equates to
* a String value 'true', with an expected Boolean result the string value could be converted to a typed Boolean
- * value.
- * @param expressionVariables variables providing aliases for this expression during evaluation. Optional.
+ * value (required).
+ * @param expressionVariables variables providing aliases for this expression during evaluation (optional).
* @return the evaluator for the parsed expression
* @throws ParserException an exception occurred during parsing
*/
diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/ExpressionVariable.java b/spring-binding/src/main/java/org/springframework/binding/expression/ExpressionVariable.java
index 65820c80..23340df3 100644
--- a/spring-binding/src/main/java/org/springframework/binding/expression/ExpressionVariable.java
+++ b/spring-binding/src/main/java/org/springframework/binding/expression/ExpressionVariable.java
@@ -3,28 +3,25 @@ package org.springframework.binding.expression;
import org.springframework.util.Assert;
/**
- * A simple, convenient alias for a more-complex expression.
- *
- * TODO - consider making the valueExpressionString a parsed Expression object for more flexibility.
- *
+ * An expression variable.
* @author Keith Donald
*/
public class ExpressionVariable {
private String name;
- private String valueExpressionString;
+ private String value;
/**
* Creates a new expression variable
* @param name the name of the variable, acting as an convenient alias
- * @param valueExpressionString the complex expression to be aliased in string form
+ * @param value the initial value of the variable
*/
- public ExpressionVariable(String name, String valueExpressionString) {
+ public ExpressionVariable(String name, String value) {
Assert.hasText(name, "The expression variable must be named");
- Assert.hasText(valueExpressionString, "The expression value expression string is required");
+ Assert.hasText(value, "The expression variable value is required");
this.name = name;
- this.valueExpressionString = valueExpressionString;
+ this.value = value;
}
/**
@@ -39,8 +36,8 @@ public class ExpressionVariable {
* Returns the expression that will be evaluated when the variable is referenced by its name in another expression.
* @return the expression value.
*/
- public String getValueExpressionString() {
- return valueExpressionString;
+ public String getValue() {
+ return value;
}
public boolean equals(Object o) {
diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/el/ELExpressionParser.java b/spring-binding/src/main/java/org/springframework/binding/expression/el/ELExpressionParser.java
index e9d6af6f..e4a402b6 100644
--- a/spring-binding/src/main/java/org/springframework/binding/expression/el/ELExpressionParser.java
+++ b/spring-binding/src/main/java/org/springframework/binding/expression/el/ELExpressionParser.java
@@ -22,16 +22,6 @@ import org.springframework.binding.expression.ParserException;
*/
public class ELExpressionParser implements ExpressionParser {
- /**
- * The expression prefix.
- */
- private static final String EXPRESSION_PREFIX = "#{";
-
- /**
- * The expression suffix.
- */
- private static final String EXPRESSION_SUFFIX = "}";
-
/**
* The ExpressionFactory for constructing EL expressions
*/
@@ -55,40 +45,29 @@ public class ELExpressionParser implements ExpressionParser {
this.contextFactories.put(expressionTargetType, contextFactory);
}
- public boolean isEvalExpressionString(String expressionString) {
- return expressionString.startsWith(EXPRESSION_PREFIX) && expressionString.endsWith(EXPRESSION_SUFFIX);
- }
-
- public String parseEvalExpressionString(String string) {
- return encloseInDelimitersIfNecessary(string);
- }
-
public Expression parseExpression(String expressionString, Class expressionTargetType,
Class expectedEvaluationResultType, ExpressionVariable[] expressionVariables) throws ParserException {
- ParserELContext context = new ParserELContext();
+ if (expectedEvaluationResultType == null) {
+ throw new ParserException(expressionString, "The 'expectedEvaluationResultType' argument is required; "
+ + "specify Object.class if the type is unknown", new NullPointerException());
+ }
try {
+ ParserELContext context = new ParserELContext();
context.mapVariables(expressionVariables, expressionFactory);
ValueExpression expression = expressionFactory.createValueExpression(context, expressionString,
expectedEvaluationResultType);
- ELContextFactory contextFactory = getContextFactory(expressionString, expressionTargetType);
+ ELContextFactory contextFactory = getContextFactory(expressionTargetType, expressionString);
return new ELExpression(contextFactory, expression, context.getVariableMapper());
} catch (ELException ex) {
throw new ParserException(expressionString, ex);
}
}
- private String encloseInDelimitersIfNecessary(String expressionString) {
- if (isEvalExpressionString(expressionString)) {
- return expressionString;
- } else {
- return EXPRESSION_PREFIX + expressionString + EXPRESSION_SUFFIX;
- }
- }
-
- private ELContextFactory getContextFactory(String expressionString, Class expressionTargetType) {
+ private ELContextFactory getContextFactory(Class expressionTargetType, String expressionString) {
if (!contextFactories.containsKey(expressionTargetType)) {
throw new ParserException(expressionString, new IllegalArgumentException(
- "No ELContextFactory registered for expressionTargetType [" + expressionTargetType + "]"));
+ "No ELContextFactory registered for expressionTargetType [" + expressionTargetType + "]; "
+ + "Please ensure a factory is registered for this type."));
}
return (ELContextFactory) contextFactories.get(expressionTargetType);
}
@@ -113,8 +92,7 @@ public class ELExpressionParser implements ExpressionParser {
variableMapper = new VariableMapperImpl();
for (int i = 0; i < variables.length; i++) {
ExpressionVariable var = variables[i];
- ValueExpression expr = expressionFactory.createValueExpression(this,
- var.getValueExpressionString(), Object.class);
+ ValueExpression expr = expressionFactory.createValueExpression(this, var.getValue(), Object.class);
variableMapper.setVariable(var.getName(), expr);
}
}
diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/ognl/OgnlExpression.java b/spring-binding/src/main/java/org/springframework/binding/expression/ognl/OgnlExpression.java
index 5fca7b5f..f89d7cb2 100644
--- a/spring-binding/src/main/java/org/springframework/binding/expression/ognl/OgnlExpression.java
+++ b/spring-binding/src/main/java/org/springframework/binding/expression/ognl/OgnlExpression.java
@@ -16,6 +16,8 @@
package org.springframework.binding.expression.ognl;
import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
import ognl.Ognl;
import ognl.OgnlException;
@@ -23,6 +25,7 @@ import ognl.OgnlException;
import org.springframework.binding.expression.EvaluationAttempt;
import org.springframework.binding.expression.EvaluationException;
import org.springframework.binding.expression.Expression;
+import org.springframework.binding.expression.ExpressionVariable;
import org.springframework.binding.expression.SetValueAttempt;
import org.springframework.util.Assert;
@@ -41,12 +44,18 @@ class OgnlExpression implements Expression {
*/
private Object expression;
+ /**
+ * Expression variable initial values.
+ */
+ private ExpressionVariable[] variables;
+
/**
* Creates a new OGNL expression.
* @param expression the parsed expression
*/
- public OgnlExpression(Object expression) {
+ public OgnlExpression(Object expression, ExpressionVariable[] variables) {
this.expression = expression;
+ this.variables = variables;
}
public int hashCode() {
@@ -66,8 +75,13 @@ class OgnlExpression implements Expression {
public Object getValue(Object target) throws EvaluationException {
Assert.notNull(target, "The target object to evaluate is required");
try {
- // TODO context map
- return Ognl.getValue(expression, Collections.EMPTY_MAP, target);
+ Map context;
+ if (variables != null && variables.length > 0) {
+ context = new HashMap(variables.length);
+ } else {
+ context = Collections.EMPTY_MAP;
+ }
+ return Ognl.getValue(expression, context, target);
} catch (OgnlException e) {
if (e.getReason() != null && e.getReason() != e) {
// unwrap the OgnlException since the actual exception is wrapped inside it
diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/ognl/OgnlExpressionParser.java b/spring-binding/src/main/java/org/springframework/binding/expression/ognl/OgnlExpressionParser.java
index 49583209..e210bdcf 100644
--- a/spring-binding/src/main/java/org/springframework/binding/expression/ognl/OgnlExpressionParser.java
+++ b/spring-binding/src/main/java/org/springframework/binding/expression/ognl/OgnlExpressionParser.java
@@ -21,6 +21,7 @@ import ognl.OgnlRuntime;
import ognl.PropertyAccessor;
import org.springframework.binding.expression.Expression;
+import org.springframework.binding.expression.ExpressionVariable;
import org.springframework.binding.expression.ParserException;
import org.springframework.binding.expression.support.AbstractExpressionParser;
@@ -31,9 +32,10 @@ import org.springframework.binding.expression.support.AbstractExpressionParser;
*/
public class OgnlExpressionParser extends AbstractExpressionParser {
- protected Expression doParseExpression(String expressionString) throws ParserException {
+ protected Expression doParseExpression(String expressionString, Class expressionTargetType,
+ Class expectedEvaluationResultType, ExpressionVariable[] expressionVariables) throws ParserException {
try {
- return new OgnlExpression(Ognl.parseExpression(expressionString));
+ return new OgnlExpression(Ognl.parseExpression(expressionString), expressionVariables);
} catch (OgnlException e) {
throw new ParserException(expressionString, e);
}
diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/support/AbstractExpressionParser.java b/spring-binding/src/main/java/org/springframework/binding/expression/support/AbstractExpressionParser.java
index f2e20907..e62b9b95 100644
--- a/spring-binding/src/main/java/org/springframework/binding/expression/support/AbstractExpressionParser.java
+++ b/spring-binding/src/main/java/org/springframework/binding/expression/support/AbstractExpressionParser.java
@@ -80,19 +80,11 @@ public abstract class AbstractExpressionParser implements ExpressionParser {
this.expressionSuffix = expressionSuffix;
}
- public boolean isEvalExpressionString(String string) {
- return string.startsWith(expressionPrefix) && string.endsWith(expressionSuffix);
- }
-
- public String parseEvalExpressionString(String string) {
- return encloseInDelimitersIfNecessary(string);
- }
-
public Expression parseExpression(String expressionString, Class expressionTargetType,
Class expectedEvaluationResultType, ExpressionVariable[] expressionVariables) throws ParserException {
Assert.notNull(expressionString, "The expression string to parse is required");
- // TODO variables
- Expression[] expressions = parseExpressions(expressionString);
+ Expression[] expressions = parseExpressions(expressionString, expressionTargetType,
+ expectedEvaluationResultType, expressionVariables);
if (expressions.length == 1) {
return expressions[0];
} else {
@@ -100,14 +92,6 @@ public abstract class AbstractExpressionParser implements ExpressionParser {
}
}
- private String encloseInDelimitersIfNecessary(String expressionString) {
- if (isEvalExpressionString(expressionString)) {
- return expressionString;
- } else {
- return expressionPrefix + expressionString + expressionSuffix;
- }
- }
-
/**
* Helper that parses given expression string using the configured parser. The expression string can contain any
* number of expressions all contained in "${...}" markers. For instance: "foo${expr0}bar${expr1}". The static
@@ -117,7 +101,8 @@ public abstract class AbstractExpressionParser implements ExpressionParser {
* @return the parsed expressions
* @throws ParserException when the expressions cannot be parsed
*/
- private Expression[] parseExpressions(String expressionString) throws ParserException {
+ private Expression[] parseExpressions(String expressionString, Class expressionTargetType,
+ Class expectedEvaluationResultType, ExpressionVariable[] expressionVariables) throws ParserException {
List expressions = new LinkedList();
int startIdx = 0;
while (startIdx < expressionString.length()) {
@@ -147,7 +132,8 @@ public abstract class AbstractExpressionParser implements ExpressionParser {
+ getExpressionPrefix() + getExpressionSuffix() + "' at character " + prefixIndex, null);
} else {
String expr = expressionString.substring(prefixIndex + getExpressionPrefix().length(), suffixIndex);
- expressions.add(doParseExpression(expr));
+ expressions.add(doParseExpression(expr, expressionTargetType, expectedEvaluationResultType,
+ expressionVariables));
startIdx = suffixIndex + 1;
}
} else {
@@ -165,8 +151,9 @@ public abstract class AbstractExpressionParser implements ExpressionParser {
* Template method for parsing a filtered expression string. Subclasses should override.
* @param expressionString the expression string
* @return the parsed expression
- * @throws ParserException an exception occured during parsing
+ * @throws ParserException an exception occurred during parsing
*/
- protected abstract Expression doParseExpression(String expressionString) throws ParserException;
+ protected abstract Expression doParseExpression(String expressionString, Class expressionTargetType,
+ Class expectedEvaluationResultType, ExpressionVariable[] expressionVariables) throws ParserException;
}
\ No newline at end of file
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
new file mode 100644
index 00000000..656e49aa
--- /dev/null
+++ b/spring-binding/src/main/java/org/springframework/binding/message/MessageBuilder.java
@@ -0,0 +1,173 @@
+package org.springframework.binding.message;
+
+import java.util.Locale;
+
+import org.springframework.context.MessageSource;
+import org.springframework.context.MessageSourceResolvable;
+
+/**
+ * A convenient builder for building {@link MessageResolver} objects programmatically. Often used by model code such as
+ * validation logic to conveniently record validation messages. Supports the production of message resolvers that
+ * hard-code their message text, as well as message resolvers that retrieve their text from a
+ * {@link MessageSource message resource bundle}.
+ *
+ * Usage example:
+ *
+ *
+ * new MessageBuilder().error().source(this).code("mycode").args(new Object[] { arg1, arg2 }).defaultText("Fallback text")
+ * .build();
+ *
+ *
+ * @author Keith Donald
+ */
+public class MessageBuilder {
+
+ private Object source;
+
+ private String[] codes;
+
+ private Severity severity;
+
+ private Object[] args;
+
+ 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
+ */
+ public MessageBuilder info() {
+ severity = Severity.INFO;
+ return this;
+ }
+
+ /**
+ * Records that the message being built is a warning message.
+ * @return this, for fluent API usage
+ */
+ public MessageBuilder warning() {
+ severity = Severity.WARNING;
+ return this;
+ }
+
+ /**
+ * Records that the message being built is an error message.
+ * @return this, for fluent API usage
+ */
+ public MessageBuilder error() {
+ severity = Severity.ERROR;
+ return this;
+ }
+
+ /**
+ * Records that the message being built has a single argument.
+ * @param arg the message argument
+ * @return this, for fluent API usage
+ */
+ public MessageBuilder arg(Object arg) {
+ this.args = new Object[] { arg };
+ return this;
+ }
+
+ /**
+ * Records that the message being built has arguments.
+ * @param args the message arguments
+ * @return this, for fluent API usage
+ */
+ public MessageBuilder args(Object[] args) {
+ this.args = args;
+ 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.
+ * @param text the default text
+ * @return this, for fluent API usage
+ */
+ public MessageBuilder defaultText(String text) {
+ defaultText = text;
+ return this;
+ }
+
+ /**
+ * Builds the message that will be resolved. Called after the end of recording builder instructions.
+ * @return the built message resolver
+ */
+ public MessageResolver build() {
+ if (severity == null) {
+ severity = Severity.INFO;
+ }
+ if (codes == null && defaultText == null) {
+ 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);
+ }
+
+ private static class BuiltMessageResolver implements MessageResolver, MessageSourceResolvable {
+ private Object source;
+ private String[] codes;
+ private Severity severity;
+ private Object[] args;
+ private String defaultText;
+
+ public BuiltMessageResolver(Object source, String[] codes, Severity severity, Object[] args, String defaultText) {
+ this.source = source;
+ this.codes = codes;
+ this.severity = severity;
+ this.args = args;
+ this.defaultText = defaultText;
+ }
+
+ public Message resolveMessage(MessageSource messageSource, Locale locale) {
+ return new Message(source, messageSource.getMessage(this, locale), severity);
+ }
+
+ // implementing MessageSourceResolver
+
+ public String[] getCodes() {
+ return codes;
+ }
+
+ public Object[] getArguments() {
+ return args;
+ }
+
+ public String getDefaultMessage() {
+ return defaultText;
+ }
+ }
+
+}
diff --git a/spring-binding/src/main/java/org/springframework/binding/message/Messages.java b/spring-binding/src/main/java/org/springframework/binding/message/Messages.java
deleted file mode 100644
index ccb8c72f..00000000
--- a/spring-binding/src/main/java/org/springframework/binding/message/Messages.java
+++ /dev/null
@@ -1,225 +0,0 @@
-package org.springframework.binding.message;
-
-import java.util.Locale;
-
-import org.springframework.context.MessageSource;
-
-/**
- * A convenient factory for creating {@link MessageResolver} objects programmatically. Often used by model code such as
- * validation logic to conveniently record validation messages. Supports the production of "text" message resolvers that
- * hard-code their message text, as well as message resolvers that retrieve their text from a
- * {@link MessageSource message resource bundle}.
- *
- * @author Keith Donald
- */
-public class Messages implements MessageResolver {
-
- private Object source;
-
- private String code;
-
- private Severity severity;
-
- private Object[] args;
-
- private String defaultText;
-
- private Messages(Object source, String code, Severity severity, Object[] args, String defaultText) {
- this.source = source;
- this.code = code;
- this.severity = severity;
- this.args = args;
- this.defaultText = defaultText;
- }
-
- public Message resolveMessage(MessageSource messageSource, Locale locale) {
- if (messageSource != null && (code != null && code.length() > 0)) {
- return new Message(source, getMessageText(messageSource, locale), severity);
- } else {
- return new Message(source, defaultText, severity);
- }
- }
-
- /**
- * Creates a message resolver that creates a INFO {@link Message} with the text provided.
- * @param text the raw message text that will be used as-is
- * @return the message resolver
- */
- public static Messages text(String text) {
- return new Messages(null, null, Severity.INFO, null, text);
- }
-
- /**
- * Creates a message resolver that creates a {@link Message} with the text and severity provided.
- * @param text the raw message text that will be used as-is
- * @param severity the desired message severity
- * @return the message resolver
- */
- public static Messages text(String text, Severity severity) {
- return new Messages(null, null, severity, null, text);
- }
-
- /**
- * Creates a message resolver that creates a {@link Severity#INFO info} {@link Message message} with its text
- * resolved from a message bundle by using the provided message code.
- * @param code the message code
- * @return the message resolver
- */
- public static Messages info(String code) {
- return new Messages(null, code, Severity.INFO, null, null);
- }
-
- /**
- * Creates a message resolver that creates a {@link Severity#WARNING warning} {@link Message message} with its text
- * resolved from a message bundle by using the provided message code.
- * @param code the message code
- * @return the message resolver
- */
- public static Messages warning(String code) {
- return new Messages(null, code, Severity.WARNING, null, null);
- }
-
- /**
- * Creates a message resolver that creates a {@link Severity#ERROR error} {@link Message message} with its text
- * resolved from a message bundle by using the provided message code.
- * @param code the message code
- * @return the message resolver
- */
- public static Messages error(String code) {
- return new Messages(null, code, Severity.ERROR, null, null);
- }
-
- /**
- * Creates a message resolver that creates a {@link Severity#INFO info} {@link Message message} with its text
- * resolved from a message bundle by using the provided message code and message arguments.
- * @param code the message code
- * @param args the message arguments
- * @return the message resolver
- */
- public static Messages info(String code, Object[] args) {
- return new Messages(null, code, Severity.INFO, args, null);
- }
-
- /**
- * Creates a message resolver that creates a {@link Severity#WARNING warning} {@link Message message} with its text
- * resolved from a message bundle by using the provided message code and message arguments.
- * @param code the message code
- * @param args the message arguments
- * @return the message resolver
- */
- public static Messages warning(String code, Object[] args) {
- return new Messages(null, code, Severity.WARNING, args, null);
- }
-
- /**
- * Creates a message resolver that creates a {@link Severity#ERROR error} {@link Message message} with its text
- * resolved from a message bundle by using the provided message code and message arguments.
- * @param code the message code
- * @param args the message arguments
- * @return the message resolver
- */
- public static Messages error(String code, Object[] args) {
- return new Messages(null, code, Severity.ERROR, args, null);
- }
-
- /**
- * Creates a message resolver that creates a {@link Severity#INFO info} {@link Message message} from the source with
- * the text provided.
- * @param source the source of the message
- * @param text the message text
- * @return the message resolver
- */
- public static Messages text(Object source, String text) {
- return new Messages(source, null, Severity.INFO, null, text);
- }
-
- /**
- * Creates a message resolver that creates a {@link Message message} from the source with the text and severity
- * provided.
- * @param source the source of the message
- * @param text the message text
- * @param severity the message severity
- * @return the message resolver
- */
- public static Messages text(Object source, String text, Severity severity) {
- return new Messages(source, null, severity, null, text);
- }
-
- /**
- * Creates a message resolver that creates a {@link Severity#INFO info} {@link Message message} from the source with
- * its text resolved from a message bundle by using the provided message code.
- * @param source the source of the message
- * @param code the message code
- * @return the message resolver
- */
- public static Messages info(Object source, String code) {
- return new Messages(source, code, Severity.INFO, null, null);
- }
-
- /**
- * Creates a message resolver that creates a {@link Severity#WARNING warning} {@link Message message} from the
- * source with its text resolved from a message bundle by using the provided message code.
- * @param source the source of the message
- * @param code the message code
- * @return the message resolver
- */
- public static Messages warning(Object source, String code) {
- return new Messages(source, code, Severity.WARNING, null, null);
- }
-
- /**
- * Creates a message resolver that creates a {@link Severity#ERROR error} {@link Message message} from the source
- * with its text resolved from a message bundle by using the provided message code.
- * @param source the source of the message
- * @param code the message code
- * @return the message resolver
- */
- public static Messages error(Object source, String code) {
- return new Messages(source, code, Severity.ERROR, null, null);
- }
-
- /**
- * Creates a message resolver that creates a {@link Severity#INFO info} {@link Message message} from the source with
- * its text resolved from a message bundle by using the provided message code and message arguments.
- * @param source the source of the message
- * @param code the message code
- * @param args the message arguments
- * @return the message resolver
- */
- public static Messages info(Object source, String code, Object[] args) {
- return new Messages(source, code, Severity.INFO, args, null);
- }
-
- /**
- * Creates a message resolver that creates a {@link Severity#WARNING warning} {@link Message message} from the
- * source with its text resolved from a message bundle by using the provided message code and message arguments.
- * @param source the source of the message
- * @param code the message code
- * @param args the message arguments
- * @return the message resolver
- */
- public static Messages warning(Object source, String code, Object[] args) {
- return new Messages(source, code, Severity.WARNING, args, null);
- }
-
- /**
- * Creates a message resolver that creates a {@link Severity#ERROR error} {@link Message message} from the source
- * with its text resolved from a message bundle by using the provided message code and message arguments.
- * @param source the source of the message
- * @param code the message code
- * @param args the message arguments
- * @return the message resolver
- */
- public static Messages error(Object source, String code, Object[] args) {
- return new Messages(source, code, Severity.ERROR, args, null);
- }
-
- private String getMessageText(MessageSource source, Locale locale) {
- if (defaultText == null) {
- return source.getMessage(code, args, locale);
- } else {
- return source.getMessage(code, args, defaultText, locale);
- }
- }
-
-}
diff --git a/spring-binding/src/test/java/org/springframework/binding/expression/el/ELExpressionParserTests.java b/spring-binding/src/test/java/org/springframework/binding/expression/el/ELExpressionParserTests.java
index a8938d41..6dfbceb6 100644
--- a/spring-binding/src/test/java/org/springframework/binding/expression/el/ELExpressionParserTests.java
+++ b/spring-binding/src/test/java/org/springframework/binding/expression/el/ELExpressionParserTests.java
@@ -2,6 +2,7 @@ package org.springframework.binding.expression.el;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
import javax.el.ELContext;
import javax.el.ELResolver;
@@ -13,6 +14,7 @@ import junit.framework.TestCase;
import org.jboss.el.ExpressionFactoryImpl;
import org.springframework.binding.expression.Expression;
import org.springframework.binding.expression.ExpressionVariable;
+import org.springframework.binding.expression.ParserException;
public class ELExpressionParserTests extends TestCase {
@@ -40,6 +42,20 @@ public class ELExpressionParserTests extends TestCase {
}
}
+ public void testParseEvalExpressionExpectedResultTypeNull() {
+ String expressionString = "#{value}";
+ Class expressionTargetType = null;
+ Class expectedEvaluationResultType = null;
+ ExpressionVariable[] expressionVariables = null;
+ try {
+ parser.parseExpression(expressionString, expressionTargetType, expectedEvaluationResultType,
+ expressionVariables);
+ fail("Should have failed");
+ } catch (ParserException e) {
+
+ }
+ }
+
public void testParseEvalExpression() {
String expressionString = "#{value}";
Class expressionTargetType = TestBean.class;
@@ -51,15 +67,31 @@ public class ELExpressionParserTests extends TestCase {
assertEquals("foo", exp.getValue(target));
}
- public void testParseLiteralExpressionStringAsEvalExpression() {
- String expressionString = "value";
- Class expressionTargetType = TestBean.class;
- Class expectedEvaluationResultType = String.class;
+ public void testParseEvalExpressionNoTargetType() {
+ String expressionString = "#{value}";
+ Class expressionTargetType = null;
+ Class expectedEvaluationResultType = Object.class;
ExpressionVariable[] expressionVariables = null;
- Expression exp = parser.parseExpression(parser.parseEvalExpressionString(expressionString),
- expressionTargetType, expectedEvaluationResultType, expressionVariables);
- TestBean target = new TestBean();
- assertEquals("foo", exp.getValue(target));
+ try {
+ parser.parseExpression(expressionString, expressionTargetType, expectedEvaluationResultType,
+ expressionVariables);
+ fail("Should have failed");
+ } catch (ParserException e) {
+
+ }
+ }
+
+ public void testParseEvalExpressionNotRegisteredTargetType() {
+ String expressionString = "#{value}";
+ Class expressionTargetType = Map.class;
+ Class expectedEvaluationResultType = Object.class;
+ ExpressionVariable[] expressionVariables = null;
+ try {
+ parser.parseExpression(expressionString, expressionTargetType, expectedEvaluationResultType,
+ expressionVariables);
+ fail("Should have failed");
+ } catch (ParserException e) {
+ }
}
public void testParseLiteralExpression() {
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
new file mode 100644
index 00000000..d769a549
--- /dev/null
+++ b/spring-binding/src/test/java/org/springframework/binding/message/DefaultMessageContextFactoryTests.java
@@ -0,0 +1,92 @@
+package org.springframework.binding.message;
+
+import java.io.Serializable;
+import java.util.Locale;
+
+import junit.framework.TestCase;
+
+import org.springframework.context.support.StaticMessageSource;
+
+public class DefaultMessageContextFactoryTests extends TestCase {
+ private DefaultMessageContextFactory factory;
+
+ protected void setUp() {
+ StaticMessageSource messageSource = new StaticMessageSource();
+ factory = new DefaultMessageContextFactory(messageSource);
+ messageSource.addMessage("message", Locale.getDefault(), "Hello world resolved!");
+ messageSource.addMessage("argmessage", Locale.getDefault(), "Hello world {0}!");
+ }
+
+ public void testCreateMessageContext() {
+ MessageContext context = factory.createMessageContext();
+ context.addMessage(new MessageBuilder().defaultText("Hello world!").build());
+ Message[] messages = context.getMessages();
+ assertEquals(1, messages.length);
+ assertEquals("Hello world!", messages[0].getText());
+ assertEquals(Severity.INFO, messages[0].getSeverity());
+ assertEquals(null, messages[0].getSource());
+ }
+
+ public void testResolveMessage() {
+ MessageContext context = factory.createMessageContext();
+ context.addMessage(new MessageBuilder().warning().source(this).code("message").build());
+ Message[] messages = context.getMessages(this);
+ assertEquals(1, messages.length);
+ assertEquals("Hello world resolved!", messages[0].getText());
+ assertEquals(Severity.WARNING, messages[0].getSeverity());
+ assertEquals(this, messages[0].getSource());
+ }
+
+ public void testResolveMessageDefaultText() {
+ MessageContext context = factory.createMessageContext();
+ context.addMessage(new MessageBuilder().error().code("bogus").defaultText("Hello world fallback!").build());
+ Message[] messages = context.getMessages(null);
+ assertEquals(1, messages.length);
+ assertEquals("Hello world fallback!", messages[0].getText());
+ assertEquals(Severity.ERROR, messages[0].getSeverity());
+ assertEquals(null, messages[0].getSource());
+ assertTrue(context instanceof StateManageableMessageContext);
+ }
+
+ public void testResolveMessageWithArgs() {
+ MessageContext context = factory.createMessageContext();
+ context.addMessage(new MessageBuilder().error().source(this).code("argmessage").arg("Keith").defaultText(
+ "Hello world fallback!").build());
+ Message[] messages = context.getMessages(this);
+ assertEquals(1, messages.length);
+ assertEquals("Hello world Keith!", messages[0].getText());
+ assertEquals(Severity.ERROR, messages[0].getSeverity());
+ assertEquals(this, messages[0].getSource());
+ assertTrue(context instanceof StateManageableMessageContext);
+ }
+
+ 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());
+ Message[] messages = context.getMessages(this);
+ assertEquals(1, messages.length);
+ assertEquals("Hello world Keith!", messages[0].getText());
+ assertEquals(Severity.ERROR, messages[0].getSeverity());
+ assertEquals(this, messages[0].getSource());
+ assertTrue(context instanceof StateManageableMessageContext);
+ }
+
+ public void testSaveRestoreMessages() {
+ MessageContext context = factory.createMessageContext();
+ context.addMessage(new MessageBuilder().defaultText("Info").build());
+ context.addMessage(new MessageBuilder().error().defaultText("Error").build());
+ context.addMessage(new MessageBuilder().warning().source(this).code("message").build());
+ assertEquals(2, context.getMessages(null).length);
+ assertEquals(1, context.getMessages(this).length);
+ assertTrue(context instanceof StateManageableMessageContext);
+ StateManageableMessageContext manageable = (StateManageableMessageContext) context;
+ Serializable messages = manageable.createMessagesMemento();
+ context = factory.createMessageContext();
+ assertEquals(0, context.getMessages().length);
+ manageable = (StateManageableMessageContext) context;
+ manageable.restoreMessages(messages);
+ assertEquals(2, context.getMessages(null).length);
+ assertEquals(1, context.getMessages(this).length);
+ }
+}