SPR-5804: problems with map access if it is the root object; SPR-5847: alternative map referencing strategies: a.b == a[b] == a['b']

This commit is contained in:
Andy Clement
2009-07-07 16:08:10 +00:00
parent 2b869d57f2
commit a4b7ce168c
4 changed files with 113 additions and 76 deletions

View File

@@ -48,14 +48,29 @@ public class Indexer extends SpelNodeImpl {
TypedValue context = state.getActiveContextObject();
Object targetObject = context.getValue();
TypeDescriptor targetObjectTypeDescriptor = context.getTypeDescriptor();
TypedValue indexValue = children[0].getValueInternal(state);
Object index = indexValue.getValue();
TypedValue indexValue = null;
Object index = null;
// This first part of the if clause prevents a 'double dereference' of the property (SPR-5847)
if (targetObject instanceof Map && (children[0] instanceof PropertyOrFieldReference)) {
PropertyOrFieldReference reference = (PropertyOrFieldReference)children[0];
index = reference.getName();
indexValue = new TypedValue(index,CommonTypeDescriptors.STRING_TYPE_DESCRIPTOR);
} else {
indexValue = children[0].getValueInternal(state);
index = indexValue.getValue();
}
// Indexing into a Map
if (targetObject instanceof Map) {
Object possiblyConvertedKey = state.convertValue(indexValue,TypeDescriptor.valueOf(targetObjectTypeDescriptor.getMapKeyType()));
Object possiblyConvertedKey = index;
if (targetObjectTypeDescriptor.isMapEntryTypeKnown()) {
possiblyConvertedKey = state.convertValue(index,TypeDescriptor.valueOf(targetObjectTypeDescriptor.getMapKeyType()));
}
Object o = ((Map<?, ?>) targetObject).get(possiblyConvertedKey);
return new TypedValue(o,TypeDescriptor.valueOf(targetObjectTypeDescriptor.getMapValueType()));
TypeDescriptor resultDescriptor = targetObjectTypeDescriptor.isMapEntryTypeKnown()?
TypeDescriptor.valueOf(targetObjectTypeDescriptor.getMapValueType()):CommonTypeDescriptors.OBJECT_TYPE_DESCRIPTOR;
return new TypedValue(o,resultDescriptor);
}
int idx = (Integer)state.convertValue(index, INTEGER_TYPE_DESCRIPTOR);
@@ -131,8 +146,12 @@ public class Indexer extends SpelNodeImpl {
// Indexing into a Map
if (targetObjectTypeDescriptor.isMap()) {
Map map = (Map)targetObject;
Object possiblyConvertedKey = state.convertValue(index.getValue(),TypeDescriptor.valueOf(targetObjectTypeDescriptor.getMapKeyType()));
Object possiblyConvertedValue = state.convertValue(newValue,TypeDescriptor.valueOf(targetObjectTypeDescriptor.getMapValueType()));
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()));
}
map.put(possiblyConvertedKey,possiblyConvertedValue);
return;
}

View File

@@ -18,10 +18,12 @@ package org.springframework.expression.spel.ast;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.expression.AccessException;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.EvaluationException;
import org.springframework.expression.PropertyAccessor;
import org.springframework.expression.TypedValue;
import org.springframework.expression.spel.ExpressionState;
@@ -52,7 +54,7 @@ public class PropertyOrFieldReference extends SpelNodeImpl {
}
@Override
public TypedValue getValueInternal(ExpressionState state) throws SpelEvaluationException {
public TypedValue getValueInternal(ExpressionState state) throws EvaluationException {
TypedValue result = readProperty(state, this.name);
if (result.getValue()==null && state.configuredToCreateCollection() && result.getTypeDescriptor().getType().equals(List.class) && nextChildIs(Indexer.class)) {
// Create a new list ready for the indexer
@@ -93,11 +95,12 @@ public class PropertyOrFieldReference extends SpelNodeImpl {
* @return the value of the property
* @throws SpelEvaluationException if any problem accessing the property or it cannot be found
*/
private TypedValue readProperty(ExpressionState state, String name) throws SpelEvaluationException {
private TypedValue readProperty(ExpressionState state, String name) throws EvaluationException {
TypedValue contextObject = state.getActiveContextObject();
EvaluationContext eContext = state.getEvaluationContext();
Object targetObject = contextObject.getValue();
if (contextObject.getValue() == null && nullSafe) {
if (targetObject == null && nullSafe) {
return TypedValue.NULL_TYPED_VALUE;
}
@@ -245,5 +248,9 @@ public class PropertyOrFieldReference extends SpelNodeImpl {
resolvers.addAll(generalAccessors);
return resolvers;
}
String getName() {
return name;
}
}