Browse Source

restored original GenericConversionService behavior with respect to empty collections/maps; restored original FormattingConversionService behavior with respect to the use of subtypes; fixed collection element resolution when using a ConversionService with a DataBinder

3.0.x
Juergen Hoeller 15 years ago
parent
commit
43f8eca91b
  1. 4
      org.springframework.beans/src/main/java/org/springframework/beans/TypeConverterDelegate.java
  2. 6
      org.springframework.context/src/main/java/org/springframework/format/support/FormattingConversionService.java
  3. 71
      org.springframework.context/src/test/java/org/springframework/format/support/FormattingConversionServiceTests.java
  4. 42
      org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/annotation/ServletAnnotationControllerTests.java

4
org.springframework.beans/src/main/java/org/springframework/beans/TypeConverterDelegate.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 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.
@ -136,7 +136,7 @@ class TypeConverterDelegate { @@ -136,7 +136,7 @@ class TypeConverterDelegate {
ConversionService conversionService = this.propertyEditorRegistry.getConversionService();
if (editor == null && conversionService != null && convertedValue != null) {
TypeDescriptor sourceTypeDesc = TypeDescriptor.forObject(convertedValue);
TypeDescriptor targetTypeDesc = typeDescriptor.forElementType(requiredType);
TypeDescriptor targetTypeDesc = typeDescriptor;
if (conversionService.canConvert(sourceTypeDesc, targetTypeDesc)) {
return (T) conversionService.convert(convertedValue, sourceTypeDesc, targetTypeDesc);
}

6
org.springframework.context/src/main/java/org/springframework/format/support/FormattingConversionService.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 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.
@ -95,7 +95,7 @@ public class FormattingConversionService extends GenericConversionService @@ -95,7 +95,7 @@ public class FormattingConversionService extends GenericConversionService
return (sourceType.getAnnotation(annotationType) != null);
}
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
FieldFormatterKey key = new FieldFormatterKey(sourceType.getAnnotation(annotationType), fieldType);
FieldFormatterKey key = new FieldFormatterKey(sourceType.getAnnotation(annotationType), sourceType.getType());
GenericConverter converter = cachedPrinters.get(key);
if (converter == null) {
Printer<?> printer = annotationFormatterFactory.getPrinter(key.getAnnotation(), key.getFieldType());
@ -117,7 +117,7 @@ public class FormattingConversionService extends GenericConversionService @@ -117,7 +117,7 @@ public class FormattingConversionService extends GenericConversionService
return (targetType.getAnnotation(annotationType) != null);
}
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
FieldFormatterKey key = new FieldFormatterKey(targetType.getAnnotation(annotationType), fieldType);
FieldFormatterKey key = new FieldFormatterKey(targetType.getAnnotation(annotationType), sourceType.getType());
GenericConverter converter = cachedParsers.get(key);
if (converter == null) {
Parser<?> printer = annotationFormatterFactory.getParser(key.getAnnotation(), key.getFieldType());

71
org.springframework.context/src/test/java/org/springframework/format/support/FormattingConversionServiceTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 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.
@ -27,12 +27,11 @@ import org.joda.time.DateTime; @@ -27,12 +27,11 @@ import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.junit.After;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.ConfigurablePropertyAccessor;
import org.springframework.beans.PropertyAccessorFactory;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.beans.factory.support.RootBeanDefinition;
@ -41,11 +40,14 @@ import org.springframework.context.support.GenericApplicationContext; @@ -41,11 +40,14 @@ import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.support.ConversionServiceFactory;
import org.springframework.format.Printer;
import org.springframework.format.datetime.joda.DateTimeParser;
import org.springframework.format.datetime.joda.JodaDateTimeFormatAnnotationFormatterFactory;
import org.springframework.format.datetime.joda.ReadablePartialPrinter;
import org.springframework.format.number.NumberFormatter;
import static org.junit.Assert.*;
/**
* @author Keith Donald
* @author Juergen Hoeller
@ -93,7 +95,13 @@ public class FormattingConversionServiceTests { @@ -93,7 +95,13 @@ public class FormattingConversionServiceTests {
@Test
public void testFormatFieldForAnnotation() throws Exception {
formattingService.addFormatterForFieldAnnotation(new JodaDateTimeFormatAnnotationFormatterFactory());
doTestFormatFieldForAnnotation(Model.class);
doTestFormatFieldForAnnotation(Model.class, false);
}
@Test
public void testFormatFieldForAnnotationWithDirectFieldAccess() throws Exception {
formattingService.addFormatterForFieldAnnotation(new JodaDateTimeFormatAnnotationFormatterFactory());
doTestFormatFieldForAnnotation(Model.class, true);
}
@Test
@ -108,7 +116,7 @@ public class FormattingConversionServiceTests { @@ -108,7 +116,7 @@ public class FormattingConversionServiceTests {
context.refresh();
context.getBeanFactory().initializeBean(formattingService, "formattingService");
formattingService.addFormatterForFieldAnnotation(new JodaDateTimeFormatAnnotationFormatterFactory());
doTestFormatFieldForAnnotation(ModelWithPlaceholders.class);
doTestFormatFieldForAnnotation(ModelWithPlaceholders.class, false);
}
@Test
@ -123,10 +131,10 @@ public class FormattingConversionServiceTests { @@ -123,10 +131,10 @@ public class FormattingConversionServiceTests {
context.getBeanFactory().registerSingleton("ppc", ppc);
context.refresh();
formattingService = context.getBean("formattingService", FormattingConversionService.class);
doTestFormatFieldForAnnotation(ModelWithPlaceholders.class);
doTestFormatFieldForAnnotation(ModelWithPlaceholders.class, false);
}
private void doTestFormatFieldForAnnotation(Class<?> modelClass) throws Exception {
private void doTestFormatFieldForAnnotation(Class<?> modelClass, boolean directFieldAccess) throws Exception {
formattingService.addConverter(new Converter<Date, Long>() {
public Long convert(Date source) {
return source.getTime();
@ -159,13 +167,15 @@ public class FormattingConversionServiceTests { @@ -159,13 +167,15 @@ public class FormattingConversionServiceTests {
assertEquals(new LocalDate(2009, 11, 2), new LocalDate(dates.get(2)));
Object model = BeanUtils.instantiate(modelClass);
BeanWrapper accessor = PropertyAccessorFactory.forBeanPropertyAccess(model);
ConfigurablePropertyAccessor accessor = directFieldAccess ? PropertyAccessorFactory.forDirectFieldAccess(model) :
PropertyAccessorFactory.forBeanPropertyAccess(model);
accessor.setConversionService(formattingService);
accessor.setPropertyValue("dates", "10-31-09,11-1-09,11-2-09");
dates = (List<Date>) accessor.getPropertyValue("dates");
assertEquals(new LocalDate(2009, 10, 31), new LocalDate(dates.get(0)));
assertEquals(new LocalDate(2009, 11, 1), new LocalDate(dates.get(1)));
assertEquals(new LocalDate(2009, 11, 2), new LocalDate(dates.get(2)));
if (!directFieldAccess) {
accessor.setPropertyValue("dates[0]", "10-30-09");
accessor.setPropertyValue("dates[1]", "10-1-09");
accessor.setPropertyValue("dates[2]", "10-2-09");
@ -174,11 +184,13 @@ public class FormattingConversionServiceTests { @@ -174,11 +184,13 @@ public class FormattingConversionServiceTests {
assertEquals(new LocalDate(2009, 10, 1), new LocalDate(dates.get(1)));
assertEquals(new LocalDate(2009, 10, 2), new LocalDate(dates.get(2)));
}
}
@Test
public void testPrintNull() throws ParseException {
formattingService.addFormatterForFieldType(Number.class, new NumberFormatter());
assertEquals("", formattingService.convert(null, TypeDescriptor.valueOf(Integer.class), TypeDescriptor.valueOf(String.class)));
assertEquals("", formattingService
.convert(null, TypeDescriptor.valueOf(Integer.class), TypeDescriptor.valueOf(String.class)));
}
@Test
@ -190,7 +202,8 @@ public class FormattingConversionServiceTests { @@ -190,7 +202,8 @@ public class FormattingConversionServiceTests {
@Test
public void testParseEmptyString() throws ParseException {
formattingService.addFormatterForFieldType(Number.class, new NumberFormatter());
assertNull(formattingService.convert("", TypeDescriptor.valueOf(String.class), TypeDescriptor.valueOf(Integer.class)));
assertNull(formattingService
.convert("", TypeDescriptor.valueOf(String.class), TypeDescriptor.valueOf(Integer.class)));
}
@Test
@ -208,14 +221,35 @@ public class FormattingConversionServiceTests { @@ -208,14 +221,35 @@ public class FormattingConversionServiceTests {
assertNull(formattingService.convert("", TypeDescriptor.valueOf(String.class), TypeDescriptor.valueOf(Integer.class)));
}
@Test
public void testFormatFieldForAnnotationWithSubclassAsFieldType() throws Exception {
formattingService.addFormatterForFieldAnnotation(new JodaDateTimeFormatAnnotationFormatterFactory() {
public Printer<?> getPrinter(org.springframework.format.annotation.DateTimeFormat annotation, Class<?> fieldType) {
assertEquals(MyDate.class, fieldType);
return super.getPrinter(annotation, fieldType);
}
});
formattingService.addConverter(new Converter<MyDate, Long>() {
public Long convert(MyDate source) {
return source.getTime();
}
});
formattingService.addConverter(new Converter<MyDate, Date>() {
public Date convert(MyDate source) {
return source;
}
});
formattingService.convert(new MyDate(), new TypeDescriptor(ModelWithSubclassField.class.getField("date")),
TypeDescriptor.valueOf(String.class));
}
public static class Model {
@SuppressWarnings("unused")
@org.springframework.format.annotation.DateTimeFormat(style="S-")
public Date date;
@SuppressWarnings("unused")
@org.springframework.format.annotation.DateTimeFormat(pattern="M-d-yy")
public List<Date> dates;
@ -231,11 +265,9 @@ public class FormattingConversionServiceTests { @@ -231,11 +265,9 @@ public class FormattingConversionServiceTests {
public static class ModelWithPlaceholders {
@SuppressWarnings("unused")
@org.springframework.format.annotation.DateTimeFormat(style="${dateStyle}")
public Date date;
@SuppressWarnings("unused")
@org.springframework.format.annotation.DateTimeFormat(pattern="${datePattern}")
public List<Date> dates;
@ -248,4 +280,15 @@ public class FormattingConversionServiceTests { @@ -248,4 +280,15 @@ public class FormattingConversionServiceTests {
}
}
public static class MyDate extends Date {
}
private static class ModelWithSubclassField {
@org.springframework.format.annotation.DateTimeFormat(style = "S-")
public MyDate date;
}
}

42
org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/annotation/ServletAnnotationControllerTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 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.
@ -50,7 +50,6 @@ import javax.validation.Valid; @@ -50,7 +50,6 @@ import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import javax.xml.bind.annotation.XmlRootElement;
import static org.junit.Assert.*;
import org.junit.Test;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
@ -134,6 +133,8 @@ import org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMap @@ -134,6 +133,8 @@ import org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMap
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.util.NestedServletException;
import static org.junit.Assert.*;
/**
* @author Juergen Hoeller
* @author Sam Brannen
@ -1156,6 +1157,7 @@ public class ServletAnnotationControllerTests { @@ -1156,6 +1157,7 @@ public class ServletAnnotationControllerTests {
MockHttpServletResponse response = new MockHttpServletResponse();
try {
servlet.service(request, response);
fail("Didn't fail with due to ambiguous method mapping");
}
catch (NestedServletException ex) {
assertTrue(ex.getCause() instanceof IllegalStateException);
@ -1815,7 +1817,7 @@ public class ServletAnnotationControllerTests { @@ -1815,7 +1817,7 @@ public class ServletAnnotationControllerTests {
}
@Test
public void parameterCsvAsStringArray() throws Exception {
public void parameterCsvAsIntegerArray() throws Exception {
servlet = new DispatcherServlet() {
@Override
protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
@ -1842,6 +1844,34 @@ public class ServletAnnotationControllerTests { @@ -1842,6 +1844,34 @@ public class ServletAnnotationControllerTests {
assertEquals("1-2", response.getContentAsString());
}
@Test
public void parameterCsvAsIntegerSet() throws Exception {
servlet = new DispatcherServlet() {
@Override
protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
GenericWebApplicationContext wac = new GenericWebApplicationContext();
wac.registerBeanDefinition("controller", new RootBeanDefinition(CsvController.class));
RootBeanDefinition csDef = new RootBeanDefinition(FormattingConversionServiceFactoryBean.class);
RootBeanDefinition wbiDef = new RootBeanDefinition(ConfigurableWebBindingInitializer.class);
wbiDef.getPropertyValues().add("conversionService", csDef);
RootBeanDefinition adapterDef = new RootBeanDefinition(AnnotationMethodHandlerAdapter.class);
adapterDef.getPropertyValues().add("webBindingInitializer", wbiDef);
wac.registerBeanDefinition("handlerAdapter", adapterDef);
wac.refresh();
return wac;
}
};
servlet.init(new MockServletConfig());
MockHttpServletRequest request = new MockHttpServletRequest();
request.setRequestURI("/integerSet");
request.setMethod("POST");
request.addParameter("content", "1,2");
MockHttpServletResponse response = new MockHttpServletResponse();
servlet.service(request, response);
assertEquals("1-2", response.getContentAsString());
}
/*
* Controllers
@ -3102,6 +3132,12 @@ public class ServletAnnotationControllerTests { @@ -3102,6 +3132,12 @@ public class ServletAnnotationControllerTests {
public void processCsv(@RequestParam("content") Integer[] content, HttpServletResponse response) throws IOException {
response.getWriter().write(StringUtils.arrayToDelimitedString(content, "-"));
}
@RequestMapping("/integerSet")
public void processCsv(@RequestParam("content") Set<Integer> content, HttpServletResponse response) throws IOException {
assertTrue(content.iterator().next() instanceof Integer);
response.getWriter().write(StringUtils.collectionToDelimitedString(content, "-"));
}
}
}

Loading…
Cancel
Save