diff --git a/spring-context/src/main/java/org/springframework/validation/DefaultMessageCodesResolver.java b/spring-context/src/main/java/org/springframework/validation/DefaultMessageCodesResolver.java
index 44d8b65c72..7c1a084be2 100644
--- a/spring-context/src/main/java/org/springframework/validation/DefaultMessageCodesResolver.java
+++ b/spring-context/src/main/java/org/springframework/validation/DefaultMessageCodesResolver.java
@@ -29,7 +29,8 @@ import org.springframework.util.StringUtils;
* Default implementation of the {@link MessageCodesResolver} interface.
*
*
Will create two message codes for an object error, in the following order (when
- * using the {@link Style#PREFIX_ERROR_CODE prefixed} {@link #setStyle(Style) style}):
+ * using the {@link Format#PREFIX_ERROR_CODE prefixed}
+ * {@link #setMessageCodeFormatter(MessageCodeFormatter) formatter}):
*
* - 1.: code + "." + object name
*
- 2.: code
@@ -73,8 +74,9 @@ import org.springframework.util.StringUtils;
*
*
* By default the {@code errorCode}s will be placed at the beginning of constructed
- * message strings. The {@link #setStyle(Style) style} property can be used to specify
- * alternative {@link Style styles} of concatination.
+ * message strings. The {@link #setMessageCodeFormatter(MessageCodeFormatter)
+ * messageCodeFormatter} property can be used to specify an alternative concatenation
+ * {@link MessageCodeFormatter format}.
*
*
In order to group all codes into a specific category within your resource bundles,
* e.g. "validation.typeMismatch.name" instead of the default "typeMismatch.name",
@@ -82,6 +84,7 @@ import org.springframework.util.StringUtils;
*
* @author Juergen Hoeller
* @author Phillip Webb
+ * @author Chris Beams
* @since 1.0.1
*/
@SuppressWarnings("serial")
@@ -92,12 +95,12 @@ public class DefaultMessageCodesResolver implements MessageCodesResolver, Serial
*/
public static final String CODE_SEPARATOR = ".";
- private static final Style DEFAULT_STYLE = Style.PREFIX_ERROR_CODE;
+ private static final MessageCodeFormatter DEFAULT_FORMATTER = Format.PREFIX_ERROR_CODE;
private String prefix = "";
- private Style style = DEFAULT_STYLE;
+ private MessageCodeFormatter formatter = DEFAULT_FORMATTER;
/**
@@ -110,11 +113,12 @@ public class DefaultMessageCodesResolver implements MessageCodesResolver, Serial
}
/**
- * Specify the style of message code that will be built by this resolver.
- *
Default is {@link Style#PREFIX_ERROR_CODE}.
+ * Specify the format for message codes built by this resolver.
+ *
The default is {@link Format#PREFIX_ERROR_CODE}.
+ * @since 3.2
*/
- public void setStyle(Style style) {
- this.style = (style == null ? DEFAULT_STYLE : style);
+ public void setMessageCodeFormatter(MessageCodeFormatter formatter) {
+ this.formatter = (formatter == null ? DEFAULT_FORMATTER : formatter);
}
/**
@@ -163,29 +167,7 @@ public class DefaultMessageCodesResolver implements MessageCodesResolver, Serial
}
private void addCode(Collection codeList, String errorCode, String objectName, String field) {
- String code = getCode(errorCode, objectName, field);
- codeList.add(postProcessMessageCode(code));
- }
-
- private String getCode(String errorCode, String objectName, String field) {
- switch (this.style) {
- case PREFIX_ERROR_CODE:
- return toDelimitedString(errorCode, objectName, field);
- case POSTFIX_ERROR_CODE:
- return toDelimitedString(objectName, field, errorCode);
- }
- throw new IllegalStateException("Unknown style " + this.style);
- }
-
- private String toDelimitedString(String... elements) {
- StringBuilder rtn = new StringBuilder();
- for (String element : elements) {
- if(StringUtils.hasLength(element)) {
- rtn.append(rtn.length() == 0 ? "" : CODE_SEPARATOR);
- rtn.append(element);
- }
- }
- return rtn.toString();
+ codeList.add(postProcessMessageCode(this.formatter.format(errorCode, objectName, field)));
}
/**
@@ -222,21 +204,51 @@ public class DefaultMessageCodesResolver implements MessageCodesResolver, Serial
/**
- * The various styles that can be used to construct message codes.
+ * Common message code formats.
+ *
+ * @author Phil Webb
+ * @author Chris Beams
+ * @since 3.2
+ * @see MessageCodeFormatter
+ * @see DefaultMessageCodesResolver#setMessageCodeFormatter(MessageCodeFormatter)
*/
- public static enum Style {
+ public static enum Format implements MessageCodeFormatter {
/**
- * Prefix the error code at the beginning of the generated message code. eg:
+ * Prefix the error code at the beginning of the generated message code. e.g.:
* {@code errorCode + "." + object name + "." + field}
*/
- PREFIX_ERROR_CODE,
+ PREFIX_ERROR_CODE {
+ public String format(String errorCode, String objectName, String field) {
+ return toDelimitedString(errorCode, objectName, field);
+ }
+ },
/**
- * Postfix the error code at the end of the generated message code. eg:
+ * Postfix the error code at the end of the generated message code. e.g.:
* {@code object name + "." + field + "." + errorCode}
*/
- POSTFIX_ERROR_CODE
+ POSTFIX_ERROR_CODE {
+ public String format(String errorCode, String objectName, String field) {
+ return toDelimitedString(objectName, field, errorCode);
+ }
+ };
+
+ /**
+ * Concatenate the given elements, delimiting each with
+ * {@link DefaultMessageCodesResolver#CODE_SEPARATOR}, skipping zero-length or
+ * null elements altogether.
+ */
+ public static String toDelimitedString(String... elements) {
+ StringBuilder rtn = new StringBuilder();
+ for (String element : elements) {
+ if(StringUtils.hasLength(element)) {
+ rtn.append(rtn.length() == 0 ? "" : CODE_SEPARATOR);
+ rtn.append(element);
+ }
+ }
+ return rtn.toString();
+ }
}
}
diff --git a/spring-context/src/main/java/org/springframework/validation/MessageCodeFormatter.java b/spring-context/src/main/java/org/springframework/validation/MessageCodeFormatter.java
new file mode 100644
index 0000000000..0ce9bdd5f7
--- /dev/null
+++ b/spring-context/src/main/java/org/springframework/validation/MessageCodeFormatter.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.validation;
+
+/**
+ * A strategy interface for formatting message codes.
+ *
+ * @author Chris Beams
+ * @since 3.2
+ * @see DefaultMessageCodesResolver
+ */
+public interface MessageCodeFormatter {
+
+ /**
+ * Build and return a message code consisting of the given fields, usually delimited
+ * by {@link DefaultMessageCodesResolver#CODE_SEPARATOR}.
+ * @param errorCode e.g.: "typeMismatch"
+ * @param objectName e.g.: "user"
+ * @param field e.g. "age"
+ * @return concatenated message code, e.g.: "typeMismatch.user.age"
+ * @see DefaultMessageCodesResolver.Format
+ */
+ String format(String errorCode, String objectName, String field);
+}
\ No newline at end of file
diff --git a/spring-context/src/test/java/org/springframework/validation/DefaultMessageCodesResolverTests.java b/spring-context/src/test/java/org/springframework/validation/DefaultMessageCodesResolverTests.java
index 18bb109b5a..db86c2384d 100644
--- a/spring-context/src/test/java/org/springframework/validation/DefaultMessageCodesResolverTests.java
+++ b/spring-context/src/test/java/org/springframework/validation/DefaultMessageCodesResolverTests.java
@@ -22,7 +22,7 @@ import static org.junit.Assert.assertThat;
import org.junit.Test;
import org.springframework.beans.TestBean;
-import org.springframework.validation.DefaultMessageCodesResolver.Style;
+import org.springframework.validation.DefaultMessageCodesResolver.Format;
/**
* Tests for {@link DefaultMessageCodesResolver}.
@@ -123,8 +123,8 @@ public class DefaultMessageCodesResolverTests {
}
@Test
- public void shouldSupportPostfixStyle() throws Exception {
- resolver.setStyle(Style.POSTFIX_ERROR_CODE);
+ public void shouldSupportPostfixFormat() throws Exception {
+ resolver.setMessageCodeFormatter(Format.POSTFIX_ERROR_CODE);
String[] codes = resolver.resolveMessageCodes("errorCode", "objectName");
assertThat(codes, is(equalTo(new String[] {
"objectName.errorCode",
@@ -132,8 +132,8 @@ public class DefaultMessageCodesResolverTests {
}
@Test
- public void shouldSupportFieldPostfixStyle() throws Exception {
- resolver.setStyle(Style.POSTFIX_ERROR_CODE);
+ public void shouldSupportFieldPostfixFormat() throws Exception {
+ resolver.setMessageCodeFormatter(Format.POSTFIX_ERROR_CODE);
String[] codes = resolver.resolveMessageCodes("errorCode", "objectName", "field",
TestBean.class);
assertThat(codes, is(equalTo(new String[] {
@@ -142,4 +142,18 @@ public class DefaultMessageCodesResolverTests {
"org.springframework.beans.TestBean.errorCode",
"errorCode" })));
}
+
+ @Test
+ public void shouldSupportCustomFormat() throws Exception {
+ resolver.setMessageCodeFormatter(new MessageCodeFormatter() {
+ public String format(String errorCode, String objectName, String field) {
+ return DefaultMessageCodesResolver.Format.toDelimitedString(
+ "CUSTOM-" + errorCode, objectName, field);
+ }
+ });
+ String[] codes = resolver.resolveMessageCodes("errorCode", "objectName");
+ assertThat(codes, is(equalTo(new String[] {
+ "CUSTOM-errorCode.objectName",
+ "CUSTOM-errorCode" })));
+ }
}