Introduce MessageCodeFormatter abstraction
This commit refactors changes introduced in 21760a8 as follows:
- Introduce top-level MessageCodeFormatter interface and
DefaultMessageCodesResolver#setMessageCodeFormatter property to allow
for user-defined message code formatting strategies
- Rename DefaultMessageCodesResolver.Style enum => DMCR.Format
- Refactor DefaultMessageCodesResolver.Format to implement the new
MessageCodeFormatter interface
The result is that users have convenient access to common formatting
strategies via the Format enum, while retaining the flexibility to
provide their own custom MessageCodeFormatter implementation if desired.
See DefaultMessageCodesResolverTests#shouldSupport*Format tests for
usage examples.
Issue: SPR-9707
This commit is contained in:
@@ -29,7 +29,8 @@ import org.springframework.util.StringUtils;
|
||||
* Default implementation of the {@link MessageCodesResolver} interface.
|
||||
*
|
||||
* <p>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}):
|
||||
* <ul>
|
||||
* <li>1.: code + "." + object name
|
||||
* <li>2.: code
|
||||
@@ -73,8 +74,9 @@ import org.springframework.util.StringUtils;
|
||||
* </ul>
|
||||
*
|
||||
* <p>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}.
|
||||
*
|
||||
* <p>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.
|
||||
* <p>Default is {@link Style#PREFIX_ERROR_CODE}.
|
||||
* Specify the format for message codes built by this resolver.
|
||||
* <p>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<String> 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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user