@ -18,6 +18,7 @@ package org.springframework.expression.spel;
@@ -18,6 +18,7 @@ package org.springframework.expression.spel;
import static org.junit.Assert.assertEquals ;
import java.lang.reflect.Field ;
import java.util.ArrayList ;
import java.util.HashMap ;
import java.util.LinkedHashMap ;
@ -51,6 +52,7 @@ import org.springframework.expression.spel.support.StandardTypeLocator;
@@ -51,6 +52,7 @@ import org.springframework.expression.spel.support.StandardTypeLocator;
* Tests based on Jiras up to the release of Spring 3 . 0 . 0
*
* @author Andy Clement
* @author Clark Duplichien
* /
public class SpringEL300Tests extends ExpressionTestCase {
@ -1060,4 +1062,136 @@ public class SpringEL300Tests extends ExpressionTestCase {
@@ -1060,4 +1062,136 @@ public class SpringEL300Tests extends ExpressionTestCase {
Assert . assertEquals ( "abc" , exp . getValue ( ctx ) ) ;
}
/ * *
* We add property accessors in the order :
* First , Second , Third , Fourth .
* They are not utilized in this order ; preventing a priority or order of operations
* in evaluation of SPEL expressions for a given context .
* /
@Test
public void testPropertyAccessorOrder_8211 ( ) {
ExpressionParser expressionParser = new SpelExpressionParser ( ) ;
StandardEvaluationContext evaluationContext =
new StandardEvaluationContext ( new ContextObject ( ) ) ;
evaluationContext . addPropertyAccessor ( new TestPropertyAccessor ( "firstContext" ) ) ;
evaluationContext . addPropertyAccessor ( new TestPropertyAccessor ( "secondContext" ) ) ;
evaluationContext . addPropertyAccessor ( new TestPropertyAccessor ( "thirdContext" ) ) ;
evaluationContext . addPropertyAccessor ( new TestPropertyAccessor ( "fourthContext" ) ) ;
assertEquals ( "first" ,
expressionParser . parseExpression ( "shouldBeFirst" ) . getValue ( evaluationContext ) ) ;
assertEquals ( "second" ,
expressionParser . parseExpression ( "shouldBeSecond" ) . getValue ( evaluationContext ) ) ;
assertEquals ( "third" ,
expressionParser . parseExpression ( "shouldBeThird" ) . getValue ( evaluationContext ) ) ;
assertEquals ( "fourth" ,
expressionParser . parseExpression ( "shouldBeFourth" ) . getValue ( evaluationContext ) ) ;
}
// test not quite complete, it doesn't check that the list of resolvers at the end of
// PropertyOrFieldReference.getPropertyAccessorsToTry() doesn't contain duplicates, which
// is what it is trying to test by having a property accessor that returns specific
// classes Integer and Number
// @Test
// public void testPropertyAccessorOrder_8211_2() {
// ExpressionParser expressionParser = new SpelExpressionParser();
// StandardEvaluationContext evaluationContext =
// new StandardEvaluationContext(new Integer(42));
//
// evaluationContext.addPropertyAccessor(new TestPropertyAccessor2());
//
// assertEquals("42", expressionParser.parseExpression("x").getValue(evaluationContext));
// }
class TestPropertyAccessor implements PropertyAccessor {
private String mapName ;
public TestPropertyAccessor ( String mapName ) {
this . mapName = mapName ;
}
@SuppressWarnings ( "unchecked" )
public Map < String , String > getMap ( Object target ) {
try {
Field f = target . getClass ( ) . getDeclaredField ( mapName ) ;
return ( Map < String , String > ) f . get ( target ) ;
} catch ( Exception e ) {
}
return null ;
}
public boolean canRead ( EvaluationContext context , Object target , String name )
throws AccessException {
return getMap ( target ) . containsKey ( name ) ;
}
public boolean canWrite ( EvaluationContext context , Object target , String name )
throws AccessException {
return getMap ( target ) . containsKey ( name ) ;
}
public Class < ? > [ ] getSpecificTargetClasses ( ) {
return new Class [ ] { ContextObject . class } ;
}
public TypedValue read ( EvaluationContext context , Object target , String name )
throws AccessException {
return new TypedValue ( getMap ( target ) . get ( name ) ) ;
}
public void write ( EvaluationContext context , Object target , String name , Object newValue )
throws AccessException {
getMap ( target ) . put ( name , ( String ) newValue ) ;
}
}
// class TestPropertyAccessor2 implements PropertyAccessor {
//
// public Class[] getSpecificTargetClasses() {
// return new Class[]{Integer.class,Number.class};
// }
//
// public boolean canRead(EvaluationContext context, Object target, String name) throws AccessException {
// return true;
// }
//
// public TypedValue read(EvaluationContext context, Object target, String name) throws AccessException {
// return new TypedValue(target.toString(),TypeDescriptor.valueOf(String.class));
// }
//
// public boolean canWrite(EvaluationContext context, Object target, String name) throws AccessException {
// return false;
// }
//
// public void write(EvaluationContext context, Object target, String name, Object newValue)
// throws AccessException {
// throw new UnsupportedOperationException();
// }
//
// }
class ContextObject {
public Map < String , String > firstContext = new HashMap < String , String > ( ) ;
public Map < String , String > secondContext = new HashMap < String , String > ( ) ;
public Map < String , String > thirdContext = new HashMap < String , String > ( ) ;
public Map < String , String > fourthContext = new HashMap < String , String > ( ) ;
public ContextObject ( ) {
firstContext . put ( "shouldBeFirst" , "first" ) ;
secondContext . put ( "shouldBeFirst" , "second" ) ;
thirdContext . put ( "shouldBeFirst" , "third" ) ;
fourthContext . put ( "shouldBeFirst" , "fourth" ) ;
secondContext . put ( "shouldBeSecond" , "second" ) ;
thirdContext . put ( "shouldBeSecond" , "third" ) ;
fourthContext . put ( "shouldBeSecond" , "fourth" ) ;
thirdContext . put ( "shouldBeThird" , "third" ) ;
fourthContext . put ( "shouldBeThird" , "fourth" ) ;
fourthContext . put ( "shouldBeFourth" , "fourth" ) ;
}
public Map < String , String > getFirstContext ( ) { return firstContext ; }
public Map < String , String > getSecondContext ( ) { return secondContext ; }
public Map < String , String > getThirdContext ( ) { return thirdContext ; }
public Map < String , String > getFourthContext ( ) { return fourthContext ; }
}
}