TypeDescriptor cleanup and general polishing; fixed a number of bugs related to TypeDescriptor usage in client code across beans and spel packages

This commit is contained in:
Keith Donald
2011-01-05 05:49:33 +00:00
parent 74b5b7b56a
commit 39e0c29d19
33 changed files with 449 additions and 539 deletions

View File

@@ -29,7 +29,7 @@ import org.springframework.core.convert.TypeDescriptor;
*/
public class TypedValue {
public static final TypedValue NULL = new TypedValue(null, TypeDescriptor.NULL);
public static final TypedValue NULL = new TypedValue(null);
private final Object value;

View File

@@ -44,7 +44,7 @@ public abstract class ExpressionUtils {
*/
public static <T> T convert(EvaluationContext context, Object value, Class<T> targetType) throws EvaluationException {
// TODO remove this function over time and use the one it delegates to
return convertTypedValue(context,new TypedValue(value,TypeDescriptor.forObject(value)),targetType);
return convertTypedValue(context,new TypedValue(value),targetType);
}
/**

View File

@@ -124,7 +124,7 @@ public class ExpressionState {
return TypedValue.NULL;
}
else {
return new TypedValue(value, TypeDescriptor.forObject(value));
return new TypedValue(value);
}
}
@@ -183,7 +183,7 @@ public class ExpressionState {
OperatorOverloader overloader = this.relatedContext.getOperatorOverloader();
if (overloader.overridesOperation(op, left, right)) {
Object returnValue = overloader.operate(op, left, right);
return new TypedValue(returnValue,TypeDescriptor.forObject(returnValue));
return new TypedValue(returnValue);
}
else {
String leftType = (left==null?"null":left.getClass().getName());

View File

@@ -17,8 +17,8 @@
package org.springframework.expression.spel.ast;
import java.lang.reflect.Array;
import java.util.List;
import java.util.ArrayList;
import java.util.List;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.expression.AccessException;
@@ -234,7 +234,6 @@ public class ConstructorReference extends SpelNodeImpl {
else {
componentType = arrayTypeCode.getType();
}
TypeDescriptor td = TypeDescriptor.valueOf(componentType);
Object newArray;
if (!hasInitializer()) {
// Confirm all dimensions were specified (for example [3][][5] is missing the 2nd dimension)
@@ -313,7 +312,7 @@ public class ConstructorReference extends SpelNodeImpl {
throw new IllegalStateException(arrayTypeCode.name());
}
}
return new TypedValue(newArray, td);
return new TypedValue(newArray);
}
private void populateReferenceTypeArray(ExpressionState state, Object newArray, TypeConverter typeConverter,

View File

@@ -90,20 +90,10 @@ public class Indexer extends SpelNodeImpl {
// Indexing into a Map
if (targetObject instanceof Map) {
if (targetObject == null) {
// Current decision: attempt to index into null map == exception and does not just return null
throw new SpelEvaluationException(getStartPosition(),SpelMessage.CANNOT_INDEX_INTO_NULL_VALUE);
}
Object possiblyConvertedKey = index;
if (targetObjectTypeDescriptor.isMapEntryTypeKnown()) {
possiblyConvertedKey = state.convertValue(index,TypeDescriptor.valueOf(targetObjectTypeDescriptor.getMapKeyType()));
}
possiblyConvertedKey = state.convertValue(index, targetObjectTypeDescriptor.getMapKeyTypeDescriptor());
Object o = ((Map<?, ?>) targetObject).get(possiblyConvertedKey);
if (targetObjectTypeDescriptor.isMapEntryTypeKnown()) {
return new TypedValue(o, targetObjectTypeDescriptor.getMapValueTypeDescriptor());
} else {
return new TypedValue(o);
}
return new TypedValue(o, targetObjectTypeDescriptor.getMapValueTypeDescriptor().applyType(o));
}
if (targetObject == null) {
@@ -125,7 +115,7 @@ public class Indexer extends SpelNodeImpl {
int pos = 0;
for (Object o : c) {
if (pos == idx) {
return new TypedValue(o, targetObjectTypeDescriptor.getElementTypeDescriptor());
return new TypedValue(o, targetObjectTypeDescriptor.getElementTypeDescriptor().applyType(o));
}
pos++;
}
@@ -195,10 +185,8 @@ public class Indexer extends SpelNodeImpl {
Map map = (Map)targetObject;
Object possiblyConvertedKey = index;
Object possiblyConvertedValue = newValue;
if (targetObjectTypeDescriptor.isMapEntryTypeKnown()) {
possiblyConvertedKey = state.convertValue(index.getValue(),TypeDescriptor.valueOf(targetObjectTypeDescriptor.getMapKeyType()));
possiblyConvertedValue = state.convertValue(newValue,TypeDescriptor.valueOf(targetObjectTypeDescriptor.getMapValueType()));
}
possiblyConvertedKey = state.convertValue(index.getValue(), targetObjectTypeDescriptor.getMapKeyTypeDescriptor());
possiblyConvertedValue = state.convertValue(newValue, targetObjectTypeDescriptor.getMapValueTypeDescriptor());
map.put(possiblyConvertedKey,possiblyConvertedValue);
return;
}

View File

@@ -19,7 +19,6 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.expression.EvaluationException;
import org.springframework.expression.TypedValue;
import org.springframework.expression.spel.ExpressionState;
@@ -72,8 +71,7 @@ public class InlineList extends SpelNodeImpl {
constantList.add(((InlineList) child).getConstantValue());
}
}
this.constant = new TypedValue(Collections.unmodifiableList(constantList), TypeDescriptor
.valueOf(List.class));
this.constant = new TypedValue(Collections.unmodifiableList(constantList));
}
}
@@ -87,7 +85,7 @@ public class InlineList extends SpelNodeImpl {
for (int c = 0; c < childcount; c++) {
returnValue.add(getChild(c).getValue(expressionState));
}
return new TypedValue(returnValue, TypeDescriptor.valueOf(List.class));
return new TypedValue(returnValue);
}
}

View File

@@ -16,7 +16,6 @@
package org.springframework.expression.spel.ast;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.expression.EvaluationException;
import org.springframework.expression.Operation;
import org.springframework.expression.TypedValue;
@@ -50,7 +49,7 @@ public class OpDivide extends Operator {
}
}
Object result = state.operate(Operation.DIVIDE, operandOne, operandTwo);
return new TypedValue(result,TypeDescriptor.forObject(result));
return new TypedValue(result);
}
}

View File

@@ -68,14 +68,14 @@ public class Projection extends SpelNodeImpl {
List<Object> result = new ArrayList<Object>();
for (Map.Entry entry : mapData.entrySet()) {
try {
state.pushActiveContextObject(new TypedValue(entry, TypeDescriptor.valueOf(Map.Entry.class)));
state.pushActiveContextObject(new TypedValue(entry));
result.add(this.children[0].getValueInternal(state).getValue());
}
finally {
state.popActiveContextObject();
}
}
return new TypedValue(result,TypeDescriptor.valueOf(List.class)); // TODO unable to build correct type descriptor
return new TypedValue(result); // TODO unable to build correct type descriptor
}
else if (operand instanceof Collection || operandIsArray) {
Collection<?> data = (operand instanceof Collection ? (Collection<?>) operand :

View File

@@ -74,7 +74,7 @@ public class Selection extends SpelNodeImpl {
Object lastKey = null;
for (Map.Entry entry : mapdata.entrySet()) {
try {
TypedValue kvpair = new TypedValue(entry,TypeDescriptor.valueOf(Map.Entry.class));
TypedValue kvpair = new TypedValue(entry);
state.pushActiveContextObject(kvpair);
Object o = selectionCriteria.getValueInternal(state).getValue();
if (o instanceof Boolean) {
@@ -95,7 +95,7 @@ public class Selection extends SpelNodeImpl {
}
}
if ((variant == FIRST || variant == LAST) && result.size() == 0) {
return new TypedValue(null,TypeDescriptor.NULL);
return new TypedValue(null);
}
if (variant == LAST) {
Map resultMap = new HashMap();

View File

@@ -16,7 +16,6 @@
package org.springframework.expression.spel.support;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.expression.TypedValue;
/**
@@ -31,7 +30,7 @@ public class BooleanTypedValue extends TypedValue {
private BooleanTypedValue(boolean b) {
super(b, TypeDescriptor.valueOf(Boolean.class));
super(b);
}

View File

@@ -236,7 +236,7 @@ public class ReflectionHelper {
TypeDescriptor targetType;
if (varargsPosition != null && argPosition >= varargsPosition) {
MethodParameter methodParam = MethodParameter.forMethodOrConstructor(methodOrCtor, varargsPosition);
targetType = new TypeDescriptor(methodParam, methodParam.getParameterType().getComponentType());
targetType = new TypeDescriptor(methodParam.getParameterType().getComponentType(), methodParam);
}
else {
targetType = new TypeDescriptor(MethodParameter.forMethodOrConstructor(methodOrCtor, argPosition));
@@ -268,7 +268,7 @@ public class ReflectionHelper {
TypeDescriptor targetType;
if (varargsPosition != null && argPosition >= varargsPosition) {
MethodParameter methodParam = new MethodParameter(method, varargsPosition);
targetType = new TypeDescriptor(methodParam, methodParam.getParameterType().getComponentType());
targetType = new TypeDescriptor(methodParam.getParameterType().getComponentType(), methodParam);
}
else {
targetType = new TypeDescriptor(new MethodParameter(method, argPosition));

View File

@@ -18,7 +18,6 @@ package org.springframework.expression.spel.support;
import java.lang.reflect.Constructor;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.expression.AccessException;
import org.springframework.expression.ConstructorExecutor;
import org.springframework.expression.EvaluationContext;
@@ -65,7 +64,7 @@ class ReflectiveConstructorExecutor implements ConstructorExecutor {
arguments = ReflectionHelper.setupArgumentsForVarargsInvocation(this.ctor.getParameterTypes(), arguments);
}
ReflectionUtils.makeAccessible(this.ctor);
return new TypedValue(this.ctor.newInstance(arguments), TypeDescriptor.valueOf(this.ctor.getDeclaringClass()));
return new TypedValue(this.ctor.newInstance(arguments));
}
catch (Exception ex) {
throw new AccessException("Problem invoking constructor: " + this.ctor, ex);

View File

@@ -80,7 +80,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
// 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 PropertyTypeDescriptor(propertyDescriptor, new MethodParameter(method, -1));
new PropertyTypeDescriptor(new MethodParameter(method, -1), propertyDescriptor);
this.readerCache.put(cacheKey, new InvokerPair(method, typeDescriptor));
this.typeDescriptorCache.put(cacheKey, typeDescriptor);
return true;
@@ -128,7 +128,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
// 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 PropertyTypeDescriptor(propertyDescriptor, new MethodParameter(method, -1));
new PropertyTypeDescriptor(new MethodParameter(method, -1), propertyDescriptor);
invoker = new InvokerPair(method, typeDescriptor);
this.readerCache.put(cacheKey, invoker);
}
@@ -192,7 +192,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
throw new AccessException("Unable to access property '" + name + "' through setter "+method, ex);
}
MethodParameter mp = new MethodParameter(method,0);
TypeDescriptor typeDescriptor = new PropertyTypeDescriptor(propertyDescriptor, mp);
TypeDescriptor typeDescriptor = new PropertyTypeDescriptor(mp, propertyDescriptor);
this.writerCache.put(cacheKey, method);
this.typeDescriptorCache.put(cacheKey, typeDescriptor);
return true;

View File

@@ -26,7 +26,6 @@ import java.util.Map;
import junit.framework.Assert;
import org.junit.Test;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.expression.AccessException;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.EvaluationException;
@@ -247,7 +246,6 @@ public class ExpressionLanguageScenarioTests extends ExpressionTestCase {
private static class FruitColourAccessor implements PropertyAccessor {
private static Map<String,Color> propertyMap = new HashMap<String,Color>();
private static TypeDescriptor mapElementTypeDescriptor = TypeDescriptor.valueOf(Color.class);
static {
propertyMap.put("banana",Color.yellow);
@@ -267,7 +265,7 @@ public class ExpressionLanguageScenarioTests extends ExpressionTestCase {
}
public TypedValue read(EvaluationContext context, Object target, String name) throws AccessException {
return new TypedValue(propertyMap.get(name),mapElementTypeDescriptor);
return new TypedValue(propertyMap.get(name));
}
public boolean canWrite(EvaluationContext context, Object target, String name) throws AccessException {
@@ -306,7 +304,7 @@ public class ExpressionLanguageScenarioTests extends ExpressionTestCase {
}
public TypedValue read(EvaluationContext context, Object target, String name) throws AccessException {
return new TypedValue(propertyMap.get(name),TypeDescriptor.valueOf(Color.class));
return new TypedValue(propertyMap.get(name));
}
public boolean canWrite(EvaluationContext context, Object target, String name) throws AccessException {

View File

@@ -127,7 +127,7 @@ public class ExpressionStateTests extends ExpressionTestCase {
Assert.assertEquals(TypedValue.NULL,state.getRootContextObject());
((StandardEvaluationContext)state.getEvaluationContext()).setRootObject(null,TypeDescriptor.NULL);
((StandardEvaluationContext)state.getEvaluationContext()).setRootObject(null);
Assert.assertEquals(null,state.getRootContextObject().getValue());
}

View File

@@ -180,7 +180,7 @@ public class PropertyAccessTests extends ExpressionTestCase {
public TypedValue read(EvaluationContext context, Object target, String name) throws AccessException {
if (!name.equals("flibbles"))
throw new RuntimeException("Assertion Failed! name should be flibbles");
return new TypedValue(flibbles, TypeDescriptor.valueOf(String.class));
return new TypedValue(flibbles);
}
public void write(EvaluationContext context, Object target, String name, Object newValue)

View File

@@ -20,8 +20,8 @@ import java.lang.reflect.Method;
import java.util.List;
import junit.framework.Assert;
import org.junit.Test;
import org.junit.Test;
import org.springframework.core.MethodParameter;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.expression.AccessException;
@@ -222,7 +222,7 @@ public class ScenariosForSpringSecurity extends ExpressionTestCase {
}
public TypedValue read(EvaluationContext context, Object target, String name) throws AccessException {
return new TypedValue(new Principal(),TypeDescriptor.valueOf(Principal.class));
return new TypedValue(new Principal());
}
public boolean canWrite(EvaluationContext context, Object target, String name) throws AccessException {
@@ -252,7 +252,7 @@ public class ScenariosForSpringSecurity extends ExpressionTestCase {
}
public TypedValue read(EvaluationContext context, Object target, String name) throws AccessException {
return new TypedValue(activePerson,TypeDescriptor.valueOf(Person.class));
return new TypedValue(activePerson);
}
public boolean canWrite(EvaluationContext context, Object target, String name) throws AccessException {

View File

@@ -69,6 +69,9 @@ public class SpelDocumentationTests extends ExpressionTestCase {
public Inventor[] Members = new Inventor[1];
public List Members2 = new ArrayList();
public Map<String,Object> officers = new HashMap<String,Object>();
public List reverse = new ArrayList<Map<String, Object>>();
@SuppressWarnings("unchecked")
IEEE() {
officers.put("president",pupin);
@@ -77,6 +80,8 @@ public class SpelDocumentationTests extends ExpressionTestCase {
officers.put("advisors",linv);
Members2.add(tesla);
Members2.add(pupin);
reverse.add(officers);
}
public boolean isMember(String name) {
@@ -215,6 +220,9 @@ public class SpelDocumentationTests extends ExpressionTestCase {
parser.parseExpression("officers['advisors'][0].PlaceOfBirth.Country").setValue(societyContext, "Croatia");
Inventor i2 = parser.parseExpression("reverse[0]['advisors'][0]").getValue(societyContext,Inventor.class);
Assert.assertEquals("Nikola Tesla",i2.getName());
}
// 7.5.3