removed 3.1 feature classes
This commit is contained in:
parent
2781b876d2
commit
a59d205b36
|
|
@ -1,42 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2004-2009 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.context.alert;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Communicates an event of interest to the user.
|
|
||||||
* For example, an alert may inform a user of a application a business rule was violated.
|
|
||||||
* @author Keith Donald
|
|
||||||
* @since 3.0
|
|
||||||
*/
|
|
||||||
public interface Alert {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The code uniquely identifying this kind of alert; for example, "weakPassword".
|
|
||||||
* May be used as a key to lookup additional alert details.
|
|
||||||
*/
|
|
||||||
public String getCode();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The level of impact this alert has on the user.
|
|
||||||
*/
|
|
||||||
public Severity getSeverity();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The localized message to display to the user; for example, "Please enter a stronger password".
|
|
||||||
*/
|
|
||||||
public String getMessage();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2004-2009 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.context.alert;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A context for adding and getting alerts for display in a user interface.
|
|
||||||
* @author Keith Donald
|
|
||||||
* @since 3.0
|
|
||||||
*/
|
|
||||||
public interface AlertContext {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return all alerts in this context indexed by the UI element they are associated with.
|
|
||||||
* @return the message map
|
|
||||||
*/
|
|
||||||
public Map<String, List<Alert>> getAlerts();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all alerts on the UI element provided.
|
|
||||||
* Returns an empty list if no alerts have been added for the element.
|
|
||||||
* Alerts are returned in the order they were added.
|
|
||||||
* @param element the id of the element to lookup alerts against
|
|
||||||
*/
|
|
||||||
public List<Alert> getAlerts(String element);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add an alert to this context.
|
|
||||||
* @param the element this alert is associated with
|
|
||||||
* @param alert the alert to add
|
|
||||||
*/
|
|
||||||
public void add(String element, Alert alert);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,104 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2004-2009 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.context.alert;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A static factory for conveniently constructing Alerts.
|
|
||||||
* Usage example:
|
|
||||||
* <pre>
|
|
||||||
* import static org.springframework.ui.alert.Alerts.*;
|
|
||||||
*
|
|
||||||
* public void example() {
|
|
||||||
* info("An info alert");
|
|
||||||
* warning("A warning alert");
|
|
||||||
* error("An error alert");
|
|
||||||
* fatal("A fatal alert");
|
|
||||||
* }
|
|
||||||
* </pre>
|
|
||||||
* @author Keith Donald
|
|
||||||
* @since 3.0
|
|
||||||
*/
|
|
||||||
public final class Alerts {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new info alert.
|
|
||||||
* @param message the alert message
|
|
||||||
* @return the info alert
|
|
||||||
* @see Severity#INFO
|
|
||||||
*/
|
|
||||||
public static Alert info(String message) {
|
|
||||||
return new GenericAlert(Severity.INFO, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new warning alert.
|
|
||||||
* @param message the alert message
|
|
||||||
* @return the info alert
|
|
||||||
* @see Severity#WARNING
|
|
||||||
*/
|
|
||||||
public static Alert warning(String message) {
|
|
||||||
return new GenericAlert(Severity.WARNING, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new error alert.
|
|
||||||
* @param message the alert message
|
|
||||||
* @return the info alert
|
|
||||||
* @see Severity#ERROR
|
|
||||||
*/
|
|
||||||
public static Alert error(String message) {
|
|
||||||
return new GenericAlert(Severity.ERROR, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new fatal alert.
|
|
||||||
* @param message the alert message
|
|
||||||
* @return the info alert
|
|
||||||
* @see Severity#FATAL
|
|
||||||
*/
|
|
||||||
public static Alert fatal(String message) {
|
|
||||||
return new GenericAlert(Severity.FATAL, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class GenericAlert implements Alert {
|
|
||||||
|
|
||||||
private Severity severity;
|
|
||||||
|
|
||||||
private String message;
|
|
||||||
|
|
||||||
public GenericAlert(Severity severity, String message) {
|
|
||||||
this.severity = severity;
|
|
||||||
this.message = message;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCode() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Severity getSeverity() {
|
|
||||||
return severity;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getMessage() {
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
return getSeverity() + ": " + getMessage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2004-2009 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.context.alert;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The set of alert severities.
|
|
||||||
* @author Keith Donald
|
|
||||||
* @since 3.0
|
|
||||||
* @see Alert
|
|
||||||
*/
|
|
||||||
public enum Severity {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The "Informational" severity.
|
|
||||||
* Indicates a successful operation or result.
|
|
||||||
*/
|
|
||||||
INFO,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The "Warning" severity.
|
|
||||||
* Indicates there is a minor problem, or to inform the user of possible misuse,
|
|
||||||
* or to indicate a problem may arise in the future.
|
|
||||||
*/
|
|
||||||
WARNING,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The "Error" severity.
|
|
||||||
* Indicates a significant problem like a business rule violation.
|
|
||||||
*/
|
|
||||||
ERROR,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The "Fatal" severity.
|
|
||||||
* Indicates a fatal problem like a system error or runtime exception.
|
|
||||||
*/
|
|
||||||
FATAL
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
/**
|
|
||||||
* A general-purpose Alerting API to communicate events of interest.
|
|
||||||
*/
|
|
||||||
package org.springframework.context.alert;
|
|
||||||
|
|
||||||
|
|
@ -1,66 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2004-2009 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.context.alert.support;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.springframework.context.alert.Alert;
|
|
||||||
import org.springframework.context.alert.AlertContext;
|
|
||||||
import org.springframework.core.style.ToStringCreator;
|
|
||||||
import org.springframework.util.CachingMapDecorator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The default alert context implementation.
|
|
||||||
* @author Keith Donald
|
|
||||||
* @since 3.0
|
|
||||||
*/
|
|
||||||
public class DefaultAlertContext implements AlertContext {
|
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
|
||||||
private Map<String, List<Alert>> alerts = new CachingMapDecorator<String, List<Alert>>(new LinkedHashMap<String, List<Alert>>()) {
|
|
||||||
protected List<Alert> create(String element) {
|
|
||||||
return new ArrayList<Alert>();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// implementing AlertContext
|
|
||||||
|
|
||||||
public Map<String, List<Alert>> getAlerts() {
|
|
||||||
return Collections.unmodifiableMap(alerts);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Alert> getAlerts(String element) {
|
|
||||||
List<Alert> messages = alerts.get(element);
|
|
||||||
if (messages.isEmpty()) {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
return Collections.unmodifiableList(messages);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void add(String element, Alert alert) {
|
|
||||||
List<Alert> alerts = this.alerts.get(element);
|
|
||||||
alerts.add(alert);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
return new ToStringCreator(this).append("alerts", alerts).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
/**
|
|
||||||
* AlertContext implementation suitable for use in most environments.
|
|
||||||
*/
|
|
||||||
package org.springframework.context.alert.support;
|
|
||||||
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2004-2009 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.context.message;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A factory for a default message to return if no message could be resolved.
|
|
||||||
* Allows the message String to be created lazily, only when it is needed.
|
|
||||||
* @author Keith Donald
|
|
||||||
* @since 3.0
|
|
||||||
* @see MessageBuilder
|
|
||||||
*/
|
|
||||||
public interface DefaultMessageFactory {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create the default message.
|
|
||||||
*/
|
|
||||||
String createDefaultMessage();
|
|
||||||
}
|
|
||||||
|
|
@ -1,153 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2004-2009 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.context.message;
|
|
||||||
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.springframework.context.MessageSource;
|
|
||||||
import org.springframework.context.MessageSourceResolvable;
|
|
||||||
import org.springframework.context.NoSuchMessageException;
|
|
||||||
import org.springframework.core.style.ToStringCreator;
|
|
||||||
import org.springframework.expression.AccessException;
|
|
||||||
import org.springframework.expression.EvaluationContext;
|
|
||||||
import org.springframework.expression.EvaluationException;
|
|
||||||
import org.springframework.expression.Expression;
|
|
||||||
import org.springframework.expression.ExpressionParser;
|
|
||||||
import org.springframework.expression.ParseException;
|
|
||||||
import org.springframework.expression.ParserContext;
|
|
||||||
import org.springframework.expression.PropertyAccessor;
|
|
||||||
import org.springframework.expression.TypedValue;
|
|
||||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
|
||||||
|
|
||||||
final class DefaultMessageResolver implements MessageResolver, MessageSourceResolvable {
|
|
||||||
|
|
||||||
private String[] codes;
|
|
||||||
|
|
||||||
private Map<String, Object> args;
|
|
||||||
|
|
||||||
private DefaultMessageFactory defaultMessageFactory;
|
|
||||||
|
|
||||||
private ExpressionParser expressionParser;
|
|
||||||
|
|
||||||
public DefaultMessageResolver(String[] codes, Map<String, Object> args,
|
|
||||||
DefaultMessageFactory defaultMessageFactory, ExpressionParser expressionParser) {
|
|
||||||
this.codes = codes;
|
|
||||||
this.args = args;
|
|
||||||
this.defaultMessageFactory = defaultMessageFactory;
|
|
||||||
this.expressionParser = expressionParser;
|
|
||||||
}
|
|
||||||
|
|
||||||
// implementing MessageResolver
|
|
||||||
|
|
||||||
public String resolveMessage(MessageSource messageSource, Locale locale) {
|
|
||||||
if (messageSource == null) {
|
|
||||||
if (defaultMessageFactory != null) {
|
|
||||||
return defaultMessageFactory.createDefaultMessage();
|
|
||||||
} else {
|
|
||||||
throw new MessageResolutionException(
|
|
||||||
"Unable to resolve message; MessagSource argument is null and no defaultMessage is configured");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
String messageString;
|
|
||||||
try {
|
|
||||||
messageString = messageSource.getMessage(this, locale);
|
|
||||||
} catch (NoSuchMessageException e) {
|
|
||||||
throw new MessageResolutionException("Unable to resolve message in" + messageSource, e);
|
|
||||||
}
|
|
||||||
Expression message;
|
|
||||||
try {
|
|
||||||
message = expressionParser.parseExpression(messageString, ParserContext.TEMPLATE_EXPRESSION);
|
|
||||||
} catch (ParseException e) {
|
|
||||||
throw new MessageResolutionException("Failed to parse message expression", e);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
StandardEvaluationContext context = new StandardEvaluationContext();
|
|
||||||
context.setRootObject(args);
|
|
||||||
context.addPropertyAccessor(new MessageArgumentAccessor(messageSource, locale));
|
|
||||||
return (String) message.getValue(context);
|
|
||||||
} catch (EvaluationException e) {
|
|
||||||
throw new MessageResolutionException("Failed to evaluate message expression '"
|
|
||||||
+ message.getExpressionString() + "' to generate final message text", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// implementing MessageSourceResolver
|
|
||||||
|
|
||||||
public String[] getCodes() {
|
|
||||||
return codes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object[] getArguments() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDefaultMessage() {
|
|
||||||
return defaultMessageFactory.createDefaultMessage();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
return new ToStringCreator(this).append("codes", codes).append("args", args).append("defaultMessageFactory",
|
|
||||||
defaultMessageFactory).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
static class MessageArgumentAccessor implements PropertyAccessor {
|
|
||||||
|
|
||||||
private MessageSource messageSource;
|
|
||||||
|
|
||||||
private Locale locale;
|
|
||||||
|
|
||||||
public MessageArgumentAccessor(MessageSource messageSource, Locale locale) {
|
|
||||||
this.messageSource = messageSource;
|
|
||||||
this.locale = locale;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean canRead(EvaluationContext context, Object target, String name) throws AccessException {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TypedValue read(EvaluationContext context, Object target, String name) throws AccessException {
|
|
||||||
Map map = (Map) target;
|
|
||||||
Object o = map.get(name);
|
|
||||||
if (o == null) {
|
|
||||||
throw new AccessException("No message argument named '" + name
|
|
||||||
+ "' is defined in the argument map; arguments available are " + map.keySet(), null);
|
|
||||||
}
|
|
||||||
if (o instanceof MessageSourceResolvable) {
|
|
||||||
String message = messageSource.getMessage((MessageSourceResolvable) o, locale);
|
|
||||||
return new TypedValue(message);
|
|
||||||
} else {
|
|
||||||
return new TypedValue(o);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean canWrite(EvaluationContext context, Object target, String name) throws AccessException {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void write(EvaluationContext context, Object target, String name, Object newValue)
|
|
||||||
throws AccessException {
|
|
||||||
throw new UnsupportedOperationException("Should not be called");
|
|
||||||
}
|
|
||||||
|
|
||||||
public Class[] getSpecificTargetClasses() {
|
|
||||||
return new Class[] { Map.class };
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,148 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2004-2009 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.context.message;
|
|
||||||
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
import org.springframework.context.MessageSource;
|
|
||||||
import org.springframework.context.i18n.LocaleContextHolder;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds a localized message for display in a user interface.
|
|
||||||
* Allows convenient specification of the codes to try to resolve the message.
|
|
||||||
* Also supports named arguments that can inserted into a message template using eval #{expressions}.
|
|
||||||
* <p>
|
|
||||||
* Usage example:
|
|
||||||
* <pre>
|
|
||||||
* String message = new MessageBuilder(messageSource).
|
|
||||||
* code("invalidFormat").
|
|
||||||
* arg("label", new ResolvableArgument("mathForm.decimalField")).
|
|
||||||
* arg("format", "#,###.##").
|
|
||||||
* defaultMessage("The decimal field must be in format #,###.##").
|
|
||||||
* build();
|
|
||||||
* </pre>
|
|
||||||
* Example messages.properties loaded by the MessageSource:
|
|
||||||
* <pre>
|
|
||||||
* invalidFormat=The #{label} must be in format #{format}.
|
|
||||||
* mathForm.decimalField=Decimal Field
|
|
||||||
* </pre>
|
|
||||||
* @author Keith Donald
|
|
||||||
* @since 3.0
|
|
||||||
* @see #code(String)
|
|
||||||
* @see #arg(String, Object)
|
|
||||||
* @see #defaultMessage(String)
|
|
||||||
* @see #locale(Locale)
|
|
||||||
*/
|
|
||||||
public class MessageBuilder {
|
|
||||||
|
|
||||||
private MessageSource messageSource;
|
|
||||||
|
|
||||||
private Locale locale;
|
|
||||||
|
|
||||||
private MessageResolverBuilder messageResolverBuilder = new MessageResolverBuilder();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new MessageBuilder that builds messages from message templates defined in the MessageSource
|
|
||||||
* @param messageSource the message source
|
|
||||||
*/
|
|
||||||
public MessageBuilder(MessageSource messageSource) {
|
|
||||||
this.messageSource = messageSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a code that will be tried to lookup the message template used to create the localized message.
|
|
||||||
* Successive calls to this method add additional codes.
|
|
||||||
* Codes are tried in the order they are added.
|
|
||||||
* @param code a message code to try
|
|
||||||
* @return this, for fluent API usage
|
|
||||||
*/
|
|
||||||
public MessageBuilder code(String code) {
|
|
||||||
messageResolverBuilder.code(code);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add an argument to insert into the message.
|
|
||||||
* Named arguments are inserted by eval #{expressions} denoted within the message template.
|
|
||||||
* For example, the value of the 'format' argument would be inserted where a corresponding #{format} expression is defined in the message template.
|
|
||||||
* Successive calls to this method add additional arguments.
|
|
||||||
* May also add {@link ResolvableArgument resolvable arguments} whose values are resolved against the MessageSource.
|
|
||||||
* @param name the argument name
|
|
||||||
* @param value the argument value
|
|
||||||
* @return this, for fluent API usage
|
|
||||||
* @see ResolvableArgument
|
|
||||||
*/
|
|
||||||
public MessageBuilder arg(String name, Object value) {
|
|
||||||
messageResolverBuilder.arg(name, value);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the default message.
|
|
||||||
* If there are no codes to try, this will be used as the message.
|
|
||||||
* If there are codes to try but none of those resolve to a message, this will be used as the message.
|
|
||||||
* @param message the default text
|
|
||||||
* @return this, for fluent API usage
|
|
||||||
*/
|
|
||||||
public MessageBuilder defaultMessage(String message) {
|
|
||||||
messageResolverBuilder.defaultMessage(message);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the default message.
|
|
||||||
* If there are no codes to try, this will be used as the message.
|
|
||||||
* If there are codes to try but none of those resolve to a message, this will be used as the message.
|
|
||||||
* @param message the default text
|
|
||||||
* @return this, for fluent API usage
|
|
||||||
*/
|
|
||||||
public MessageBuilder defaultMessage(DefaultMessageFactory defaultMessageFactory) {
|
|
||||||
messageResolverBuilder.defaultMessage(defaultMessageFactory);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the message locale.
|
|
||||||
* If not set, the default locale the Locale of the current request obtained from {@link LocaleContextHolder#getLocale()}.
|
|
||||||
* @param message the locale
|
|
||||||
* @return this, for fluent API usage
|
|
||||||
*/
|
|
||||||
public MessageBuilder locale(Locale locale) {
|
|
||||||
this.locale = locale;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds the resolver for the message.
|
|
||||||
* Call after recording all builder instructions.
|
|
||||||
* @return the built message resolver
|
|
||||||
* @throws IllegalStateException if no codes have been added and there is no default message
|
|
||||||
*/
|
|
||||||
public String build() {
|
|
||||||
return messageResolverBuilder.build().resolveMessage(messageSource, getLocale());
|
|
||||||
}
|
|
||||||
|
|
||||||
// internal helpers
|
|
||||||
|
|
||||||
private Locale getLocale() {
|
|
||||||
if (locale != null) {
|
|
||||||
return locale;
|
|
||||||
} else {
|
|
||||||
return LocaleContextHolder.getLocale();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2004-2009 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.context.message;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Runtime exception thrown by a {@link MessageResolver} if a message resolution fails.
|
|
||||||
* @author Keith Donald
|
|
||||||
* @since 3.0
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("serial")
|
|
||||||
public class MessageResolutionException extends RuntimeException {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new message resolution exception.
|
|
||||||
* @param message a messaging describing the failure
|
|
||||||
*/
|
|
||||||
public MessageResolutionException(String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new message resolution exception.
|
|
||||||
* @param message a messaging describing the failure
|
|
||||||
* @param cause the cause of the failure
|
|
||||||
*/
|
|
||||||
public MessageResolutionException(String message, Throwable cause) {
|
|
||||||
super(message, cause);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2004-2009 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.context.message;
|
|
||||||
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
import org.springframework.context.MessageSource;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A factory for a localized message resolved from a MessageSource.
|
|
||||||
* @author Keith Donald
|
|
||||||
* @since 3.0
|
|
||||||
* @see MessageSource
|
|
||||||
*/
|
|
||||||
public interface MessageResolver {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resolve the message from the message source for the locale.
|
|
||||||
* @param messageSource the message source, an abstraction for a resource bundle
|
|
||||||
* @param locale the locale of this request
|
|
||||||
* @return the resolved message
|
|
||||||
* @throws MessageResolutionException if a resolution failure occurs
|
|
||||||
*/
|
|
||||||
public String resolveMessage(MessageSource messageSource, Locale locale);
|
|
||||||
}
|
|
||||||
|
|
@ -1,130 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2004-2009 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.context.message;
|
|
||||||
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.LinkedHashSet;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.springframework.expression.ExpressionParser;
|
|
||||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds a {@link MessageResolver} that can resolve a localized message for display in a user interface.
|
|
||||||
* Allows convenient specification of the codes to try to resolve the message.
|
|
||||||
* Also supports named arguments that can inserted into a message template using eval #{expressions}.
|
|
||||||
* <p>
|
|
||||||
* Usage example:
|
|
||||||
* <pre>
|
|
||||||
* MessageResolver resolver = new MessageResolverBuilder().
|
|
||||||
* code("invalidFormat").
|
|
||||||
* arg("label", new ResolvableArgument("mathForm.decimalField")).
|
|
||||||
* arg("format", "#,###.##").
|
|
||||||
* defaultMessage("The decimal field must be in format #,###.##").
|
|
||||||
* build();
|
|
||||||
* String message = resolver.resolveMessage(messageSource, locale);
|
|
||||||
* </pre>
|
|
||||||
* Example messages.properties loaded by the MessageSource:
|
|
||||||
* <pre>
|
|
||||||
* invalidFormat=The #{label} must be in format #{format}.
|
|
||||||
* mathForm.decimalField=Decimal Field
|
|
||||||
* </pre>
|
|
||||||
* @author Keith Donald
|
|
||||||
* @since 3.0
|
|
||||||
* @see #code(String)
|
|
||||||
* @see #arg(String, Object)
|
|
||||||
* @see #defaultMessage(String)
|
|
||||||
*/
|
|
||||||
public class MessageResolverBuilder {
|
|
||||||
|
|
||||||
private Set<String> codes = new LinkedHashSet<String>();
|
|
||||||
|
|
||||||
private Map<String, Object> args = new LinkedHashMap<String, Object>();
|
|
||||||
|
|
||||||
private DefaultMessageFactory defaultMessageFactory;
|
|
||||||
|
|
||||||
private ExpressionParser expressionParser = new SpelExpressionParser();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a code that will be tried to lookup the message template used to create the localized message.
|
|
||||||
* Successive calls to this method add additional codes.
|
|
||||||
* Codes are tried in the order they are added.
|
|
||||||
* @param code a message code to try
|
|
||||||
* @return this, for fluent API usage
|
|
||||||
*/
|
|
||||||
public MessageResolverBuilder code(String code) {
|
|
||||||
codes.add(code);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add an argument to insert into the message.
|
|
||||||
* Named arguments are inserted by eval #{expressions} denoted within the message template.
|
|
||||||
* For example, the value of the 'format' argument would be inserted where a corresponding #{format} expression is defined in the message template.
|
|
||||||
* Successive calls to this method add additional arguments.
|
|
||||||
* May also add {@link ResolvableArgument resolvable arguments} whose values are resolved against the MessageSource passed to
|
|
||||||
* {@link MessageResolver#resolveMessage(org.springframework.context.MessageSource, java.util.Locale)}.
|
|
||||||
* @param name the argument name
|
|
||||||
* @param value the argument value
|
|
||||||
* @return this, for fluent API usage
|
|
||||||
* @see ResolvableArgument
|
|
||||||
*/
|
|
||||||
public MessageResolverBuilder arg(String name, Object value) {
|
|
||||||
args.put(name, value);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the default message.
|
|
||||||
* If the MessageResolver has no codes to try, this will be used as the message.
|
|
||||||
* If the MessageResolver has codes to try but none of those resolve to a message, this will be used as the message.
|
|
||||||
* @param message the default text
|
|
||||||
* @return this, for fluent API usage
|
|
||||||
*/
|
|
||||||
public MessageResolverBuilder defaultMessage(String message) {
|
|
||||||
return defaultMessage(new StaticDefaultMessageFactory(message));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the default message.
|
|
||||||
* If the MessageResolver has no codes to try, this will be used as the message.
|
|
||||||
* If the MessageResolver has codes to try but none of those resolve to a message, this will be used as the message.
|
|
||||||
* @param message the default text
|
|
||||||
* @return this, for fluent API usage
|
|
||||||
*/
|
|
||||||
public MessageResolverBuilder defaultMessage(DefaultMessageFactory defaultMessageFactory) {
|
|
||||||
this.defaultMessageFactory = defaultMessageFactory;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds the resolver for the message.
|
|
||||||
* Call after recording all builder instructions.
|
|
||||||
* @return the built message resolver
|
|
||||||
* @throws IllegalStateException if no codes have been added and there is no default message
|
|
||||||
*/
|
|
||||||
public MessageResolver build() {
|
|
||||||
if (codes == null && defaultMessageFactory == null) {
|
|
||||||
throw new IllegalStateException(
|
|
||||||
"A message code or the message text is required to build this message resolver");
|
|
||||||
}
|
|
||||||
String[] codesArray = (String[]) codes.toArray(new String[codes.size()]);
|
|
||||||
return new DefaultMessageResolver(codesArray, args, defaultMessageFactory, expressionParser);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2004-2009 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.context.message;
|
|
||||||
|
|
||||||
import org.springframework.context.MessageSource;
|
|
||||||
import org.springframework.context.MessageSourceResolvable;
|
|
||||||
import org.springframework.core.style.ToStringCreator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A message argument value that is resolved from a MessageSource.
|
|
||||||
* Allows the value to be localized.
|
|
||||||
* @see MessageSource
|
|
||||||
* @author Keith Donald
|
|
||||||
*/
|
|
||||||
public class ResolvableArgument implements MessageSourceResolvable {
|
|
||||||
|
|
||||||
private String code;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a resolvable argument.
|
|
||||||
* @param code the code that will be used to lookup the argument value from the message source
|
|
||||||
*/
|
|
||||||
public ResolvableArgument(String code) {
|
|
||||||
this.code = code;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String[] getCodes() {
|
|
||||||
return new String[] { code.toString() };
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object[] getArguments() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDefaultMessage() {
|
|
||||||
return String.valueOf(code);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
return new ToStringCreator(this).append("code", code).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2004-2009 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.context.message;
|
|
||||||
|
|
||||||
class StaticDefaultMessageFactory implements DefaultMessageFactory {
|
|
||||||
|
|
||||||
private String defaultMessage;
|
|
||||||
|
|
||||||
public StaticDefaultMessageFactory(String defaultMessage) {
|
|
||||||
this.defaultMessage = defaultMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String createDefaultMessage() {
|
|
||||||
return defaultMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
/**
|
|
||||||
* An API for creating localized messages.
|
|
||||||
*/
|
|
||||||
package org.springframework.context.message;
|
|
||||||
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2002-2009 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.mapping;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maps between a source and target.
|
|
||||||
* @author Keith Donald
|
|
||||||
* @param <S> the source type mapped from
|
|
||||||
* @param <T> the target type mapped to
|
|
||||||
*/
|
|
||||||
public interface Mapper<S, T> {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Map the source to the target.
|
|
||||||
* @param source the source to map from
|
|
||||||
* @param target the target to map to
|
|
||||||
* @throws MappingException if the mapping process failed
|
|
||||||
*/
|
|
||||||
void map(S source, T target);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2002-2009 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.mapping;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base runtime exception for the mapping system.
|
|
||||||
* @author Keith Donald
|
|
||||||
*/
|
|
||||||
public class MappingException extends RuntimeException {
|
|
||||||
|
|
||||||
public MappingException(String message, Throwable cause) {
|
|
||||||
super(message, cause);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
package org.springframework.mapping.support;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.springframework.expression.EvaluationContext;
|
|
||||||
|
|
||||||
interface MappableType {
|
|
||||||
|
|
||||||
Set<String> getMappableFields(Object instance);
|
|
||||||
|
|
||||||
EvaluationContext getMappingContext(Object instance);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
package org.springframework.mapping.support;
|
|
||||||
|
|
||||||
import org.springframework.core.convert.converter.Converter;
|
|
||||||
|
|
||||||
public interface MappingConfiguration {
|
|
||||||
MappingConfiguration setConverter(Converter converter);
|
|
||||||
}
|
|
||||||
|
|
@ -1,222 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2002-2009 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.mapping.support;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.LinkedHashSet;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.springframework.context.expression.MapAccessor;
|
|
||||||
import org.springframework.core.convert.converter.Converter;
|
|
||||||
import org.springframework.expression.EvaluationContext;
|
|
||||||
import org.springframework.expression.Expression;
|
|
||||||
import org.springframework.expression.ExpressionParser;
|
|
||||||
import org.springframework.expression.ParseException;
|
|
||||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
|
||||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
|
||||||
import org.springframework.mapping.Mapper;
|
|
||||||
import org.springframework.mapping.MappingException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A generic object mapper implementation based on the Spring Expression Language (SpEL).
|
|
||||||
* @author Keith Donald
|
|
||||||
*/
|
|
||||||
public class SpelMapper implements Mapper<Object, Object> {
|
|
||||||
|
|
||||||
private static final MappableType MAP_MAPPABLE_TYPE = new MapMappableType();
|
|
||||||
|
|
||||||
private static final MappableType BEAN_MAPPABLE_TYPE = new BeanMappableType();
|
|
||||||
|
|
||||||
private static final ExpressionParser expressionParser = new SpelExpressionParser();
|
|
||||||
|
|
||||||
private Set<Mapping> mappings = new LinkedHashSet<Mapping>();
|
|
||||||
|
|
||||||
private boolean autoMappingEnabled = true;
|
|
||||||
|
|
||||||
public void setAutoMappingEnabled(boolean autoMappingEnabled) {
|
|
||||||
this.autoMappingEnabled = autoMappingEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MappingConfiguration addMapping(String sourceExpression, String targetExpression) {
|
|
||||||
Expression sourceExp;
|
|
||||||
try {
|
|
||||||
sourceExp = expressionParser.parseExpression(sourceExpression);
|
|
||||||
} catch (ParseException e) {
|
|
||||||
throw new IllegalArgumentException("The mapping source '" + sourceExpression
|
|
||||||
+ "' is not a parseable value expression", e);
|
|
||||||
}
|
|
||||||
Expression targetExp;
|
|
||||||
try {
|
|
||||||
targetExp = expressionParser.parseExpression(targetExpression);
|
|
||||||
} catch (ParseException e) {
|
|
||||||
throw new IllegalArgumentException("The mapping target '" + sourceExpression
|
|
||||||
+ "' is not a parseable property expression", e);
|
|
||||||
}
|
|
||||||
Mapping mapping = new Mapping(sourceExp, targetExp);
|
|
||||||
if (mappings == null) {
|
|
||||||
mappings = new LinkedHashSet<Mapping>();
|
|
||||||
}
|
|
||||||
mappings.add(mapping);
|
|
||||||
return mapping;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void map(Object source, Object target) throws MappingException {
|
|
||||||
EvaluationContext sourceContext = getMappingContext(source);
|
|
||||||
EvaluationContext targetContext = getMappingContext(target);
|
|
||||||
for (Mapping mapping : mappings) {
|
|
||||||
mapping.map(sourceContext, targetContext);
|
|
||||||
}
|
|
||||||
Set<Mapping> autoMappings = getAutoMappings(source);
|
|
||||||
for (Mapping mapping : autoMappings) {
|
|
||||||
mapping.map(sourceContext, targetContext);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected EvaluationContext getMappingContext(Object object) {
|
|
||||||
if (object instanceof Map) {
|
|
||||||
return MAP_MAPPABLE_TYPE.getMappingContext(object);
|
|
||||||
} else {
|
|
||||||
return BEAN_MAPPABLE_TYPE.getMappingContext(object);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Set<String> getMappableFields(Object object) {
|
|
||||||
if (object instanceof Map) {
|
|
||||||
return MAP_MAPPABLE_TYPE.getMappableFields(object);
|
|
||||||
} else {
|
|
||||||
return BEAN_MAPPABLE_TYPE.getMappableFields(object);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Set<Mapping> getAutoMappings(Object source) {
|
|
||||||
if (autoMappingEnabled) {
|
|
||||||
Set<Mapping> autoMappings = new LinkedHashSet<Mapping>();
|
|
||||||
Set<String> fields = getMappableFields(source);
|
|
||||||
for (String field : fields) {
|
|
||||||
if (!explicitlyMapped(field)) {
|
|
||||||
Expression exp;
|
|
||||||
try {
|
|
||||||
exp = expressionParser.parseExpression(field);
|
|
||||||
} catch (ParseException e) {
|
|
||||||
throw new IllegalArgumentException("The mapping source '" + source
|
|
||||||
+ "' is not a parseable value expression", e);
|
|
||||||
}
|
|
||||||
Mapping mapping = new Mapping(exp, exp);
|
|
||||||
autoMappings.add(mapping);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return autoMappings;
|
|
||||||
} else {
|
|
||||||
return Collections.emptySet();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean explicitlyMapped(String field) {
|
|
||||||
for (Mapping mapping : mappings) {
|
|
||||||
if (mapping.source.getExpressionString().equals(field)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class Mapping implements MappingConfiguration {
|
|
||||||
|
|
||||||
private Expression source;
|
|
||||||
|
|
||||||
private Expression target;
|
|
||||||
|
|
||||||
private Converter converter;
|
|
||||||
|
|
||||||
public Mapping(Expression source, Expression target) {
|
|
||||||
this.source = source;
|
|
||||||
this.target = target;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MappingConfiguration setConverter(Converter converter) {
|
|
||||||
this.converter = converter;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void map(EvaluationContext sourceContext, EvaluationContext targetContext) throws MappingException {
|
|
||||||
try {
|
|
||||||
Object value = source.getValue(sourceContext);
|
|
||||||
if (converter != null) {
|
|
||||||
value = converter.convert(value);
|
|
||||||
}
|
|
||||||
target.setValue(targetContext, value);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new MappingException("Could not perform mapping", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int hashCode() {
|
|
||||||
return source.getExpressionString().hashCode() + target.getExpressionString().hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (!(o instanceof Mapping)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Mapping m = (Mapping) o;
|
|
||||||
return source.getExpressionString().equals(m.source.getExpressionString())
|
|
||||||
&& target.getExpressionString().equals(m.source.getExpressionString());
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
return source.getExpressionString() + " -> " + target.getExpressionString();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static class MapMappableType implements MappableType {
|
|
||||||
|
|
||||||
StandardEvaluationContext evaluationContext = new StandardEvaluationContext();
|
|
||||||
|
|
||||||
public Set<String> getMappableFields(Object instance) {
|
|
||||||
Map map = (Map) instance;
|
|
||||||
LinkedHashSet<String> fields = new LinkedHashSet<String>(map.size(), 1);
|
|
||||||
for (Object key : map.keySet()) {
|
|
||||||
fields.add(key.toString());
|
|
||||||
}
|
|
||||||
return fields;
|
|
||||||
}
|
|
||||||
|
|
||||||
public EvaluationContext getMappingContext(Object instance) {
|
|
||||||
StandardEvaluationContext context = new StandardEvaluationContext(instance);
|
|
||||||
context.addPropertyAccessor(new MapAccessor());
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static class BeanMappableType implements MappableType {
|
|
||||||
|
|
||||||
StandardEvaluationContext evaluationContext = new StandardEvaluationContext();
|
|
||||||
|
|
||||||
public Set<String> getMappableFields(Object instance) {
|
|
||||||
// TODO
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public EvaluationContext getMappingContext(Object instance) {
|
|
||||||
return new StandardEvaluationContext(instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2004-2009 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.model.binder;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bind to fields of a model object.
|
|
||||||
* @author Keith Donald
|
|
||||||
* @since 3.0
|
|
||||||
* @param <M> The type of model this binder binds to
|
|
||||||
*/
|
|
||||||
public interface Binder<M> {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bind submitted field values.
|
|
||||||
* @param fieldValues the field values to bind; an entry key is a field name, the associated entry value is the submitted value for that field
|
|
||||||
* @param model the model to bind to
|
|
||||||
* @return the results of the binding operation
|
|
||||||
* @throws MissingFieldException when the fieldValues Map is missing required fields
|
|
||||||
*/
|
|
||||||
BindingResults bind(Map<String, ? extends Object> fieldValues, M model);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2004-2009 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.model.binder;
|
|
||||||
|
|
||||||
import org.springframework.context.alert.Alert;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The result of a bind operation.
|
|
||||||
* @author Keith Donald
|
|
||||||
* @since 3.0
|
|
||||||
* @see Binder#bind(java.util.Map, Object)
|
|
||||||
*/
|
|
||||||
public interface BindingResult {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The name of the field this binding result is for.
|
|
||||||
* @see Binder#getNested(String)
|
|
||||||
*/
|
|
||||||
String getFieldName();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The raw submitted value for which binding was attempted.
|
|
||||||
* If not a failure, this value was successfully bound to the model.
|
|
||||||
* @see #isFailure()
|
|
||||||
*/
|
|
||||||
Object getSubmittedValue();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates if the binding failed.
|
|
||||||
*/
|
|
||||||
boolean isFailure();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the alert for this binding result, appropriate for rendering the result to the user.
|
|
||||||
* An alert describing a successful binding will have info severity.
|
|
||||||
* An alert describing a failed binding will have either warning, error, or fatal severity.
|
|
||||||
*/
|
|
||||||
Alert getAlert();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,68 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2004-2009 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.model.binder;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.springframework.context.alert.Severity;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The results of a bind operation.
|
|
||||||
* @author Keith Donald
|
|
||||||
* @since 3.0
|
|
||||||
* @see Binder#bind(java.util.Map, Object)
|
|
||||||
*/
|
|
||||||
public interface BindingResults extends Iterable<BindingResult> {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The subset of BindingResults that were successful.
|
|
||||||
*/
|
|
||||||
List<BindingResult> successes();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The subset of BindingResults that failed.
|
|
||||||
*/
|
|
||||||
List<BindingResult> failures();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If there is at least one failure with a Severity equal to or greater than {@link Severity#ERROR}.
|
|
||||||
* @see BindingResults#failures()
|
|
||||||
*/
|
|
||||||
boolean hasErrors();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The subset of BindingResults that failed with {@link Severity#ERROR} or greater.
|
|
||||||
*/
|
|
||||||
List<BindingResult> errors();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The total number of results.
|
|
||||||
*/
|
|
||||||
int size();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The BindingResult at the specified index.
|
|
||||||
* @throws IndexOutOfBoundsException if the index is out of bounds
|
|
||||||
*/
|
|
||||||
BindingResult get(int index);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The BindingResult for the specified field.
|
|
||||||
* Returns null if no result exists for the fieldName specified.
|
|
||||||
*/
|
|
||||||
BindingResult get(String fieldName);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,58 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2004-2009 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.model.binder;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Exception thrown by a Binder when a required source value is missing unexpectedly from the sourceValues map.
|
|
||||||
* Indicates a client configuration error.
|
|
||||||
* @author Keith Donald
|
|
||||||
* @since 3.0
|
|
||||||
* @see Binder#bind(Map, Object)
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("serial")
|
|
||||||
public class MissingFieldException extends RuntimeException {
|
|
||||||
|
|
||||||
private List<String> missing;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new missing field exceptions.
|
|
||||||
* @param missing
|
|
||||||
* @param fieldValues
|
|
||||||
*/
|
|
||||||
public MissingFieldException(List<String> missing, Map<String, ? extends Object> fieldValues) {
|
|
||||||
super(getMessage(missing, fieldValues));
|
|
||||||
this.missing = missing;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The names of the fields that are missing.
|
|
||||||
*/
|
|
||||||
public List<String> getMissing() {
|
|
||||||
return missing;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String getMessage(List<String> missingRequired, Map<String, ? extends Object> sourceValues) {
|
|
||||||
if (missingRequired.size() == 1) {
|
|
||||||
return "Missing a field [" + missingRequired.get(0) + "]; fieldValues map contained " + sourceValues.keySet();
|
|
||||||
} else {
|
|
||||||
return "Missing fields " + missingRequired + "; fieldValues map contained " + sourceValues.keySet();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
/**
|
|
||||||
* API for binding submitted field values in a single batch operation.
|
|
||||||
*/
|
|
||||||
package org.springframework.model.binder;
|
|
||||||
|
|
||||||
|
|
@ -1,127 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2004-2009 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.model.binder.support;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.springframework.context.MessageSource;
|
|
||||||
import org.springframework.model.binder.Binder;
|
|
||||||
import org.springframework.model.binder.BindingResult;
|
|
||||||
import org.springframework.model.binder.BindingResults;
|
|
||||||
import org.springframework.model.binder.MissingFieldException;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base Binder implementation that defines common structural elements.
|
|
||||||
* Subclasses should be parameterized & implement {@link #bind(Map, Object)}.
|
|
||||||
* @author Keith Donald
|
|
||||||
* @since 3.0
|
|
||||||
* @see #setRequiredFields(String[])
|
|
||||||
* @see #setMessageSource(MessageSource)
|
|
||||||
* @see #createFieldBinder()
|
|
||||||
* @see #bind(Map, Object)
|
|
||||||
*/
|
|
||||||
public abstract class AbstractBinder<M> implements Binder<M> {
|
|
||||||
|
|
||||||
private MessageSource messageSource;
|
|
||||||
|
|
||||||
private String[] requiredFields;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configure the fields for which values must be present in each bind attempt.
|
|
||||||
* @param fieldNames the required field names
|
|
||||||
* @see MissingFieldException
|
|
||||||
*/
|
|
||||||
public void setRequiredFields(String[] fieldNames) {
|
|
||||||
this.requiredFields = fieldNames;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configure the MessageSource that resolves localized {@link BindingResult} alert messages.
|
|
||||||
* @param messageSource the message source
|
|
||||||
*/
|
|
||||||
public void setMessageSource(MessageSource messageSource) {
|
|
||||||
Assert.notNull(messageSource, "The MessageSource is required");
|
|
||||||
this.messageSource = messageSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The configured MessageSource that resolves binding result alert messages.
|
|
||||||
*/
|
|
||||||
protected MessageSource getMessageSource() {
|
|
||||||
return messageSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Binder implementation
|
|
||||||
|
|
||||||
public final BindingResults bind(Map<String, ? extends Object> fieldValues, M model) {
|
|
||||||
fieldValues = filter(fieldValues, model);
|
|
||||||
checkRequired(fieldValues);
|
|
||||||
FieldBinder fieldBinder = createFieldBinder(model);
|
|
||||||
ArrayListBindingResults results = new ArrayListBindingResults(fieldValues.size());
|
|
||||||
for (Map.Entry<String, ? extends Object> fieldValue : fieldValues.entrySet()) {
|
|
||||||
results.add(fieldBinder.bind(fieldValue.getKey(), fieldValue.getValue()));
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
// subclass hooks
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Subclasses must implement this method to create the {@link FieldBinder}
|
|
||||||
* instance for the given model.
|
|
||||||
*/
|
|
||||||
protected abstract FieldBinder createFieldBinder(M model);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Filter the fields to bind.
|
|
||||||
* Allows for pre-processing the fieldValues Map before any binding occurs.
|
|
||||||
* For example, you might insert empty or default values for fields that are not present.
|
|
||||||
* As another example, you might collapse multiple fields into a single field.
|
|
||||||
* Default implementation simply returns the fieldValues Map unchanged.
|
|
||||||
* @param fieldValues the original fieldValues Map provided by the caller
|
|
||||||
* @return the filtered fieldValues Map that will be used to bind
|
|
||||||
*/
|
|
||||||
protected Map<String, ? extends Object> filter(Map<String, ? extends Object> fieldValues, M model) {
|
|
||||||
return fieldValues;
|
|
||||||
}
|
|
||||||
|
|
||||||
// internal helpers
|
|
||||||
|
|
||||||
private void checkRequired(Map<String, ? extends Object> fieldValues) {
|
|
||||||
if (requiredFields == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
List<String> missingRequired = new ArrayList<String>();
|
|
||||||
for (String required : requiredFields) {
|
|
||||||
boolean found = false;
|
|
||||||
for (String property : fieldValues.keySet()) {
|
|
||||||
if (property.equals(required)) {
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!found) {
|
|
||||||
missingRequired.add(required);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!missingRequired.isEmpty()) {
|
|
||||||
throw new MissingFieldException(missingRequired, fieldValues);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2004-2009 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.model.binder.support;
|
|
||||||
|
|
||||||
import org.springframework.context.alert.Alert;
|
|
||||||
import org.springframework.context.alert.Severity;
|
|
||||||
import org.springframework.model.binder.BindingResult;
|
|
||||||
|
|
||||||
public class AlertBindingResult implements BindingResult {
|
|
||||||
|
|
||||||
private String fieldName;
|
|
||||||
|
|
||||||
private Object submittedValue;
|
|
||||||
|
|
||||||
private Alert alert;
|
|
||||||
|
|
||||||
public AlertBindingResult(String fieldName, Object sourceValue, Alert alert) {
|
|
||||||
this.fieldName = fieldName;
|
|
||||||
this.submittedValue = sourceValue;
|
|
||||||
this.alert = alert;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getFieldName() {
|
|
||||||
return fieldName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object getSubmittedValue() {
|
|
||||||
return submittedValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isFailure() {
|
|
||||||
return alert.getSeverity().compareTo(Severity.INFO) > 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Alert getAlert() {
|
|
||||||
return alert;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
return getAlert().toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,104 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2004-2009 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.model.binder.support;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.springframework.context.alert.Severity;
|
|
||||||
import org.springframework.model.binder.BindingResult;
|
|
||||||
import org.springframework.model.binder.BindingResults;
|
|
||||||
|
|
||||||
class ArrayListBindingResults implements BindingResults {
|
|
||||||
|
|
||||||
private List<BindingResult> results;
|
|
||||||
|
|
||||||
public ArrayListBindingResults() {
|
|
||||||
results = new ArrayList<BindingResult>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ArrayListBindingResults(int size) {
|
|
||||||
results = new ArrayList<BindingResult>(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void add(BindingResult result) {
|
|
||||||
results.add(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
// implementing Iterable
|
|
||||||
|
|
||||||
public Iterator<BindingResult> iterator() {
|
|
||||||
return results.iterator();
|
|
||||||
}
|
|
||||||
|
|
||||||
// implementing BindingResults
|
|
||||||
|
|
||||||
public List<BindingResult> successes() {
|
|
||||||
List<BindingResult> results = new ArrayList<BindingResult>();
|
|
||||||
for (BindingResult result : this) {
|
|
||||||
if (!result.isFailure()) {
|
|
||||||
results.add(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<BindingResult> failures() {
|
|
||||||
List<BindingResult> results = new ArrayList<BindingResult>();
|
|
||||||
for (BindingResult result : this) {
|
|
||||||
if (result.isFailure()) {
|
|
||||||
results.add(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasErrors() {
|
|
||||||
return errors().size() > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<BindingResult> errors() {
|
|
||||||
List<BindingResult> results = new ArrayList<BindingResult>();
|
|
||||||
for (BindingResult result : this) {
|
|
||||||
if (result.isFailure() && result.getAlert().getSeverity().compareTo(Severity.ERROR) >= 0) {
|
|
||||||
results.add(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BindingResult get(int index) {
|
|
||||||
return results.get(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BindingResult get(String fieldName) {
|
|
||||||
for (BindingResult result : results) {
|
|
||||||
if (result.getFieldName().equals(fieldName)) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int size() {
|
|
||||||
return results.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
return "[BindingResults = " + results.toString() + "]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2004-2009 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.model.binder.support;
|
|
||||||
|
|
||||||
import org.springframework.model.binder.BindingResult;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Binder callback interface for binding a single field value.
|
|
||||||
* @author Keith Donald
|
|
||||||
* @since 3.0
|
|
||||||
* @see AbstractBinder#createFieldBinder(Object)
|
|
||||||
*/
|
|
||||||
public interface FieldBinder {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bind a single field.
|
|
||||||
* @param fieldName the field name
|
|
||||||
* @param value the field value
|
|
||||||
* @return the binding result
|
|
||||||
*/
|
|
||||||
BindingResult bind(String fieldName, Object value);
|
|
||||||
}
|
|
||||||
|
|
@ -1,86 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2004-2009 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.model.binder.support;
|
|
||||||
|
|
||||||
import org.springframework.context.MessageSource;
|
|
||||||
import org.springframework.context.alert.Alert;
|
|
||||||
import org.springframework.context.alert.Severity;
|
|
||||||
import org.springframework.context.message.DefaultMessageFactory;
|
|
||||||
import org.springframework.context.message.MessageBuilder;
|
|
||||||
import org.springframework.context.message.ResolvableArgument;
|
|
||||||
import org.springframework.model.binder.BindingResult;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates a field failed to bind because it was not editable/writeable.
|
|
||||||
* @author Keith Donald
|
|
||||||
* @since 3.0
|
|
||||||
*/
|
|
||||||
public class FieldNotEditableResult implements BindingResult {
|
|
||||||
|
|
||||||
private String fieldName;
|
|
||||||
|
|
||||||
private Object submittedValue;
|
|
||||||
|
|
||||||
private MessageSource messageSource;
|
|
||||||
|
|
||||||
public FieldNotEditableResult(String fieldName, Object submittedValue, MessageSource messageSource) {
|
|
||||||
this.fieldName = fieldName;
|
|
||||||
this.submittedValue = submittedValue;
|
|
||||||
this.messageSource = messageSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getFieldName() {
|
|
||||||
return fieldName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object getSubmittedValue() {
|
|
||||||
return submittedValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isFailure() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Alert getAlert() {
|
|
||||||
return new Alert() {
|
|
||||||
public String getCode() {
|
|
||||||
return "fieldNotEditable";
|
|
||||||
}
|
|
||||||
|
|
||||||
public Severity getSeverity() {
|
|
||||||
return Severity.WARNING;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getMessage() {
|
|
||||||
MessageBuilder builder = new MessageBuilder(messageSource);
|
|
||||||
builder.code(getCode());
|
|
||||||
builder.arg("label", new ResolvableArgument(fieldName));
|
|
||||||
builder.arg("value", submittedValue);
|
|
||||||
builder.defaultMessage(new DefaultMessageFactory() {
|
|
||||||
public String createDefaultMessage() {
|
|
||||||
return "Failed to bind submitted value " + submittedValue + "; field '" + fieldName + "' is not editable";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
return getAlert().toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,86 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2004-2009 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.model.binder.support;
|
|
||||||
|
|
||||||
import org.springframework.context.MessageSource;
|
|
||||||
import org.springframework.context.alert.Alert;
|
|
||||||
import org.springframework.context.alert.Severity;
|
|
||||||
import org.springframework.context.message.DefaultMessageFactory;
|
|
||||||
import org.springframework.context.message.MessageBuilder;
|
|
||||||
import org.springframework.context.message.ResolvableArgument;
|
|
||||||
import org.springframework.model.binder.BindingResult;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates field failed to bind because it was not found.
|
|
||||||
* @author Keith Donald
|
|
||||||
* @since 3.0
|
|
||||||
*/
|
|
||||||
public class FieldNotFoundResult implements BindingResult {
|
|
||||||
|
|
||||||
private String fieldName;
|
|
||||||
|
|
||||||
private Object submittedValue;
|
|
||||||
|
|
||||||
private MessageSource messageSource;
|
|
||||||
|
|
||||||
public FieldNotFoundResult(String fieldName, Object submittedValue, MessageSource messageSource) {
|
|
||||||
this.fieldName = fieldName;
|
|
||||||
this.submittedValue = submittedValue;
|
|
||||||
this.messageSource = messageSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getFieldName() {
|
|
||||||
return fieldName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object getSubmittedValue() {
|
|
||||||
return submittedValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isFailure() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Alert getAlert() {
|
|
||||||
return new Alert() {
|
|
||||||
public String getCode() {
|
|
||||||
return "fieldNotFound";
|
|
||||||
}
|
|
||||||
|
|
||||||
public Severity getSeverity() {
|
|
||||||
return Severity.WARNING;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getMessage() {
|
|
||||||
MessageBuilder builder = new MessageBuilder(messageSource);
|
|
||||||
builder.code(getCode());
|
|
||||||
builder.arg("label", new ResolvableArgument(fieldName));
|
|
||||||
builder.arg("value", submittedValue);
|
|
||||||
builder.defaultMessage(new DefaultMessageFactory() {
|
|
||||||
public String createDefaultMessage() {
|
|
||||||
return "Failed to bind submitted value " + submittedValue + "; no field '" + fieldName + "' found";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
return getAlert().toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,212 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2004-2009 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.model.binder.support;
|
|
||||||
|
|
||||||
import org.springframework.context.MessageSource;
|
|
||||||
import org.springframework.context.alert.Alert;
|
|
||||||
import org.springframework.context.alert.Severity;
|
|
||||||
import org.springframework.context.expression.MapAccessor;
|
|
||||||
import org.springframework.context.message.DefaultMessageFactory;
|
|
||||||
import org.springframework.context.message.MessageBuilder;
|
|
||||||
import org.springframework.context.message.ResolvableArgument;
|
|
||||||
import org.springframework.core.convert.ConversionFailedException;
|
|
||||||
import org.springframework.expression.EvaluationContext;
|
|
||||||
import org.springframework.expression.EvaluationException;
|
|
||||||
import org.springframework.expression.Expression;
|
|
||||||
import org.springframework.expression.ExpressionParser;
|
|
||||||
import org.springframework.expression.ParseException;
|
|
||||||
import org.springframework.expression.spel.SpelEvaluationException;
|
|
||||||
import org.springframework.expression.spel.SpelMessage;
|
|
||||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
|
||||||
import org.springframework.expression.spel.standard.SpelExpressionParserConfiguration;
|
|
||||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
|
||||||
import org.springframework.model.binder.Binder;
|
|
||||||
import org.springframework.model.binder.BindingResult;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A {@link Binder} implementation that accepts any target object and uses
|
|
||||||
* Spring's Expression Language (SpEL) to evaluate the keys in the field value Map.
|
|
||||||
* @author Mark Fisher
|
|
||||||
* @author Keith Donald
|
|
||||||
* @since 3.0
|
|
||||||
*/
|
|
||||||
public class GenericBinder extends AbstractBinder<Object> {
|
|
||||||
|
|
||||||
private final ExpressionParser expressionParser = new SpelExpressionParser(
|
|
||||||
SpelExpressionParserConfiguration.CreateObjectIfAttemptToReferenceNull
|
|
||||||
| SpelExpressionParserConfiguration.GrowListsOnIndexBeyondSize);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected FieldBinder createFieldBinder(Object model) {
|
|
||||||
StandardEvaluationContext context = new StandardEvaluationContext();
|
|
||||||
context.addPropertyAccessor(new MapAccessor());
|
|
||||||
context.setRootObject(model);
|
|
||||||
return new ExpressionFieldBinder(getMessageSource(), expressionParser, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class ExpressionFieldBinder implements FieldBinder {
|
|
||||||
|
|
||||||
private final MessageSource messageSource;
|
|
||||||
|
|
||||||
private final ExpressionParser expressionParser;
|
|
||||||
|
|
||||||
private final EvaluationContext evaluationContext;
|
|
||||||
|
|
||||||
private ExpressionFieldBinder(MessageSource messageSource, ExpressionParser expressionParser,
|
|
||||||
EvaluationContext evaluationContext) {
|
|
||||||
this.messageSource = messageSource;
|
|
||||||
this.expressionParser = expressionParser;
|
|
||||||
this.evaluationContext = evaluationContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BindingResult bind(String fieldName, Object value) {
|
|
||||||
Alert alert = null;
|
|
||||||
try {
|
|
||||||
Expression exp = expressionParser.parseExpression(fieldName);
|
|
||||||
if (!exp.isWritable(evaluationContext)) {
|
|
||||||
return new FieldNotEditableResult(fieldName, value, messageSource);
|
|
||||||
}
|
|
||||||
exp.setValue(evaluationContext, value);
|
|
||||||
alert = new BindSuccessAlert(fieldName, value, messageSource);
|
|
||||||
} catch (ParseException e) {
|
|
||||||
alert = new InternalErrorAlert(e);
|
|
||||||
} catch (EvaluationException e) {
|
|
||||||
SpelEvaluationException spelException = (SpelEvaluationException) e;
|
|
||||||
if (spelException.getMessageCode() == SpelMessage.EXCEPTION_DURING_PROPERTY_WRITE) {
|
|
||||||
ConversionFailedException conversionFailure = findConversionFailureCause(spelException);
|
|
||||||
if (conversionFailure != null) {
|
|
||||||
alert = new TypeMismatchAlert(fieldName, value, conversionFailure, messageSource);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (alert == null) {
|
|
||||||
alert = new InternalErrorAlert(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new AlertBindingResult(fieldName, value, alert);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ConversionFailedException findConversionFailureCause(Exception e) {
|
|
||||||
Throwable cause = e.getCause();
|
|
||||||
while (cause != null) {
|
|
||||||
if (cause instanceof ConversionFailedException) {
|
|
||||||
return (ConversionFailedException) cause;
|
|
||||||
}
|
|
||||||
cause = cause.getCause();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class BindSuccessAlert implements Alert {
|
|
||||||
|
|
||||||
private final String fieldName;
|
|
||||||
|
|
||||||
private final Object value;
|
|
||||||
|
|
||||||
private MessageSource messageSource;
|
|
||||||
|
|
||||||
public BindSuccessAlert(String fieldName, Object value, MessageSource messageSource) {
|
|
||||||
this.fieldName = fieldName;
|
|
||||||
this.value = value;
|
|
||||||
this.messageSource = messageSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCode() {
|
|
||||||
return "bindSuccess";
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getMessage() {
|
|
||||||
MessageBuilder builder = new MessageBuilder(messageSource);
|
|
||||||
builder.code(getCode());
|
|
||||||
builder.arg("label", new ResolvableArgument(fieldName));
|
|
||||||
builder.arg("value", value);
|
|
||||||
builder.defaultMessage(new DefaultMessageFactory() {
|
|
||||||
public String createDefaultMessage() {
|
|
||||||
return "Successfully bound submitted value " + value + " to field '" + fieldName + "'";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Severity getSeverity() {
|
|
||||||
return Severity.INFO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class TypeMismatchAlert implements Alert {
|
|
||||||
|
|
||||||
private final String fieldName;
|
|
||||||
|
|
||||||
private final Object value;
|
|
||||||
|
|
||||||
private final ConversionFailedException cause;
|
|
||||||
|
|
||||||
private MessageSource messageSource;
|
|
||||||
|
|
||||||
public TypeMismatchAlert(String fieldName, Object value, ConversionFailedException cause,
|
|
||||||
MessageSource messageSource) {
|
|
||||||
this.fieldName = fieldName;
|
|
||||||
this.value = value;
|
|
||||||
this.cause = cause;
|
|
||||||
this.messageSource = messageSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCode() {
|
|
||||||
return "typeMismatch";
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getMessage() {
|
|
||||||
MessageBuilder builder = new MessageBuilder(messageSource);
|
|
||||||
builder.code(getCode());
|
|
||||||
builder.arg("label", new ResolvableArgument(fieldName));
|
|
||||||
builder.arg("value", value);
|
|
||||||
builder.defaultMessage(new DefaultMessageFactory() {
|
|
||||||
public String createDefaultMessage() {
|
|
||||||
return "Failed to bind submitted value " + value + " to field '" + fieldName
|
|
||||||
+ "'; value could not be converted to type [" + cause.getTargetType().getName() + "]";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Severity getSeverity() {
|
|
||||||
return Severity.ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class InternalErrorAlert implements Alert {
|
|
||||||
|
|
||||||
private final Exception cause;
|
|
||||||
|
|
||||||
public InternalErrorAlert(Exception cause) {
|
|
||||||
this.cause = cause;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCode() {
|
|
||||||
return "internalError";
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getMessage() {
|
|
||||||
return "An internal error occurred; message = [" + cause.getMessage() + "]";
|
|
||||||
}
|
|
||||||
|
|
||||||
public Severity getSeverity() {
|
|
||||||
return Severity.FATAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
/**
|
|
||||||
* Binder API implementation support.
|
|
||||||
*/
|
|
||||||
package org.springframework.model.binder.support;
|
|
||||||
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
package org.springframework.context.alert;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.springframework.context.alert.Alerts.error;
|
|
||||||
import static org.springframework.context.alert.Alerts.fatal;
|
|
||||||
import static org.springframework.context.alert.Alerts.info;
|
|
||||||
import static org.springframework.context.alert.Alerts.warning;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.springframework.context.alert.Alert;
|
|
||||||
import org.springframework.context.alert.Severity;
|
|
||||||
|
|
||||||
public class AlertsTests {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testFactoryMethods() {
|
|
||||||
Alert a1 = info("alert 1");
|
|
||||||
assertEquals(Severity.INFO, a1.getSeverity());
|
|
||||||
assertEquals("alert 1", a1.getMessage());
|
|
||||||
|
|
||||||
Alert a2 = warning("alert 2");
|
|
||||||
assertEquals(Severity.WARNING, a2.getSeverity());
|
|
||||||
assertEquals("alert 2", a2.getMessage());
|
|
||||||
|
|
||||||
Alert a3 = error("alert 3");
|
|
||||||
assertEquals(Severity.ERROR, a3.getSeverity());
|
|
||||||
assertEquals("alert 3", a3.getMessage());
|
|
||||||
|
|
||||||
Alert a4 = fatal("alert 4");
|
|
||||||
assertEquals(Severity.FATAL, a4.getSeverity());
|
|
||||||
assertEquals("alert 4", a4.getMessage());
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
package org.springframework.context.alert.support;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.springframework.context.alert.Alert;
|
|
||||||
import org.springframework.context.alert.Severity;
|
|
||||||
import org.springframework.context.alert.support.DefaultAlertContext;
|
|
||||||
|
|
||||||
public class DefaultAlertContextTests {
|
|
||||||
|
|
||||||
private DefaultAlertContext context;
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void setUp() {
|
|
||||||
context = new DefaultAlertContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void addAlert() {
|
|
||||||
Alert alert = new Alert() {
|
|
||||||
public String getCode() {
|
|
||||||
return "invalidFormat";
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getMessage() {
|
|
||||||
return "Please enter a value in format yyyy-dd-mm";
|
|
||||||
}
|
|
||||||
|
|
||||||
public Severity getSeverity() {
|
|
||||||
return Severity.ERROR;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
context.add("form.property", alert);
|
|
||||||
assertEquals(1, context.getAlerts().size());
|
|
||||||
assertEquals("invalidFormat", context.getAlerts("form.property").get(0).getCode());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
package org.springframework.context.message;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.springframework.context.message.MessageBuilder;
|
|
||||||
import org.springframework.context.message.ResolvableArgument;
|
|
||||||
|
|
||||||
public class MessageBuilderTests {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void buildMessage() {
|
|
||||||
MockMessageSource messageSource = new MockMessageSource();
|
|
||||||
messageSource.addMessage("invalidFormat", Locale.US, "#{label} must be in format #{format}");
|
|
||||||
messageSource.addMessage("mathForm.decimalField", Locale.US, "Decimal Field");
|
|
||||||
MessageBuilder builder = new MessageBuilder(messageSource);
|
|
||||||
String message = builder.code("invalidFormat").arg("label", new ResolvableArgument("mathForm.decimalField"))
|
|
||||||
.arg("format", "#,###.##").locale(Locale.US).defaultMessage("Field must be in format #,###.##").build();
|
|
||||||
assertEquals("Decimal Field must be in format #,###.##", message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
package org.springframework.context.message;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.springframework.context.message.MessageResolver;
|
|
||||||
import org.springframework.context.message.MessageResolverBuilder;
|
|
||||||
import org.springframework.context.message.ResolvableArgument;
|
|
||||||
|
|
||||||
public class MessageResolverBuilderTests {
|
|
||||||
|
|
||||||
private MessageResolverBuilder builder = new MessageResolverBuilder();
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void buildMessage() {
|
|
||||||
MessageResolver resolver = builder.code("invalidFormat").arg("label", new ResolvableArgument("mathForm.decimalField"))
|
|
||||||
.arg("format", "#,###.##").defaultMessage("Field must be in format #,###.##").build();
|
|
||||||
MockMessageSource messageSource = new MockMessageSource();
|
|
||||||
messageSource.addMessage("invalidFormat", Locale.US, "#{label} must be in format #{format}");
|
|
||||||
messageSource.addMessage("mathForm.decimalField", Locale.US, "Decimal Field");
|
|
||||||
String message = resolver.resolveMessage(messageSource, Locale.US);
|
|
||||||
assertEquals("Decimal Field must be in format #,###.##", message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
package org.springframework.context.message;
|
|
||||||
|
|
||||||
import java.text.MessageFormat;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.springframework.context.support.AbstractMessageSource;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
|
|
||||||
public class MockMessageSource extends AbstractMessageSource {
|
|
||||||
|
|
||||||
/** Map from 'code + locale' keys to message Strings */
|
|
||||||
private final Map<String, String> messages = new HashMap<String, String>();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected MessageFormat resolveCode(String code, Locale locale) {
|
|
||||||
throw new IllegalStateException("Should not be called");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String resolveCodeWithoutArguments(String code, Locale locale) {
|
|
||||||
return this.messages.get(code + "_" + locale.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Associate the given message with the given code.
|
|
||||||
* @param code the lookup code
|
|
||||||
* * @param locale the locale that the message should be found within
|
|
||||||
* @param msg the message associated with this lookup code
|
|
||||||
*/
|
|
||||||
public void addMessage(String code, Locale locale, String msg) {
|
|
||||||
Assert.notNull(code, "Code must not be null");
|
|
||||||
Assert.notNull(locale, "Locale must not be null");
|
|
||||||
Assert.notNull(msg, "Message must not be null");
|
|
||||||
this.messages.put(code + "_" + locale.toString(), msg);
|
|
||||||
if (logger.isDebugEnabled()) {
|
|
||||||
logger.debug("Added message [" + msg + "] for code [" + code + "] and Locale [" + locale + "]");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return getClass().getName() + ": " + this.messages;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,149 +0,0 @@
|
||||||
package org.springframework.mapping.support;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.springframework.mapping.MappingException;
|
|
||||||
import org.springframework.mapping.support.SpelMapper;
|
|
||||||
|
|
||||||
public class SpelMapperTests {
|
|
||||||
|
|
||||||
private SpelMapper mapper = new SpelMapper();
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void mapAutomatic() {
|
|
||||||
Map<String, Object> source = new HashMap<String, Object>();
|
|
||||||
source.put("name", "Keith");
|
|
||||||
source.put("age", 31);
|
|
||||||
|
|
||||||
Person target = new Person();
|
|
||||||
|
|
||||||
mapper.map(source, target);
|
|
||||||
|
|
||||||
assertEquals("Keith", target.name);
|
|
||||||
assertEquals(31, target.age);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void mapExplicit() throws MappingException {
|
|
||||||
mapper.setAutoMappingEnabled(false);
|
|
||||||
mapper.addMapping("name", "name");
|
|
||||||
|
|
||||||
Map<String, Object> source = new HashMap<String, Object>();
|
|
||||||
source.put("name", "Keith");
|
|
||||||
source.put("age", 31);
|
|
||||||
|
|
||||||
Person target = new Person();
|
|
||||||
|
|
||||||
mapper.map(source, target);
|
|
||||||
|
|
||||||
assertEquals("Keith", target.name);
|
|
||||||
assertEquals(0, target.age);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void mapAutomaticWithExplictOverrides() {
|
|
||||||
mapper.addMapping("test", "age");
|
|
||||||
|
|
||||||
Map<String, Object> source = new HashMap<String, Object>();
|
|
||||||
source.put("name", "Keith");
|
|
||||||
source.put("test", "3");
|
|
||||||
source.put("favoriteSport", "FOOTBALL");
|
|
||||||
|
|
||||||
Person target = new Person();
|
|
||||||
|
|
||||||
mapper.map(source, target);
|
|
||||||
|
|
||||||
assertEquals("Keith", target.name);
|
|
||||||
assertEquals(3, target.age);
|
|
||||||
assertEquals(Sport.FOOTBALL, target.favoriteSport);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void mapSameSourceFieldToMultipleTargets() {
|
|
||||||
mapper.addMapping("test", "name");
|
|
||||||
mapper.addMapping("test", "favoriteSport");
|
|
||||||
|
|
||||||
Map<String, Object> source = new HashMap<String, Object>();
|
|
||||||
source.put("test", "FOOTBALL");
|
|
||||||
|
|
||||||
Person target = new Person();
|
|
||||||
|
|
||||||
mapper.map(source, target);
|
|
||||||
|
|
||||||
assertEquals("FOOTBALL", target.name);
|
|
||||||
assertEquals(0, target.age);
|
|
||||||
assertEquals(Sport.FOOTBALL, target.favoriteSport);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void bean() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static class Employee {
|
|
||||||
|
|
||||||
private String name;
|
|
||||||
|
|
||||||
private int age;
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setName(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getAge() {
|
|
||||||
return age;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAge(int age) {
|
|
||||||
this.age = age;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Person {
|
|
||||||
|
|
||||||
private String name;
|
|
||||||
|
|
||||||
private int age;
|
|
||||||
|
|
||||||
private Sport favoriteSport;
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setName(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getAge() {
|
|
||||||
return age;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAge(int age) {
|
|
||||||
this.age = age;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Sport getFavoriteSport() {
|
|
||||||
return favoriteSport;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFavoriteSport(Sport favoriteSport) {
|
|
||||||
this.favoriteSport = favoriteSport;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum Sport {
|
|
||||||
FOOTBALL, BASKETBALL
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,278 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2004-2009 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.model.binder.support;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.springframework.context.alert.Severity;
|
|
||||||
import org.springframework.context.i18n.LocaleContextHolder;
|
|
||||||
import org.springframework.context.message.MockMessageSource;
|
|
||||||
import org.springframework.core.style.ToStringCreator;
|
|
||||||
import org.springframework.model.binder.Binder;
|
|
||||||
import org.springframework.model.binder.BindingResults;
|
|
||||||
import org.springframework.model.binder.MissingFieldException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Mark Fisher
|
|
||||||
* @since 3.0
|
|
||||||
*/
|
|
||||||
public class GenericBinderTests {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void simpleValues() {
|
|
||||||
Person person = new Person();
|
|
||||||
Map<String, Object> map = new LinkedHashMap<String, Object>();
|
|
||||||
map.put("name", "John Doe");
|
|
||||||
map.put("age", 42);
|
|
||||||
map.put("male", true);
|
|
||||||
Binder<Object> binder = new GenericBinder();
|
|
||||||
|
|
||||||
BindingResults results = binder.bind(map, person);
|
|
||||||
assertEquals(3, results.size());
|
|
||||||
assertEquals(3, results.successes().size());
|
|
||||||
assertEquals(0, results.failures().size());
|
|
||||||
assertEquals(0, results.errors().size());
|
|
||||||
assertEquals("name", results.get(0).getFieldName());
|
|
||||||
assertEquals("John Doe", results.get(0).getSubmittedValue());
|
|
||||||
assertEquals(false, results.get(0).isFailure());
|
|
||||||
assertEquals(Severity.INFO, results.get(0).getAlert().getSeverity());
|
|
||||||
assertEquals("bindSuccess", results.get(0).getAlert().getCode());
|
|
||||||
assertEquals("Successfully bound submitted value John Doe to field 'name'", results.get(0).getAlert().getMessage());
|
|
||||||
assertEquals("name", results.get("name").getFieldName());
|
|
||||||
assertEquals("John Doe", results.get("name").getSubmittedValue());
|
|
||||||
|
|
||||||
assertEquals("John Doe", person.name);
|
|
||||||
assertEquals(42, person.age);
|
|
||||||
assertTrue(person.male);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void nestedValues() {
|
|
||||||
Person person = new Person();
|
|
||||||
Map<String, Object> map = new HashMap<String, Object>();
|
|
||||||
map.put("pob.city", "Rome");
|
|
||||||
map.put("pob.country", "Italy");
|
|
||||||
Binder<Object> binder = new GenericBinder();
|
|
||||||
binder.bind(map, person);
|
|
||||||
assertNotNull(person.pob);
|
|
||||||
assertEquals("Rome", person.pob.city);
|
|
||||||
assertEquals("Italy", person.pob.country);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void mapValues() {
|
|
||||||
Person person = new Person();
|
|
||||||
Map<String, Object> map = new HashMap<String, Object>();
|
|
||||||
map.put("jobHistory['0']", "Clerk");
|
|
||||||
map.put("jobHistory['1']", "Plumber");
|
|
||||||
Binder<Object> binder = new GenericBinder();
|
|
||||||
binder.bind(map, person);
|
|
||||||
assertEquals("Clerk", person.jobHistory.get(0));
|
|
||||||
assertEquals("Plumber", person.jobHistory.get(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void typeMismatch() {
|
|
||||||
Person person = new Person();
|
|
||||||
Map<String, Object> map = new HashMap<String, Object>();
|
|
||||||
map.put("male", "bogus");
|
|
||||||
Binder<Object> binder = new GenericBinder();
|
|
||||||
BindingResults results = binder.bind(map, person);
|
|
||||||
assertEquals(1, results.size());
|
|
||||||
assertEquals(0, results.successes().size());
|
|
||||||
assertEquals(1, results.failures().size());
|
|
||||||
assertEquals(1, results.errors().size());
|
|
||||||
assertEquals("bogus", results.get(0).getSubmittedValue());
|
|
||||||
assertEquals("typeMismatch", results.get(0).getAlert().getCode());
|
|
||||||
assertEquals(Severity.ERROR, results.get(0).getAlert().getSeverity());
|
|
||||||
assertEquals("Failed to bind submitted value bogus to field 'male'; value could not be converted to type [boolean]", results.get(0).getAlert().getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void internalError() {
|
|
||||||
Person person = new Person();
|
|
||||||
Map<String, Object> map = new HashMap<String, Object>();
|
|
||||||
map.put("bogus", "bogus");
|
|
||||||
Binder<Object> binder = new GenericBinder();
|
|
||||||
BindingResults results = binder.bind(map, person);
|
|
||||||
assertEquals(1, results.size());
|
|
||||||
assertEquals(0, results.successes().size());
|
|
||||||
assertEquals(1, results.failures().size());
|
|
||||||
assertEquals(1, results.errors().size());
|
|
||||||
assertEquals("bogus", results.get(0).getSubmittedValue());
|
|
||||||
assertEquals("internalError", results.get(0).getAlert().getCode());
|
|
||||||
assertEquals(Severity.FATAL, results.get(0).getAlert().getSeverity());
|
|
||||||
assertEquals("An internal error occurred; message = [EL1034E:(pos 0): A problem occurred whilst attempting to set the property 'bogus': Unable to access property 'bogus' through setter]", results.get(0).getAlert().getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void fieldNotEditable() {
|
|
||||||
Person person = new Person();
|
|
||||||
Map<String, Object> map = new HashMap<String, Object>();
|
|
||||||
map.put("readOnly", "whatever");
|
|
||||||
Binder<Object> binder = new GenericBinder();
|
|
||||||
BindingResults results = binder.bind(map, person);
|
|
||||||
assertEquals(1, results.size());
|
|
||||||
assertEquals(0, results.successes().size());
|
|
||||||
assertEquals(1, results.failures().size());
|
|
||||||
assertEquals(0, results.errors().size());
|
|
||||||
assertEquals("whatever", results.get(0).getSubmittedValue());
|
|
||||||
assertEquals("fieldNotEditable", results.get(0).getAlert().getCode());
|
|
||||||
assertEquals(Severity.WARNING, results.get(0).getAlert().getSeverity());
|
|
||||||
assertEquals("Failed to bind submitted value whatever; field 'readOnly' is not editable", results.get(0).getAlert().getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void messageSource() {
|
|
||||||
Person person = new Person();
|
|
||||||
Map<String, Object> map = new HashMap<String, Object>();
|
|
||||||
map.put("male", "bogus");
|
|
||||||
GenericBinder binder = new GenericBinder();
|
|
||||||
MockMessageSource messageSource = new MockMessageSource();
|
|
||||||
messageSource.addMessage("typeMismatch", Locale.US, "Please enter true or false for the value of the #{label} field; you entered #{value}");
|
|
||||||
binder.setMessageSource(messageSource);
|
|
||||||
LocaleContextHolder.setLocale(Locale.US);
|
|
||||||
BindingResults results = binder.bind(map, person);
|
|
||||||
assertEquals("Please enter true or false for the value of the male field; you entered bogus", results.get(0).getAlert().getMessage());
|
|
||||||
LocaleContextHolder.setLocale(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void missingFields() {
|
|
||||||
Person person = new Person();
|
|
||||||
Map<String, Object> map = new HashMap<String, Object>();
|
|
||||||
GenericBinder binder = new GenericBinder();
|
|
||||||
binder.setRequiredFields(new String[] { "name", "age", "male" });
|
|
||||||
try {
|
|
||||||
binder.bind(map, person);
|
|
||||||
} catch (MissingFieldException e) {
|
|
||||||
assertEquals(3, e.getMissing().size());
|
|
||||||
assertEquals("name", e.getMissing().get(0));
|
|
||||||
assertEquals("age", e.getMissing().get(1));
|
|
||||||
assertEquals("male", e.getMissing().get(2));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Person {
|
|
||||||
|
|
||||||
private String name;
|
|
||||||
|
|
||||||
private int age;
|
|
||||||
|
|
||||||
private boolean male;
|
|
||||||
|
|
||||||
private PlaceOfBirth pob;
|
|
||||||
|
|
||||||
private Map<Integer, String> jobHistory;
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setName(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getAge() {
|
|
||||||
return age;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAge(int age) {
|
|
||||||
this.age = age;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isMale() {
|
|
||||||
return male;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMale(boolean male) {
|
|
||||||
this.male = male;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PlaceOfBirth getPob() {
|
|
||||||
return pob;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPob(PlaceOfBirth pob) {
|
|
||||||
this.pob = pob;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<Integer, String> getJobHistory() {
|
|
||||||
return jobHistory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setJobHistory(Map<Integer, String> jobHistory) {
|
|
||||||
this.jobHistory = jobHistory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBogus(String bogus) {
|
|
||||||
throw new RuntimeException("internal error");
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isReadOnly() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
return new ToStringCreator(this)
|
|
||||||
.append("name", name)
|
|
||||||
.append("age", age)
|
|
||||||
.append("male", male)
|
|
||||||
.append("pob", pob)
|
|
||||||
.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static class PlaceOfBirth {
|
|
||||||
|
|
||||||
private String city;
|
|
||||||
|
|
||||||
private String country;
|
|
||||||
|
|
||||||
public String getCity() {
|
|
||||||
return city;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCity(String city) {
|
|
||||||
this.city = city;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCountry() {
|
|
||||||
return country;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCountry(String country) {
|
|
||||||
this.country = country;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
return new ToStringCreator(this)
|
|
||||||
.append("city", city)
|
|
||||||
.append("country", country)
|
|
||||||
.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue