core context.message, context.alert, model.binder modules; includes SpEL-based GenericBinder implementation

This commit is contained in:
Keith Donald
2009-08-20 03:40:23 +00:00
parent 2bd664f7ee
commit 78304c0ccf
35 changed files with 2318 additions and 0 deletions

View File

@@ -0,0 +1,34 @@
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());
}
}

View File

@@ -0,0 +1,39 @@
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());
}
}

View File

@@ -0,0 +1,23 @@
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);
}
}

View File

@@ -0,0 +1,26 @@
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);
}
}

View File

@@ -0,0 +1,47 @@
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;
}
}

View File

@@ -0,0 +1,261 @@
/*
* 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;
/**
* @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);
}
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();
}
}
}