removed dependency on java.beans
This commit is contained in:
parent
94d690fb2c
commit
c09227a712
|
|
@ -43,6 +43,7 @@ import org.springframework.core.MethodParameter;
|
|||
import org.springframework.core.convert.ConversionException;
|
||||
import org.springframework.core.convert.ConverterNotFoundException;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.TypeDescriptor.Property;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
|
@ -369,11 +370,11 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
|||
if (pd != null) {
|
||||
if (tokens.keys != null) {
|
||||
if (pd.getReadMethod() != null || pd.getWriteMethod() != null) {
|
||||
return TypeDescriptor.nested(nestedBw.getWrappedClass(), pd, tokens.keys.length);
|
||||
return TypeDescriptor.nested(property(pd), tokens.keys.length);
|
||||
}
|
||||
} else {
|
||||
if (pd.getReadMethod() != null || pd.getWriteMethod() != null) {
|
||||
return new TypeDescriptor(nestedBw.getWrappedClass(), pd);
|
||||
return new TypeDescriptor(property(pd));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -493,7 +494,7 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
|||
throws TypeMismatchException {
|
||||
GenericTypeAwarePropertyDescriptor gpd = (GenericTypeAwarePropertyDescriptor) pd;
|
||||
Class<?> beanClass = gpd.getBeanClass();
|
||||
return convertIfNecessary(propertyName, oldValue, newValue, pd.getPropertyType(), new TypeDescriptor(beanClass, pd));
|
||||
return convertIfNecessary(propertyName, oldValue, newValue, pd.getPropertyType(), new TypeDescriptor(property(pd)));
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -948,7 +949,7 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
|||
if (isExtractOldValueForEditor() && arrayIndex < Array.getLength(propValue)) {
|
||||
oldValue = Array.get(propValue, arrayIndex);
|
||||
}
|
||||
Object convertedValue = convertIfNecessary(propertyName, oldValue, pv.getValue(), requiredType, TypeDescriptor.nested(getWrappedClass(), pd, tokens.keys.length));
|
||||
Object convertedValue = convertIfNecessary(propertyName, oldValue, pv.getValue(), requiredType, TypeDescriptor.nested(property(pd), tokens.keys.length));
|
||||
// TODO review this grow algorithm along side the null gap algorithm for setting lists below ... the two are inconsistent
|
||||
propValue = growArrayIfNecessary(propValue, arrayIndex, actualName);
|
||||
Array.set(propValue, arrayIndex, convertedValue);
|
||||
|
|
@ -968,7 +969,7 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
|||
if (isExtractOldValueForEditor() && index < list.size()) {
|
||||
oldValue = list.get(index);
|
||||
}
|
||||
Object convertedValue = convertIfNecessary(propertyName, oldValue, pv.getValue(), requiredType, TypeDescriptor.nested(getWrappedClass(), pd, tokens.keys.length));
|
||||
Object convertedValue = convertIfNecessary(propertyName, oldValue, pv.getValue(), requiredType, TypeDescriptor.nested(property(pd), tokens.keys.length));
|
||||
if (index < list.size()) {
|
||||
list.set(index, convertedValue);
|
||||
}
|
||||
|
|
@ -1005,7 +1006,7 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
|||
// Pass full property name and old value in here, since we want full
|
||||
// conversion ability for map values.
|
||||
Object convertedMapValue = convertIfNecessary(
|
||||
propertyName, oldValue, pv.getValue(), mapValueType, TypeDescriptor.nested(getWrappedClass(), pd, tokens.keys.length));
|
||||
propertyName, oldValue, pv.getValue(), mapValueType, TypeDescriptor.nested(property(pd), tokens.keys.length));
|
||||
map.put(convertedMapKey, convertedMapValue);
|
||||
}
|
||||
else {
|
||||
|
|
@ -1167,5 +1168,10 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
|||
|
||||
public String[] keys;
|
||||
}
|
||||
|
||||
private Property property(PropertyDescriptor pd) {
|
||||
GenericTypeAwarePropertyDescriptor typeAware = (GenericTypeAwarePropertyDescriptor) pd;
|
||||
return new Property(typeAware.getBeanClass(), typeAware.getReadMethod(), typeAware.getWriteMethod());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ abstract class AbstractDescriptor {
|
|||
|
||||
private final Class<?> type;
|
||||
|
||||
public AbstractDescriptor(Class<?> type) {
|
||||
protected AbstractDescriptor(Class<?> type) {
|
||||
if (type == null) {
|
||||
throw new IllegalArgumentException("type cannot be null");
|
||||
}
|
||||
|
|
@ -93,15 +93,15 @@ abstract class AbstractDescriptor {
|
|||
// internal helpers
|
||||
|
||||
private boolean isCollection() {
|
||||
return getType() != null && Collection.class.isAssignableFrom(getType());
|
||||
return Collection.class.isAssignableFrom(getType());
|
||||
}
|
||||
|
||||
private boolean isArray() {
|
||||
return getType() != null && getType().isArray();
|
||||
return getType().isArray();
|
||||
}
|
||||
|
||||
private boolean isMap() {
|
||||
return getType() != null && Map.class.isAssignableFrom(getType());
|
||||
return Map.class.isAssignableFrom(getType());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -15,35 +15,25 @@
|
|||
*/
|
||||
package org.springframework.core.convert;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.core.GenericCollectionTypeResolver;
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.core.convert.TypeDescriptor.Property;
|
||||
|
||||
class BeanPropertyDescriptor extends AbstractDescriptor {
|
||||
|
||||
private final Class<?> beanClass;
|
||||
|
||||
private final PropertyDescriptor property;
|
||||
private final Property property;
|
||||
|
||||
private final MethodParameter methodParameter;
|
||||
|
||||
private final Annotation[] annotations;
|
||||
|
||||
public BeanPropertyDescriptor(Class<?> beanClass, PropertyDescriptor property) {
|
||||
super(property.getPropertyType());
|
||||
this.beanClass = beanClass;
|
||||
public BeanPropertyDescriptor(Property property) {
|
||||
super(property.getType());
|
||||
this.property = property;
|
||||
this.methodParameter = resolveMethodParameter();
|
||||
this.annotations = resolveAnnotations();
|
||||
this.methodParameter = property.getMethodParameter();
|
||||
this.annotations = property.getAnnotations();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -71,79 +61,13 @@ class BeanPropertyDescriptor extends AbstractDescriptor {
|
|||
MethodParameter methodParameter = new MethodParameter(this.methodParameter);
|
||||
methodParameter.increaseNestingLevel();
|
||||
methodParameter.setTypeIndexForCurrentLevel(typeIndex);
|
||||
return new BeanPropertyDescriptor(type, beanClass, property, methodParameter, annotations);
|
||||
return new BeanPropertyDescriptor(type, property, methodParameter, annotations);
|
||||
}
|
||||
|
||||
// internal
|
||||
|
||||
private MethodParameter resolveMethodParameter() {
|
||||
MethodParameter parameter = parameterForPropertyMethod();
|
||||
// needed to resolve generic property types that parameterized by sub-classes e.g. T getFoo();
|
||||
GenericTypeResolver.resolveParameterType(parameter, beanClass);
|
||||
return parameter;
|
||||
}
|
||||
|
||||
private MethodParameter parameterForPropertyMethod() {
|
||||
if (property.getReadMethod() != null) {
|
||||
return new MethodParameter(property.getReadMethod(), -1);
|
||||
} else if (property.getWriteMethod() != null) {
|
||||
return new MethodParameter(property.getWriteMethod(), 0);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Property is neither readable or writeable");
|
||||
}
|
||||
}
|
||||
|
||||
private Annotation[] resolveAnnotations() {
|
||||
Map<Class<?>, Annotation> annMap = new LinkedHashMap<Class<?>, Annotation>();
|
||||
Method readMethod = this.property.getReadMethod();
|
||||
if (readMethod != null) {
|
||||
for (Annotation ann : readMethod.getAnnotations()) {
|
||||
annMap.put(ann.annotationType(), ann);
|
||||
}
|
||||
}
|
||||
Method writeMethod = this.property.getWriteMethod();
|
||||
if (writeMethod != null) {
|
||||
for (Annotation ann : writeMethod.getAnnotations()) {
|
||||
annMap.put(ann.annotationType(), ann);
|
||||
}
|
||||
}
|
||||
Field field = getField();
|
||||
if (field != null) {
|
||||
for (Annotation ann : field.getAnnotations()) {
|
||||
annMap.put(ann.annotationType(), ann);
|
||||
}
|
||||
}
|
||||
return annMap.values().toArray(new Annotation[annMap.size()]);
|
||||
}
|
||||
|
||||
private Field getField() {
|
||||
String name = this.property.getName();
|
||||
if (!StringUtils.hasLength(name)) {
|
||||
return null;
|
||||
}
|
||||
Class<?> declaringClass = declaringClass();
|
||||
Field field = ReflectionUtils.findField(declaringClass, name);
|
||||
if (field == null) {
|
||||
// Same lenient fallback checking as in CachedIntrospectionResults...
|
||||
field = ReflectionUtils.findField(declaringClass, name.substring(0, 1).toLowerCase() + name.substring(1));
|
||||
if (field == null) {
|
||||
field = ReflectionUtils.findField(declaringClass, name.substring(0, 1).toUpperCase() + name.substring(1));
|
||||
}
|
||||
}
|
||||
return field;
|
||||
}
|
||||
|
||||
private Class<?> declaringClass() {
|
||||
if (this.property.getReadMethod() != null) {
|
||||
return this.property.getReadMethod().getDeclaringClass();
|
||||
} else {
|
||||
return this.property.getWriteMethod().getDeclaringClass();
|
||||
}
|
||||
}
|
||||
|
||||
private BeanPropertyDescriptor(Class<?> type, Class<?> beanClass, java.beans.PropertyDescriptor propertyDescriptor, MethodParameter methodParameter, Annotation[] annotations) {
|
||||
private BeanPropertyDescriptor(Class<?> type, Property propertyDescriptor, MethodParameter methodParameter, Annotation[] annotations) {
|
||||
super(type);
|
||||
this.beanClass = beanClass;
|
||||
this.property = propertyDescriptor;
|
||||
this.methodParameter = methodParameter;
|
||||
this.annotations = annotations;
|
||||
|
|
|
|||
|
|
@ -13,19 +13,22 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.core.convert;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Context about a type to convert from or to.
|
||||
|
|
@ -91,11 +94,10 @@ public class TypeDescriptor {
|
|||
/**
|
||||
* Create a new type descriptor for a bean property.
|
||||
* Use this constructor when a target conversion point is a property on a Java class.
|
||||
* @param beanClass the class that declares the property
|
||||
* @param property the property descriptor
|
||||
* @param property the property
|
||||
*/
|
||||
public TypeDescriptor(Class<?> beanClass, PropertyDescriptor property) {
|
||||
this(new BeanPropertyDescriptor(beanClass, property));
|
||||
public TypeDescriptor(Property property) {
|
||||
this(new BeanPropertyDescriptor(property));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -140,7 +142,7 @@ public class TypeDescriptor {
|
|||
}
|
||||
return new TypeDescriptor(mapType, keyType, valueType);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a type descriptor for a nested type declared within the method parameter.
|
||||
* For example, if the methodParameter is a List<String> and the nestingLevel is 1, the nested type descriptor will be String.class.
|
||||
|
|
@ -182,8 +184,8 @@ public class TypeDescriptor {
|
|||
* @return the nested type descriptor
|
||||
* @throws IllegalArgumentException if the property is not of a collection, array, or map type.
|
||||
*/
|
||||
public static TypeDescriptor nested(Class<?> beanClass, PropertyDescriptor property, int nestingLevel) {
|
||||
return nested(new BeanPropertyDescriptor(beanClass, property), nestingLevel);
|
||||
public static TypeDescriptor nested(Property property, int nestingLevel) {
|
||||
return nested(new BeanPropertyDescriptor(property), nestingLevel);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -196,7 +198,7 @@ public class TypeDescriptor {
|
|||
public static TypeDescriptor forObject(Object source) {
|
||||
return source != null ? valueOf(source.getClass()) : null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine the declared (non-generic) type of the wrapped parameter/field.
|
||||
* @return the declared type, or <code>null</code> if this is {@link TypeDescriptor#NULL}
|
||||
|
|
@ -230,7 +232,7 @@ public class TypeDescriptor {
|
|||
}
|
||||
return new TypeDescriptor(value.getClass(), elementType, mapKeyType, mapValueType, annotations);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name of this type: the fully qualified class name.
|
||||
*/
|
||||
|
|
@ -288,7 +290,7 @@ public class TypeDescriptor {
|
|||
}
|
||||
|
||||
// indexable type descriptor operations
|
||||
|
||||
|
||||
/**
|
||||
* Is this type a {@link Collection} type?
|
||||
*/
|
||||
|
|
@ -336,7 +338,7 @@ public class TypeDescriptor {
|
|||
}
|
||||
|
||||
// map type descriptor operations
|
||||
|
||||
|
||||
/**
|
||||
* Is this type a {@link Map} type?
|
||||
*/
|
||||
|
|
@ -406,7 +408,7 @@ public class TypeDescriptor {
|
|||
}
|
||||
|
||||
// extending Object
|
||||
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
|
|
@ -415,17 +417,17 @@ public class TypeDescriptor {
|
|||
return false;
|
||||
}
|
||||
TypeDescriptor other = (TypeDescriptor) obj;
|
||||
boolean annotatedTypeEquals = ObjectUtils.nullSafeEquals(getType(), other.getType()) && ObjectUtils.nullSafeEquals(getAnnotations(), other.getAnnotations());
|
||||
boolean annotatedTypeEquals = ObjectUtils.nullSafeEquals(getType(), other.getType())
|
||||
&& ObjectUtils.nullSafeEquals(getAnnotations(), other.getAnnotations());
|
||||
if (!annotatedTypeEquals) {
|
||||
return false;
|
||||
}
|
||||
if (isCollection() || isArray()) {
|
||||
return ObjectUtils.nullSafeEquals(getElementType(), other.getElementType());
|
||||
}
|
||||
else if (isMap()) {
|
||||
return ObjectUtils.nullSafeEquals(getMapKeyType(), other.getMapKeyType()) && ObjectUtils.nullSafeEquals(getMapValueType(), other.getMapValueType());
|
||||
}
|
||||
else {
|
||||
} else if (isMap()) {
|
||||
return ObjectUtils.nullSafeEquals(getMapKeyType(), other.getMapKeyType())
|
||||
&& ObjectUtils.nullSafeEquals(getMapValueType(), other.getMapValueType());
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -444,13 +446,171 @@ public class TypeDescriptor {
|
|||
if (isMap()) {
|
||||
builder.append("<").append(wildcard(getMapKeyType()));
|
||||
builder.append(", ").append(wildcard(getMapValueType())).append(">");
|
||||
}
|
||||
else if (isCollection()) {
|
||||
} else if (isCollection()) {
|
||||
builder.append("<").append(wildcard(getElementType())).append(">");
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
// helper public class
|
||||
|
||||
public static final class Property {
|
||||
|
||||
private final Class<?> objectType;
|
||||
|
||||
private final Method readMethod;
|
||||
|
||||
private final Method writeMethod;
|
||||
|
||||
private final String name;
|
||||
|
||||
private final MethodParameter methodParameter;
|
||||
|
||||
private final Annotation[] annotations;
|
||||
|
||||
public Property(Class<?> objectType, Method readMethod, Method writeMethod) {
|
||||
this.objectType = objectType;
|
||||
this.readMethod = readMethod;
|
||||
this.writeMethod = writeMethod;
|
||||
this.methodParameter = resolveMethodParameter();
|
||||
this.name = resolveName();
|
||||
this.annotations = resolveAnnotations();
|
||||
}
|
||||
|
||||
public Class<?> getObjectType() {
|
||||
return objectType;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Class<?> getType() {
|
||||
return methodParameter.getParameterType();
|
||||
}
|
||||
|
||||
public Method getReadMethod() {
|
||||
return readMethod;
|
||||
}
|
||||
|
||||
public Method getWriteMethod() {
|
||||
return writeMethod;
|
||||
}
|
||||
|
||||
MethodParameter getMethodParameter() {
|
||||
return methodParameter;
|
||||
}
|
||||
|
||||
Annotation[] getAnnotations() {
|
||||
return annotations;
|
||||
}
|
||||
|
||||
private String resolveName() {
|
||||
if (readMethod != null) {
|
||||
int index = readMethod.getName().indexOf("get");
|
||||
if (index != -1) {
|
||||
index += 3;
|
||||
} else {
|
||||
index = readMethod.getName().indexOf("is");
|
||||
if (index == -1) {
|
||||
throw new IllegalArgumentException("Not a getter method");
|
||||
}
|
||||
index += 2;
|
||||
}
|
||||
return StringUtils.uncapitalize(readMethod.getName().substring(index));
|
||||
} else {
|
||||
int index = writeMethod.getName().indexOf("set") + 3;
|
||||
if (index == -1) {
|
||||
throw new IllegalArgumentException("Not a setter method");
|
||||
}
|
||||
return StringUtils.uncapitalize(writeMethod.getName().substring(index));
|
||||
}
|
||||
}
|
||||
|
||||
private MethodParameter resolveMethodParameter() {
|
||||
MethodParameter read = resolveReadMethodParameter();
|
||||
MethodParameter write = resolveWriteMethodParameter();
|
||||
if (read == null && write == null) {
|
||||
throw new IllegalStateException("Property is neither readable or writeable");
|
||||
}
|
||||
if (read != null && write != null && !read.getParameterType().equals(write.getParameterType())) {
|
||||
throw new IllegalStateException("Read and write parameter types are not the same");
|
||||
}
|
||||
return read != null ? read : write;
|
||||
}
|
||||
|
||||
private MethodParameter resolveReadMethodParameter() {
|
||||
if (getReadMethod() == null) {
|
||||
return null;
|
||||
}
|
||||
return resolveParameterType(new MethodParameter(getReadMethod(), -1));
|
||||
}
|
||||
|
||||
private MethodParameter resolveWriteMethodParameter() {
|
||||
if (getWriteMethod() == null) {
|
||||
return null;
|
||||
}
|
||||
return resolveParameterType(new MethodParameter(getWriteMethod(), 0));
|
||||
}
|
||||
|
||||
private MethodParameter resolveParameterType(MethodParameter parameter) {
|
||||
// needed to resolve generic property types that parameterized by sub-classes e.g. T getFoo();
|
||||
GenericTypeResolver.resolveParameterType(parameter, getObjectType());
|
||||
return parameter;
|
||||
}
|
||||
|
||||
private Annotation[] resolveAnnotations() {
|
||||
Map<Class<?>, Annotation> annMap = new LinkedHashMap<Class<?>, Annotation>();
|
||||
Method readMethod = getReadMethod();
|
||||
if (readMethod != null) {
|
||||
for (Annotation ann : readMethod.getAnnotations()) {
|
||||
annMap.put(ann.annotationType(), ann);
|
||||
}
|
||||
}
|
||||
Method writeMethod = getWriteMethod();
|
||||
if (writeMethod != null) {
|
||||
for (Annotation ann : writeMethod.getAnnotations()) {
|
||||
annMap.put(ann.annotationType(), ann);
|
||||
}
|
||||
}
|
||||
Field field = getField();
|
||||
if (field != null) {
|
||||
for (Annotation ann : field.getAnnotations()) {
|
||||
annMap.put(ann.annotationType(), ann);
|
||||
}
|
||||
}
|
||||
return annMap.values().toArray(new Annotation[annMap.size()]);
|
||||
}
|
||||
|
||||
private Field getField() {
|
||||
String name = getName();
|
||||
if (!StringUtils.hasLength(name)) {
|
||||
return null;
|
||||
}
|
||||
Class<?> declaringClass = declaringClass();
|
||||
Field field = ReflectionUtils.findField(declaringClass, name);
|
||||
if (field == null) {
|
||||
// Same lenient fallback checking as in CachedIntrospectionResults...
|
||||
field = ReflectionUtils.findField(declaringClass,
|
||||
name.substring(0, 1).toLowerCase() + name.substring(1));
|
||||
if (field == null) {
|
||||
field = ReflectionUtils.findField(declaringClass,
|
||||
name.substring(0, 1).toUpperCase() + name.substring(1));
|
||||
}
|
||||
}
|
||||
return field;
|
||||
}
|
||||
|
||||
private Class<?> declaringClass() {
|
||||
if (getReadMethod() != null) {
|
||||
return getReadMethod().getDeclaringClass();
|
||||
} else {
|
||||
return getWriteMethod().getDeclaringClass();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// package private
|
||||
|
||||
TypeDescriptor(AbstractDescriptor descriptor) {
|
||||
|
|
@ -464,7 +624,7 @@ public class TypeDescriptor {
|
|||
static Annotation[] nullSafeAnnotations(Annotation[] annotations) {
|
||||
return annotations != null ? annotations : EMPTY_ANNOTATION_ARRAY;
|
||||
}
|
||||
|
||||
|
||||
// internal constructors
|
||||
|
||||
private TypeDescriptor(Class<?> type) {
|
||||
|
|
@ -479,7 +639,8 @@ public class TypeDescriptor {
|
|||
this(mapType, null, keyType, valueType, EMPTY_ANNOTATION_ARRAY);
|
||||
}
|
||||
|
||||
private TypeDescriptor(Class<?> type, TypeDescriptor elementType, TypeDescriptor mapKeyType, TypeDescriptor mapValueType, Annotation[] annotations) {
|
||||
private TypeDescriptor(Class<?> type, TypeDescriptor elementType, TypeDescriptor mapKeyType,
|
||||
TypeDescriptor mapValueType, Annotation[] annotations) {
|
||||
this.type = type;
|
||||
this.elementType = elementType;
|
||||
this.mapKeyType = mapKeyType;
|
||||
|
|
@ -494,7 +655,7 @@ public class TypeDescriptor {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
return new TypeDescriptor(descriptor);
|
||||
return new TypeDescriptor(descriptor);
|
||||
}
|
||||
|
||||
// internal helpers
|
||||
|
|
@ -507,7 +668,7 @@ public class TypeDescriptor {
|
|||
if (keyType == null) {
|
||||
return false;
|
||||
}
|
||||
return keyType.isAssignableTo(targetKeyType);
|
||||
return keyType.isAssignableTo(targetKeyType);
|
||||
}
|
||||
|
||||
private boolean collectionElementsAssignable(TypeDescriptor targetElementType) {
|
||||
|
|
@ -518,9 +679,9 @@ public class TypeDescriptor {
|
|||
if (elementType == null) {
|
||||
return false;
|
||||
}
|
||||
return elementType.isAssignableTo(targetElementType);
|
||||
return elementType.isAssignableTo(targetElementType);
|
||||
}
|
||||
|
||||
|
||||
private boolean mapValuesAssignable(TypeDescriptor targetValueType) {
|
||||
TypeDescriptor valueType = getMapValueType();
|
||||
if (targetValueType == null) {
|
||||
|
|
@ -529,21 +690,21 @@ public class TypeDescriptor {
|
|||
if (valueType == null) {
|
||||
return false;
|
||||
}
|
||||
return valueType.isAssignableTo(targetValueType);
|
||||
return valueType.isAssignableTo(targetValueType);
|
||||
}
|
||||
|
||||
private void assertCollectionOrArray() {
|
||||
if (!isCollection() && !isArray()) {
|
||||
throw new IllegalStateException("Not a java.util.Collection or Array");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void assertMap() {
|
||||
if (!isMap()) {
|
||||
throw new IllegalStateException("Not a java.util.Map");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private String wildcard(TypeDescriptor nestedType) {
|
||||
return nestedType != null ? nestedType.toString() : "?";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ import static org.junit.Assert.assertFalse;
|
|||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
|
@ -37,6 +36,7 @@ import java.util.Map;
|
|||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.convert.TypeDescriptor.Property;
|
||||
|
||||
/**
|
||||
* @author Keith Donald
|
||||
|
|
@ -205,8 +205,8 @@ public class TypeDescriptorTests {
|
|||
|
||||
@Test
|
||||
public void propertyComplex() throws Exception {
|
||||
PropertyDescriptor property = new PropertyDescriptor("complexProperty", getClass().getMethod("getComplexProperty", null), getClass().getMethod("setComplexProperty", Map.class));
|
||||
TypeDescriptor desc = new TypeDescriptor(getClass(), property);
|
||||
Property property = new Property(getClass(), getClass().getMethod("getComplexProperty", null), getClass().getMethod("setComplexProperty", Map.class));
|
||||
TypeDescriptor desc = new TypeDescriptor(property);
|
||||
assertEquals(String.class, desc.getMapKeyType().getType());
|
||||
assertEquals(Integer.class, desc.getMapValueType().getElementType().getElementType().getType());
|
||||
}
|
||||
|
|
@ -222,16 +222,16 @@ public class TypeDescriptorTests {
|
|||
@Test
|
||||
public void propertyGenericType() throws Exception {
|
||||
GenericType<Integer> genericBean = new IntegerType();
|
||||
PropertyDescriptor property = new PropertyDescriptor("property", genericBean.getClass().getMethod("getProperty", null), genericBean.getClass().getMethod("setProperty", Integer.class));
|
||||
TypeDescriptor desc = new TypeDescriptor(genericBean.getClass(), property);
|
||||
Property property = new Property(getClass(), genericBean.getClass().getMethod("getProperty", null), genericBean.getClass().getMethod("setProperty", Integer.class));
|
||||
TypeDescriptor desc = new TypeDescriptor(property);
|
||||
assertEquals(Integer.class, desc.getType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void propertyGenericTypeList() throws Exception {
|
||||
GenericType<Integer> genericBean = new IntegerType();
|
||||
PropertyDescriptor property = new PropertyDescriptor("listProperty", genericBean.getClass().getMethod("getListProperty", null), genericBean.getClass().getMethod("setListProperty", List.class));
|
||||
TypeDescriptor desc = new TypeDescriptor(genericBean.getClass(), property);
|
||||
Property property = new Property(getClass(), genericBean.getClass().getMethod("getListProperty", null), genericBean.getClass().getMethod("setListProperty", List.class));
|
||||
TypeDescriptor desc = new TypeDescriptor(property);
|
||||
assertEquals(List.class, desc.getType());
|
||||
assertEquals(Integer.class, desc.getElementType().getType());
|
||||
}
|
||||
|
|
@ -274,8 +274,8 @@ public class TypeDescriptorTests {
|
|||
@Test
|
||||
public void propertyGenericClassList() throws Exception {
|
||||
IntegerClass genericBean = new IntegerClass();
|
||||
PropertyDescriptor property = new PropertyDescriptor("listProperty", genericBean.getClass().getMethod("getListProperty", null), genericBean.getClass().getMethod("setListProperty", List.class));
|
||||
TypeDescriptor desc = new TypeDescriptor(genericBean.getClass(), property);
|
||||
Property property = new Property(genericBean.getClass(), genericBean.getClass().getMethod("getListProperty", null), genericBean.getClass().getMethod("setListProperty", List.class));
|
||||
TypeDescriptor desc = new TypeDescriptor(property);
|
||||
assertEquals(List.class, desc.getType());
|
||||
assertEquals(Integer.class, desc.getElementType().getType());
|
||||
assertNotNull(desc.getAnnotation(MethodAnnotation1.class));
|
||||
|
|
@ -306,8 +306,9 @@ public class TypeDescriptorTests {
|
|||
|
||||
@Test
|
||||
public void property() throws Exception {
|
||||
PropertyDescriptor property = new PropertyDescriptor("property", getClass().getMethod("getProperty", null), getClass().getMethod("setProperty", Map.class));
|
||||
TypeDescriptor desc = new TypeDescriptor(getClass(), property);
|
||||
Property property = new Property(getClass(), getClass().getMethod("getProperty", null), getClass().getMethod("setProperty", Map.class));
|
||||
TypeDescriptor desc = new TypeDescriptor(property);
|
||||
assertEquals(Map.class, desc.getType());
|
||||
assertEquals(Integer.class, desc.getMapKeyType().getElementType().getType());
|
||||
assertEquals(Long.class, desc.getMapValueType().getElementType().getType());
|
||||
assertNotNull(desc.getAnnotation(MethodAnnotation1.class));
|
||||
|
|
@ -573,8 +574,8 @@ public class TypeDescriptorTests {
|
|||
|
||||
@Test
|
||||
public void nestedPropertyTypeMapTwoLevels() throws Exception {
|
||||
PropertyDescriptor property = new PropertyDescriptor("test4", getClass().getMethod("getTest4", null), getClass().getMethod("setTest4", List.class));
|
||||
TypeDescriptor t1 = TypeDescriptor.nested(getClass(), property, 2);
|
||||
Property property = new Property(getClass(), getClass().getMethod("getTest4", null), getClass().getMethod("setTest4", List.class));
|
||||
TypeDescriptor t1 = TypeDescriptor.nested(property, 2);
|
||||
assertEquals(String.class, t1.getType());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,8 +16,6 @@
|
|||
|
||||
package org.springframework.expression.spel.support;
|
||||
|
||||
import java.beans.IntrospectionException;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Member;
|
||||
|
|
@ -28,6 +26,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.TypeDescriptor.Property;
|
||||
import org.springframework.expression.AccessException;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
|
|
@ -75,17 +74,12 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
|
|||
Method method = findGetterForProperty(name, type, target instanceof Class);
|
||||
if (method != null) {
|
||||
// Treat it like a property
|
||||
try {
|
||||
// The readerCache will only contain gettable properties (let's not worry about setters for now)
|
||||
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(name, method, null);
|
||||
TypeDescriptor typeDescriptor = new TypeDescriptor(type, propertyDescriptor);
|
||||
this.readerCache.put(cacheKey, new InvokerPair(method, typeDescriptor));
|
||||
this.typeDescriptorCache.put(cacheKey, typeDescriptor);
|
||||
return true;
|
||||
}
|
||||
catch (IntrospectionException ex) {
|
||||
throw new AccessException("Unable to access property '" + name + "' through getter " + method, ex);
|
||||
}
|
||||
// The readerCache will only contain gettable properties (let's not worry about setters for now)
|
||||
Property property = new Property(type, method, null);
|
||||
TypeDescriptor typeDescriptor = new TypeDescriptor(property);
|
||||
this.readerCache.put(cacheKey, new InvokerPair(method, typeDescriptor));
|
||||
this.typeDescriptorCache.put(cacheKey, typeDescriptor);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
Field field = findField(name, type, target instanceof Class);
|
||||
|
|
@ -122,17 +116,11 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
|
|||
if (method != null) {
|
||||
// TODO remove the duplication here between canRead and read
|
||||
// Treat it like a property
|
||||
try {
|
||||
// The readerCache will only contain gettable properties (let's not worry about setters for now)
|
||||
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(name, method, null);
|
||||
TypeDescriptor typeDescriptor = new TypeDescriptor(type, propertyDescriptor);
|
||||
invoker = new InvokerPair(method, typeDescriptor);
|
||||
this.readerCache.put(cacheKey, invoker);
|
||||
}
|
||||
catch (IntrospectionException ex) {
|
||||
throw new AccessException(
|
||||
"Unable to access property '" + name + "' through getter " + method, ex);
|
||||
}
|
||||
// The readerCache will only contain gettable properties (let's not worry about setters for now)
|
||||
Property property = new Property(type, method, null);
|
||||
TypeDescriptor typeDescriptor = new TypeDescriptor(property);
|
||||
invoker = new InvokerPair(method, typeDescriptor);
|
||||
this.readerCache.put(cacheKey, invoker);
|
||||
}
|
||||
}
|
||||
if (method != null) {
|
||||
|
|
@ -183,14 +171,8 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
|
|||
Method method = findSetterForProperty(name, type, target instanceof Class);
|
||||
if (method != null) {
|
||||
// Treat it like a property
|
||||
PropertyDescriptor propertyDescriptor = null;
|
||||
try {
|
||||
propertyDescriptor = new PropertyDescriptor(name, null, method);
|
||||
}
|
||||
catch (IntrospectionException ex) {
|
||||
throw new AccessException("Unable to access property '" + name + "' through setter "+method, ex);
|
||||
}
|
||||
TypeDescriptor typeDescriptor = new TypeDescriptor(type, propertyDescriptor);
|
||||
Property property = new Property(type, null, method);
|
||||
TypeDescriptor typeDescriptor = new TypeDescriptor(property);
|
||||
this.writerCache.put(cacheKey, method);
|
||||
this.typeDescriptorCache.put(cacheKey, typeDescriptor);
|
||||
return true;
|
||||
|
|
|
|||
Loading…
Reference in New Issue