1
1
/*
2
- * Copyright 2002-2012 the original author or authors.
2
+ * Copyright 2002-2013 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
30
30
import org .springframework .expression .TypeComparator ;
31
31
import org .springframework .expression .TypeConverter ;
32
32
import org .springframework .expression .TypedValue ;
33
+ import org .springframework .util .Assert ;
33
34
34
35
/**
35
- * An ExpressionState is for maintaining per-expression-evaluation state, any changes to it are not seen by other
36
- * expressions but it gives a place to hold local variables and for component expressions in a compound expression to
37
- * communicate state. This is in contrast to the EvaluationContext, which is shared amongst expression evaluations, and
38
- * any changes to it will be seen by other expressions or any code that chooses to ask questions of the context.
36
+ * An ExpressionState is for maintaining per-expression-evaluation state, any changes to
37
+ * it are not seen by other expressions but it gives a place to hold local variables and
38
+ * for component expressions in a compound expression to communicate state. This is in
39
+ * contrast to the EvaluationContext, which is shared amongst expression evaluations, and
40
+ * any changes to it will be seen by other expressions or any code that chooses to ask
41
+ * questions of the context.
39
42
*
40
- * <p>It also acts as a place for to define common utility routines that the various Ast nodes might need.
43
+ * <p>It also acts as a place for to define common utility routines that the various AST
44
+ * nodes might need.
41
45
*
42
46
* @author Andy Clement
43
47
* @since 3.0
@@ -46,35 +50,33 @@ public class ExpressionState {
46
50
47
51
private final EvaluationContext relatedContext ;
48
52
49
- private Stack < VariableScope > variableScopes ;
53
+ private final TypedValue rootObject ;
50
54
51
- private Stack < TypedValue > contextObjects ;
55
+ private final SpelParserConfiguration configuration ;
52
56
53
- private final TypedValue rootObject ;
57
+ private Stack < VariableScope > variableScopes ;
54
58
55
- private SpelParserConfiguration configuration ;
59
+ private Stack < TypedValue > contextObjects ;
56
60
57
61
58
62
public ExpressionState (EvaluationContext context ) {
59
- this .relatedContext = context ;
60
- this .rootObject = context .getRootObject ();
63
+ this (context , context .getRootObject (), new SpelParserConfiguration (false , false ));
61
64
}
62
65
63
66
public ExpressionState (EvaluationContext context , SpelParserConfiguration configuration ) {
64
- this .relatedContext = context ;
65
- this .configuration = configuration ;
66
- this .rootObject = context .getRootObject ();
67
+ this (context , context .getRootObject (), configuration );
67
68
}
68
69
69
70
public ExpressionState (EvaluationContext context , TypedValue rootObject ) {
70
- this .relatedContext = context ;
71
- this .rootObject = rootObject ;
71
+ this (context , rootObject , new SpelParserConfiguration (false , false ));
72
72
}
73
73
74
74
public ExpressionState (EvaluationContext context , TypedValue rootObject , SpelParserConfiguration configuration ) {
75
+ Assert .notNull (context , "EvaluationContext must not be null" );
76
+ Assert .notNull (configuration , "SpelParserConfiguration must not be null" );
75
77
this .relatedContext = context ;
76
- this .configuration = configuration ;
77
78
this .rootObject = rootObject ;
79
+ this .configuration = configuration ;
78
80
}
79
81
80
82
@@ -90,23 +92,22 @@ private void ensureVariableScopesInitialized() {
90
92
* The active context object is what unqualified references to properties/etc are resolved against.
91
93
*/
92
94
public TypedValue getActiveContextObject () {
93
- if (this .contextObjects == null || this .contextObjects .isEmpty ()) {
95
+ if (this .contextObjects == null || this .contextObjects .isEmpty ()) {
94
96
return this .rootObject ;
95
97
}
96
-
97
98
return this .contextObjects .peek ();
98
99
}
99
100
100
101
public void pushActiveContextObject (TypedValue obj ) {
101
- if (this .contextObjects == null ) {
102
- this .contextObjects = new Stack <TypedValue >();
102
+ if (this .contextObjects == null ) {
103
+ this .contextObjects = new Stack <TypedValue >();
103
104
}
104
105
this .contextObjects .push (obj );
105
106
}
106
107
107
108
public void popActiveContextObject () {
108
- if (this .contextObjects == null ) {
109
- this .contextObjects = new Stack <TypedValue >();
109
+ if (this .contextObjects == null ) {
110
+ this .contextObjects = new Stack <TypedValue >();
110
111
}
111
112
this .contextObjects .pop ();
112
113
}
@@ -138,7 +139,8 @@ public Class<?> findType(String type) throws EvaluationException {
138
139
}
139
140
140
141
public Object convertValue (Object value , TypeDescriptor targetTypeDescriptor ) throws EvaluationException {
141
- return this .relatedContext .getTypeConverter ().convertValue (value , TypeDescriptor .forObject (value ), targetTypeDescriptor );
142
+ return this .relatedContext .getTypeConverter ().convertValue (value ,
143
+ TypeDescriptor .forObject (value ), targetTypeDescriptor );
142
144
}
143
145
144
146
public TypeConverter getTypeConverter () {
@@ -151,9 +153,8 @@ public Object convertValue(TypedValue value, TypeDescriptor targetTypeDescriptor
151
153
}
152
154
153
155
/*
154
- * A new scope is entered when a function is invoked
156
+ * A new scope is entered when a function is invoked.
155
157
*/
156
-
157
158
public void enterScope (Map <String , Object > argMap ) {
158
159
ensureVariableScopesInitialized ();
159
160
this .variableScopes .push (new VariableScope (argMap ));
@@ -192,8 +193,8 @@ public TypedValue operate(Operation op, Object left, Object right) throws Evalua
192
193
return new TypedValue (returnValue );
193
194
}
194
195
else {
195
- String leftType = (left == null ? "null" : left .getClass ().getName ());
196
- String rightType = (right == null ?"null" : right .getClass ().getName ());
196
+ String leftType = (left == null ? "null" : left .getClass ().getName ());
197
+ String rightType = (right == null ? "null" : right .getClass ().getName ());
197
198
throw new SpelEvaluationException (SpelMessage .OPERATOR_NOT_SUPPORTED_BETWEEN_TYPES , op , leftType , rightType );
198
199
}
199
200
}
@@ -210,16 +211,20 @@ public SpelParserConfiguration getConfiguration() {
210
211
return this .configuration ;
211
212
}
212
213
214
+
213
215
/**
214
- * A new scope is entered when a function is called and it is used to hold the parameters to the function call. If the names
215
- * of the parameters clash with those in a higher level scope, those in the higher level scope will not be accessible whilst
216
- * the function is executing. When the function returns the scope is exited.
216
+ * A new scope is entered when a function is called and it is used to hold the
217
+ * parameters to the function call. If the names of the parameters clash with
218
+ * those in a higher level scope, those in the higher level scope will not be
219
+ * accessible whilst the function is executing. When the function returns,
220
+ * the scope is exited.
217
221
*/
218
222
private static class VariableScope {
219
223
220
224
private final Map <String , Object > vars = new HashMap <String , Object >();
221
225
222
- public VariableScope () { }
226
+ public VariableScope () {
227
+ }
223
228
224
229
public VariableScope (Map <String , Object > arguments ) {
225
230
if (arguments != null ) {
0 commit comments