improved null handling and javadoc
This commit is contained in:
parent
0adcb2ad2e
commit
5f8faa3ae7
|
@ -16,6 +16,13 @@
|
|||
|
||||
package org.springframework.beans;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.beans.PropertyEditorSupport;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
|
@ -36,22 +43,23 @@ import java.util.TreeMap;
|
|||
import java.util.TreeSet;
|
||||
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import test.beans.BooleanTestBean;
|
||||
import test.beans.ITestBean;
|
||||
import test.beans.IndexedTestBean;
|
||||
import test.beans.NumberTestBean;
|
||||
import test.beans.TestBean;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowire;
|
||||
import org.springframework.beans.propertyeditors.CustomNumberEditor;
|
||||
import org.springframework.beans.propertyeditors.StringArrayPropertyEditor;
|
||||
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
|
||||
import org.springframework.beans.support.DerivedFromProtectedBaseBean;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.util.StopWatch;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import test.beans.BooleanTestBean;
|
||||
import test.beans.ITestBean;
|
||||
import test.beans.IndexedTestBean;
|
||||
import test.beans.NumberTestBean;
|
||||
import test.beans.TestBean;
|
||||
|
||||
/**
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
|
@ -61,6 +69,31 @@ import org.springframework.util.StringUtils;
|
|||
*/
|
||||
public final class BeanWrapperTests {
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testNullNestedTypeDescriptor() {
|
||||
Foo foo = new Foo();
|
||||
BeanWrapperImpl wrapper = new BeanWrapperImpl(foo);
|
||||
wrapper.setConversionService(new DefaultConversionService());
|
||||
wrapper.setAutoGrowNestedPaths(true);
|
||||
wrapper.setPropertyValue("listOfMaps[0]['luckyNumber']", "9");
|
||||
assertEquals(9, foo.listOfMaps.get(0).get("luckyNumber"));
|
||||
}
|
||||
|
||||
static class Foo {
|
||||
|
||||
private List<Map> listOfMaps;
|
||||
|
||||
public List<Map> getListOfMaps() {
|
||||
return listOfMaps;
|
||||
}
|
||||
|
||||
public void setListOfMaps(List<Map> listOfMaps) {
|
||||
this.listOfMaps = listOfMaps;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsReadablePropertyNotReadable() {
|
||||
NoRead nr = new NoRead();
|
||||
|
|
|
@ -30,6 +30,7 @@ public interface ConversionService {
|
|||
* @param sourceType the source type to convert from (required)
|
||||
* @param targetType the target type to convert to (required)
|
||||
* @return true if a conversion can be performed, false if not
|
||||
* @throws IllegalArgumentException if targetType is null
|
||||
*/
|
||||
boolean canConvert(Class<?> sourceType, Class<?> targetType);
|
||||
|
||||
|
@ -39,6 +40,7 @@ public interface ConversionService {
|
|||
* @param targetType the target type to convert to (required)
|
||||
* @return the converted object, an instance of targetType
|
||||
* @throws ConversionException if an exception occurred
|
||||
* @throws IllegalArgumentException if targetType is null
|
||||
*/
|
||||
<T> T convert(Object source, Class<T> targetType);
|
||||
|
||||
|
@ -49,6 +51,8 @@ public interface ConversionService {
|
|||
* @param sourceType context about the source type to convert from (required)
|
||||
* @param targetType context about the target type to convert to (required)
|
||||
* @return true if a conversion can be performed between the source and target types, false if not
|
||||
* @throws IllegalArgumentException if targetType is null
|
||||
* @see TypeDescriptor#forObject(Object)
|
||||
*/
|
||||
boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType);
|
||||
|
||||
|
@ -57,10 +61,13 @@ public interface ConversionService {
|
|||
* The TypeDescriptors provide additional context about the field locations where conversion will occur, often object property locations.
|
||||
* This flavor of the convert operation exists mainly for use by a general purpose data mapping framework, and not for use by user code.
|
||||
* @param source the source object to convert (may be null)
|
||||
* @param sourceType context about the source type converting from (required)
|
||||
* @param sourceType context about the source type converting from (may be null if source is null)
|
||||
* @param targetType context about the target type to convert to (required)
|
||||
* @return the converted object, an instance of {@link TypeDescriptor#getObjectType() targetType}</code>
|
||||
* @throws ConversionException if an exception occurred
|
||||
* @throws IllegalArgumentException if targetType is null
|
||||
* @throws IllegalArgumentException if sourceType is null but source is not null
|
||||
* @see TypeDescriptor#forObject(Object)
|
||||
*/
|
||||
Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);
|
||||
|
||||
|
|
|
@ -144,10 +144,12 @@ public class TypeDescriptor {
|
|||
* If the methodParameter is a List<List<String>> and the nestingLevel is 2, the nested type descriptor will also be a String.class.
|
||||
* If the methodParameter is a Map<Integer, String> and the nesting level is 1, the nested type descriptor will be String, derived from the map value.
|
||||
* If the methodParameter is a List<Map<Integer, String>> and the nesting level is 2, the nested type descriptor will be String, derived from the map value.
|
||||
* Returns null if a nested type cannot be obtained because it was not declared.
|
||||
* For example, if the method parameter is a List<?>, the nested type descriptor returned will be null.
|
||||
* @param methodParameter the method parameter with a nestingLevel of 1
|
||||
* @param nestingLevel the nesting level of the collection/array element or map key/value declaration within the method parameter.
|
||||
* @return the nested type descriptor
|
||||
* @throws IllegalArgumentException if the method parameter is not of a collection, array, or map type.
|
||||
* @return the nested type descriptor at the specified nesting level, or null if it could not be obtained.
|
||||
* @throws IllegalArgumentException if the types up to the specified nesting level are not of collection, array, or map types.
|
||||
*/
|
||||
public static TypeDescriptor nested(MethodParameter methodParameter, int nestingLevel) {
|
||||
return nested(new ParameterDescriptor(methodParameter), nestingLevel);
|
||||
|
@ -159,10 +161,12 @@ public class TypeDescriptor {
|
|||
* If the field is a List<List<String>> and the nestingLevel is 2, the nested type descriptor will also be a String.class.
|
||||
* If the field is a Map<Integer, String> and the nestingLevel is 1, the nested type descriptor will be String, derived from the map value.
|
||||
* If the field is a List<Map<Integer, String>> and the nestingLevel is 2, the nested type descriptor will be String, derived from the map value.
|
||||
* Returns null if a nested type cannot be obtained because it was not declared.
|
||||
* For example, if the field is a List<?>, the nested type descriptor returned will be null.
|
||||
* @param field the field
|
||||
* @param nestingLevel the nesting level of the collection/array element or map key/value declaration within the field.
|
||||
* @return the nested type descriptor
|
||||
* @throws IllegalArgumentException if the field is not of a collection, array, or map type.
|
||||
* @return the nested type descriptor at the specified nestingLevel, or null if it could not be obtained
|
||||
* @throws IllegalArgumentException if the types up to the specified nesting level are not of collection, array, or map types.
|
||||
*/
|
||||
public static TypeDescriptor nested(Field field, int nestingLevel) {
|
||||
return nested(new FieldDescriptor(field), nestingLevel);
|
||||
|
@ -174,10 +178,12 @@ public class TypeDescriptor {
|
|||
* If the property is a List<List<String>> and the nestingLevel is 2, the nested type descriptor will also be a String.class.
|
||||
* If the field is a Map<Integer, String> and the nestingLevel is 1, the nested type descriptor will be String, derived from the map value.
|
||||
* If the property is a List<Map<Integer, String>> and the nestingLevel is 2, the nested type descriptor will be String, derived from the map value.
|
||||
* Returns null if a nested type cannot be obtained because it was not declared.
|
||||
* For example, if the property is a List<?>, the nested type descriptor returned will be null.
|
||||
* @param property the property
|
||||
* @param nestingLevel the nesting level of the collection/array element or map key/value declaration within the property.
|
||||
* @return the nested type descriptor
|
||||
* @throws IllegalArgumentException if the property is not of a collection, array, or map type.
|
||||
* @return the nested type descriptor at the specified nestingLevel, or null if it could not be obtained
|
||||
* @throws IllegalArgumentException if the types up to the specified nesting level are not of collection, array, or map types.
|
||||
*/
|
||||
public static TypeDescriptor nested(Property property, int nestingLevel) {
|
||||
return nested(new BeanPropertyDescriptor(property), nestingLevel);
|
||||
|
|
|
@ -133,7 +133,10 @@ public class GenericConversionService implements ConfigurableConversionService {
|
|||
// implementing ConversionService
|
||||
|
||||
public boolean canConvert(Class<?> sourceType, Class<?> targetType) {
|
||||
return canConvert(TypeDescriptor.valueOf(sourceType), TypeDescriptor.valueOf(targetType));
|
||||
if (targetType == null) {
|
||||
throw new IllegalArgumentException("The targetType to convert to cannot be null");
|
||||
}
|
||||
return canConvert(sourceType != null ? TypeDescriptor.valueOf(sourceType) : null, TypeDescriptor.valueOf(targetType));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
@ -145,6 +148,12 @@ public class GenericConversionService implements ConfigurableConversionService {
|
|||
}
|
||||
|
||||
public boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
if (targetType == null) {
|
||||
throw new IllegalArgumentException("The targetType to convert to cannot be null");
|
||||
}
|
||||
if (sourceType == null) {
|
||||
return true;
|
||||
}
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Checking if I can convert " + sourceType + " to " + targetType);
|
||||
}
|
||||
|
|
|
@ -50,6 +50,43 @@ public class GenericConversionServiceTests {
|
|||
|
||||
private GenericConversionService conversionService = new GenericConversionService();
|
||||
|
||||
@Test
|
||||
public void canConvert() {
|
||||
assertFalse(conversionService.canConvert(String.class, Integer.class));
|
||||
conversionService.addConverterFactory(new StringToNumberConverterFactory());
|
||||
assertTrue(conversionService.canConvert(String.class, Integer.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canConvertAssignable() {
|
||||
assertTrue(conversionService.canConvert(String.class, String.class));
|
||||
assertTrue(conversionService.canConvert(Integer.class, Number.class));
|
||||
assertTrue(conversionService.canConvert(boolean.class, boolean.class));
|
||||
assertTrue(conversionService.canConvert(boolean.class, Boolean.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canConvertIllegalArgumentNullTargetType() {
|
||||
try {
|
||||
assertFalse(conversionService.canConvert(String.class, null));
|
||||
fail("Should have failed");
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
||||
}
|
||||
try {
|
||||
assertFalse(conversionService.canConvert(TypeDescriptor.valueOf(String.class), null));
|
||||
fail("Should have failed");
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canConvertNullSourceType() {
|
||||
assertTrue(conversionService.canConvert(null, Integer.class));
|
||||
assertTrue(conversionService.canConvert(null, TypeDescriptor.valueOf(Integer.class)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convert() {
|
||||
conversionService.addConverterFactory(new StringToNumberConverterFactory());
|
||||
|
|
Loading…
Reference in New Issue