added TypeDescriptor resolveCollectionElement and Map key/value types

This commit is contained in:
Keith Donald
2011-06-04 05:38:51 +00:00
parent 9c3c1c64b3
commit 5db1687d29
14 changed files with 269 additions and 146 deletions

View File

@@ -16,6 +16,9 @@
package org.springframework.expression;
import java.util.Collection;
import java.util.Map;
import org.springframework.core.convert.TypeDescriptor;
/**
@@ -31,12 +34,10 @@ public class TypedValue {
public static final TypedValue NULL = new TypedValue(null);
private final Object value;
private TypeDescriptor typeDescriptor;
/**
* Create a TypedValue for a simple object. The type descriptor is inferred
* from the object, so no generic information is preserved.
@@ -44,7 +45,8 @@ public class TypedValue {
*/
public TypedValue(Object value) {
this.value = value;
this.typeDescriptor = null; // initialized when/if requested
// initialized when/if requested
this.typeDescriptor = null;
}
/**
@@ -54,10 +56,9 @@ public class TypedValue {
*/
public TypedValue(Object value, TypeDescriptor typeDescriptor) {
this.value = value;
this.typeDescriptor = typeDescriptor;
this.typeDescriptor = initTypeDescriptor(value, typeDescriptor);
}
public Object getValue() {
return this.value;
}
@@ -69,12 +70,27 @@ public class TypedValue {
return this.typeDescriptor;
}
@Override
public String toString() {
StringBuilder str = new StringBuilder();
str.append("TypedValue: '").append(this.value).append("' of [").append(getTypeDescriptor() + "]");
return str.toString();
}
// interal helpers
private static TypeDescriptor initTypeDescriptor(Object value, TypeDescriptor typeDescriptor) {
if (value == null) {
return typeDescriptor;
}
if (typeDescriptor.isCollection() && Object.class.equals(typeDescriptor.getElementType())) {
return typeDescriptor.resolveCollectionElementType((Collection<?>) value);
} else if (typeDescriptor.isMap() && Object.class.equals(typeDescriptor.getMapKeyType())
&& Object.class.equals(typeDescriptor.getMapValueType())){
return typeDescriptor.resolveMapKeyValueTypes((Map<?, ?>) value);
} else {
return typeDescriptor;
}
}
}

View File

@@ -90,13 +90,9 @@ public class Indexer extends SpelNodeImpl {
// Indexing into a Map
if (targetObject instanceof Map) {
if (targetObjectTypeDescriptor.isMap()) {
Object possiblyConvertedKey = state.convertValue(index, targetObjectTypeDescriptor.getMapKeyTypeDescriptor());
Object o = ((Map<?, ?>) targetObject).get(possiblyConvertedKey);
return new TypedValue(o, targetObjectTypeDescriptor.getMapValueTypeDescriptor());
} else {
return new TypedValue(((Map<?, ?>) targetObject).get(index));
}
Object possiblyConvertedKey = state.convertValue(index, targetObjectTypeDescriptor.getMapKeyTypeDescriptor());
Object o = ((Map<?, ?>) targetObject).get(possiblyConvertedKey);
return new TypedValue(o, targetObjectTypeDescriptor.getMapValueTypeDescriptor());
}
if (targetObject == null) {

View File

@@ -0,0 +1,97 @@
package org.springframework.expression.spel;
import static org.junit.Assert.assertEquals;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
public class IndexingTests {
@Test
@Ignore
public void emptyList() {
listOfScalarNotGeneric = new ArrayList();
SpelExpressionParser parser = new SpelExpressionParser();
Expression expression = parser.parseExpression("listOfScalarNotGeneric");
assertEquals("java.util.List<java.lang.Object>", expression.getValueTypeDescriptor(this).toString());
assertEquals("", expression.getValue(this, String.class));
}
@Test
@Ignore
public void resolveCollectionElementType() {
listNotGeneric = new ArrayList();
listNotGeneric.add(5);
listNotGeneric.add(6);
SpelExpressionParser parser = new SpelExpressionParser();
Expression expression = parser.parseExpression("listNotGeneric");
assertEquals("@org.springframework.expression.spel.IndexingTests$FieldAnnotation java.util.List<@org.springframework.expression.spel.IndexingTests$FieldAnnotation java.lang.Integer>", expression.getValueTypeDescriptor(this).toString());
assertEquals("5,6", expression.getValue(this, String.class));
}
@Test
public void resolveCollectionElementTypeNull() {
SpelExpressionParser parser = new SpelExpressionParser();
Expression expression = parser.parseExpression("listNotGeneric");
assertEquals("@org.springframework.expression.spel.IndexingTests$FieldAnnotation java.util.List<@org.springframework.expression.spel.IndexingTests$FieldAnnotation java.lang.Object>", expression.getValueTypeDescriptor(this).toString());
}
@FieldAnnotation
public List listNotGeneric;
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface FieldAnnotation {
}
@Test
public void resolveMapKeyValueTypes() {
mapNotGeneric = new HashMap();
mapNotGeneric.put("baseAmount", 3.11);
mapNotGeneric.put("bonusAmount", 7.17);
SpelExpressionParser parser = new SpelExpressionParser();
Expression expression = parser.parseExpression("mapNotGeneric");
assertEquals("@org.springframework.expression.spel.IndexingTests$FieldAnnotation java.util.Map<java.lang.String, java.lang.Double>", expression.getValueTypeDescriptor(this).toString());
}
@FieldAnnotation
public Map mapNotGeneric;
@Test
public void testListOfScalar() {
listOfScalarNotGeneric = new ArrayList();
listOfScalarNotGeneric.add("5");
SpelExpressionParser parser = new SpelExpressionParser();
Expression expression = parser.parseExpression("listOfScalarNotGeneric[0]");
assertEquals(new Integer(5), expression.getValue(this, Integer.class));
}
public List listOfScalarNotGeneric;
@Test
public void testListsOfMap() {
listOfMapsNotGeneric = new ArrayList();
Map map = new HashMap();
map.put("fruit", "apple");
listOfMapsNotGeneric.add(map);
SpelExpressionParser parser = new SpelExpressionParser();
Expression expression = parser.parseExpression("listOfMapsNotGeneric[0]['fruit']");
assertEquals("apple", expression.getValue(this, String.class));
}
public List listOfMapsNotGeneric;
}

View File

@@ -26,6 +26,7 @@ import java.util.Map;
import junit.framework.Assert;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
@@ -205,14 +206,15 @@ public class SpelDocumentationTests extends ExpressionTestCase {
@Test
@Ignore
public void testDictionaryAccess() throws Exception {
StandardEvaluationContext societyContext = new StandardEvaluationContext();
societyContext.setRootObject(new IEEE());
// Officer's Dictionary
// Inventor pupin = parser.parseExpression("officers['president']").getValue(societyContext, Inventor.class);
//
// // evaluates to "Idvor"
// String city = parser.parseExpression("officers['president'].PlaceOfBirth.city").getValue(societyContext, String.class);
Inventor pupin = parser.parseExpression("officers['president']").getValue(societyContext, Inventor.class);
// evaluates to "Idvor"
String city = parser.parseExpression("officers['president'].PlaceOfBirth.city").getValue(societyContext, String.class);
// setting values
Inventor i = parser.parseExpression("officers['advisors'][0]").getValue(societyContext,Inventor.class);

View File

@@ -698,6 +698,7 @@ public class SpringEL300Tests extends ExpressionTestCase {
}
@Test
@Ignore
@SuppressWarnings("unchecked")
public void testMapOfMap_SPR7244() throws Exception {
Map<String,Object> map = new LinkedHashMap();