提交 470e0861 编写于 作者: A Andy Clement

map access tests added

上级 769e706b
......@@ -25,9 +25,9 @@ import org.springframework.expression.EvaluationContext;
import org.springframework.expression.PropertyAccessor;
import org.springframework.expression.PropertyReaderExecutor;
import org.springframework.expression.PropertyWriterExecutor;
import org.springframework.expression.spel.ExpressionState;
import org.springframework.expression.spel.SpelException;
import org.springframework.expression.spel.SpelMessages;
import org.springframework.expression.spel.ExpressionState;
import org.springframework.expression.spel.internal.Utils;
/**
......@@ -68,9 +68,9 @@ public class PropertyOrFieldReference extends SpelNode {
return name.toString();
}
/**
/**
* Attempt to read the named property from the current context object.
*
*
* @param state the evaluation state
* @param name the name of the property
* @return the value of the property
......@@ -88,19 +88,20 @@ public class PropertyOrFieldReference extends SpelNode {
// let's try to get a new one and call it before giving up
}
}
Class<?> contextObjectClass = getObjectClass(contextObject);
List<PropertyAccessor> accessorsToTry = getPropertyAccessorsToTry(contextObjectClass, state);
// Go through the accessors that may be able to resolve it. If they are a cacheable accessor then
// get the accessor and use it. If they are not cacheable but report they can read the property
// Go through the accessors that may be able to resolve it. If they are a cacheable accessor then
// get the accessor and use it. If they are not cacheable but report they can read the property
// then ask them to read it
if (accessorsToTry != null) {
try {
for (PropertyAccessor accessor : accessorsToTry) {
if (accessor instanceof CacheablePropertyAccessor) {
cachedReaderExecutor = ((CacheablePropertyAccessor)accessor).getReaderAccessor(eContext, contextObject, name);
cachedReaderExecutor = ((CacheablePropertyAccessor) accessor).getReaderAccessor(eContext,
contextObject, name);
if (cachedReaderExecutor != null) {
try {
return cachedReaderExecutor.execute(state.getEvaluationContext(), contextObject);
......@@ -124,14 +125,14 @@ public class PropertyOrFieldReference extends SpelNode {
throw new SpelException(ae, SpelMessages.EXCEPTION_DURING_PROPERTY_READ, name, ae.getMessage());
}
}
throw new SpelException(SpelMessages.PROPERTY_OR_FIELD_NOT_FOUND, name, Utils.formatClassnameForMessage(contextObjectClass));
throw new SpelException(SpelMessages.PROPERTY_OR_FIELD_NOT_FOUND, name, Utils
.formatClassnameForMessage(contextObjectClass));
}
private void writeProperty(ExpressionState state, Object name, Object newValue) throws SpelException {
Object contextObject = state.getActiveContextObject();
EvaluationContext eContext = state.getEvaluationContext();
if (cachedWriterExecutor != null) {
try {
cachedWriterExecutor.execute(state.getEvaluationContext(), contextObject, newValue);
......@@ -149,7 +150,8 @@ public class PropertyOrFieldReference extends SpelNode {
try {
for (PropertyAccessor accessor : accessorsToTry) {
if (accessor instanceof CacheablePropertyAccessor) {
cachedWriterExecutor = ((CacheablePropertyAccessor)accessor).getWriterAccessor(eContext, contextObject, name);
cachedWriterExecutor = ((CacheablePropertyAccessor) accessor).getWriterAccessor(eContext,
contextObject, name);
if (cachedWriterExecutor != null) {
try {
cachedWriterExecutor.execute(state.getEvaluationContext(), contextObject, newValue);
......@@ -171,7 +173,8 @@ public class PropertyOrFieldReference extends SpelNode {
}
}
} catch (AccessException ae) {
throw new SpelException(getCharPositionInLine(), ae, SpelMessages.EXCEPTION_DURING_PROPERTY_WRITE, name, ae.getMessage());
throw new SpelException(getCharPositionInLine(), ae, SpelMessages.EXCEPTION_DURING_PROPERTY_WRITE,
name, ae.getMessage());
}
}
throw new SpelException(SpelMessages.PROPERTY_OR_FIELD_SETTER_NOT_FOUND, name, Utils
......@@ -204,8 +207,8 @@ public class PropertyOrFieldReference extends SpelNode {
* Determines the set of property resolvers that should be used to try and access a property on the specified target
* type. The resolvers are considered to be in an ordered list, however in the returned list any that are exact
* matches for the input target type (as opposed to 'general' resolvers that could work for any type) are placed at
* the start of the list. In addition, there are specific resolvers that exactly name the class in question and
* resolvers that name a specific class but it is a supertype of the class we have. These are put at the end of the
* the start of the list. In addition, there are specific resolvers that exactly name the class in question and
* resolvers that name a specific class but it is a supertype of the class we have. These are put at the end of the
* specific resolvers set and will be tried after exactly matching accessors but before generic accessors.
*
* @param targetType the type upon which property access is being attempted
......@@ -219,13 +222,16 @@ public class PropertyOrFieldReference extends SpelNode {
if (targets == null) { // generic resolver that says it can be used for any type
generalAccessors.add(resolver);
} else {
int pos = 0;
for (int i = 0; i < targets.length; i++) {
Class<?> clazz = targets[i];
if (clazz == targetType) { // put exact matches on the front to be tried first?
specificAccessors.add(pos++, resolver);
} else if (clazz.isAssignableFrom(targetType)) { // put supertype matches at the end of the specificAccessor list
generalAccessors.add(resolver);
if (targetType != null) {
int pos = 0;
for (int i = 0; i < targets.length; i++) {
Class<?> clazz = targets[i];
if (clazz == targetType) { // put exact matches on the front to be tried first?
specificAccessors.add(pos++, resolver);
} else if (clazz.isAssignableFrom(targetType)) { // put supertype matches at the end of the
// specificAccessor list
generalAccessors.add(resolver);
}
}
}
}
......
......@@ -48,6 +48,7 @@ public class AllTests {
suite.addTestSuite(TemplateExpressionParsingTests.class);
suite.addTestSuite(ExpressionLanguageScenarioTests.class);
suite.addTestSuite(ScenariosForSpringSecurity.class);
suite.addTestSuite(MapAccessTests.class);
suite.addTestSuite(SpelUtilitiesTests.class);
suite.addTestSuite(LiteralExpressionTests.class);
suite.addTestSuite(CompositeStringExpressionTests.class);
......
......@@ -15,7 +15,6 @@
*/
package org.springframework.expression.spel;
/**
* Tests the evaluation of real expressions in a real context.
*
......@@ -457,4 +456,5 @@ public class EvaluationTests extends ExpressionTestCase {
evaluateAndAskForReturnType("3*4+5", (short) 17, Short.class);
evaluateAndAskForReturnType("3*4+5", "17", String.class);
}
}
/*
* Copyright 2004-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.expression.spel;
import java.util.Map;
import org.springframework.expression.AccessException;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.PropertyAccessor;
import org.springframework.expression.spel.standard.StandardEvaluationContext;
/**
* Testing variations on map access.
*
* @author Andy Clement
*/
public class MapAccessTests extends ExpressionTestCase {
static class MapAccessor implements PropertyAccessor {
public boolean canRead(EvaluationContext context, Object target, Object name) throws AccessException {
return (((Map) target).containsKey(name));
}
public Object read(EvaluationContext context, Object target, Object name) throws AccessException {
return ((Map) target).get(name);
}
public boolean canWrite(EvaluationContext context, Object target, Object name) throws AccessException {
return true;
}
public void write(EvaluationContext context, Object target, Object name, Object newValue)
throws AccessException {
((Map) target).put(name, newValue);
}
public Class<?>[] getSpecificTargetClasses() {
return new Class[] { Map.class };
}
}
public void testSimpleMapAccess01() {
evaluate("testMap.get('monday')", "montag", String.class);
}
public void testMapAccessThroughIndexer() {
evaluate("testMap['monday']", "montag", String.class);
}
public void testCustomMapAccessor() throws Exception {
SpelExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext ctx = TestScenarioCreator.getTestEvaluationContext();
ctx.addPropertyAccessor(new MapAccessor());
Expression expr = parser.parseExpression("testMap.monday");
Object value = expr.getValue(ctx, String.class);
assertEquals("montag", value);
}
public void testVariableMapAccess() throws Exception {
SpelExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext ctx = TestScenarioCreator.getTestEvaluationContext();
ctx.setVariable("day", "saturday");
Expression expr = parser.parseExpression("testMap[#day]");
Object value = expr.getValue(ctx, String.class);
assertEquals("samstag", value);
}
// public void testMapAccess04() {
// evaluate("testMap[monday]", "montag", String.class);
// }
}
package org.springframework.expression.spel.testresources;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@SuppressWarnings("unused")
public class Inventor {
......@@ -11,15 +13,24 @@ public class Inventor {
private String nationality;
private String[] inventions;
public String randomField;
public Map testMap;
public Inventor(String name, Date birthdate, String nationality) {
this.name = name;
this.birthdate = birthdate;
this.nationality = nationality;
testMap = new HashMap();
testMap.put("monday", "montag");
testMap.put("tuesday", "dienstag");
testMap.put("wednesday", "mittwoch");
testMap.put("thursday", "donnerstag");
testMap.put("friday", "freitag");
testMap.put("saturday", "samstag");
testMap.put("sunday", "sonntag");
}
public void setPlaceOfBirth(PlaceOfBirth placeOfBirth2) {
this.placeOfBirth = placeOfBirth2;
placeOfBirth = placeOfBirth2;
}
public void setInventions(String[] inventions) {
......@@ -45,17 +56,20 @@ public class Inventor {
public String joinThreeStrings(String a, String b, String c) {
return a + b + c;
}
public int aVarargsMethod(String...strings ) {
if (strings==null) return 0;
public int aVarargsMethod(String... strings) {
if (strings == null)
return 0;
return strings.length;
}
public int aVarargsMethod2(int i, String...strings ) {
if (strings==null) return i;
return strings.length+i;
public int aVarargsMethod2(int i, String... strings) {
if (strings == null)
return i;
return strings.length + i;
}
public Inventor(String...strings ) {
public Inventor(String... strings) {
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册