diff --git a/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/OperatorGreaterThanOrEqual.java b/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/OperatorGreaterThanOrEqual.java index 47de02e4dfce8fddc50bf1190d02cee1f4b37c3e..e028bc0feb7aeb8bcd1abb9dc88c8821c38a3091 100644 --- a/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/OperatorGreaterThanOrEqual.java +++ b/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/OperatorGreaterThanOrEqual.java @@ -42,19 +42,14 @@ public class OperatorGreaterThanOrEqual extends Operator { Object left = getLeftOperand().getValueInternal(state).getValue(); Object right = getRightOperand().getValueInternal(state).getValue(); if (left instanceof Number && right instanceof Number) { - Number op1 = (Number) left; - Number op2 = (Number) right; - if (op1 instanceof Double || op2 instanceof Double) { - return BooleanTypedValue.forValue(op1.doubleValue() >= op2.doubleValue()); - } - else if (op1 instanceof Float || op2 instanceof Float) { - return BooleanTypedValue.forValue(op1.floatValue() >= op2.floatValue()); - } - else if (op1 instanceof Long || op2 instanceof Long) { - return BooleanTypedValue.forValue( op1.longValue() >= op2.longValue()); - } - else { - return BooleanTypedValue.forValue(op1.intValue() >= op2.intValue()); + Number leftNumber = (Number) left; + Number rightNumber = (Number) right; + if (leftNumber instanceof Double || rightNumber instanceof Double) { + return BooleanTypedValue.forValue(leftNumber.doubleValue() >= rightNumber.doubleValue()); + } else if (leftNumber instanceof Long || rightNumber instanceof Long) { + return BooleanTypedValue.forValue( leftNumber.longValue() >= rightNumber.longValue()); + } else { + return BooleanTypedValue.forValue(leftNumber.intValue() >= rightNumber.intValue()); } } return BooleanTypedValue.forValue(state.getTypeComparator().compare(left, right) >= 0); diff --git a/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/OperatorMinus.java b/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/OperatorMinus.java index 01628594b95999d6942dbfdb80fbc21ad1e9be7c..45a2ac3dff2d0ffc12851ea508ee737be296bc57 100644 --- a/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/OperatorMinus.java +++ b/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/OperatorMinus.java @@ -21,11 +21,18 @@ import org.springframework.expression.EvaluationException; import org.springframework.expression.Operation; import org.springframework.expression.TypedValue; import org.springframework.expression.spel.ExpressionState; -import org.springframework.expression.spel.SpelException; -import org.springframework.expression.spel.SpelMessages; /** - * Implements the minus operator. If there is only one operand it is a unary minus. + * The minus operator supports: + * + * It can be used as a unary operator for numbers (double/long/int). The standard promotions are performed + * when the operand types vary (double-int=double). + * For other options it defers to the registered overloader. * * @author Andy Clement * @since 3.0 @@ -36,43 +43,24 @@ public class OperatorMinus extends Operator { super(payload); } - @Override - public String getOperatorName() { - return "-"; - } - - @Override - public String toStringAST() { - if (getRightOperand() == null) { // unary minus - return new StringBuilder().append("-").append(getLeftOperand()).toString(); - } - return super.toStringAST(); - } - @Override public TypedValue getValueInternal(ExpressionState state) throws EvaluationException { SpelNodeImpl leftOp = getLeftOperand(); SpelNodeImpl rightOp = getRightOperand(); if (rightOp == null) {// If only one operand, then this is unary minus - Object left = leftOp.getValueInternal(state).getValue(); - if (left instanceof Number) { - Number n = (Number) left; - if (left instanceof Double) { + Object operand = leftOp.getValueInternal(state).getValue(); + if (operand instanceof Number) { + Number n = (Number) operand; + if (operand instanceof Double) { return new TypedValue(0 - n.doubleValue(),DOUBLE_TYPE_DESCRIPTOR); - } - else if (left instanceof Float) { - return new TypedValue(0 - n.floatValue(),FLOAT_TYPE_DESCRIPTOR); - } - else if (left instanceof Long) { + } else if (operand instanceof Long) { return new TypedValue(0 - n.longValue(),LONG_TYPE_DESCRIPTOR); - } - else { + } else { return new TypedValue(0 - n.intValue(),INTEGER_TYPE_DESCRIPTOR); } } - throw new SpelException(SpelMessages.CANNOT_NEGATE_TYPE, left.getClass().getName()); - } - else { + return state.operate(Operation.SUBTRACT, operand, null); + } else { Object left = leftOp.getValueInternal(state).getValue(); Object right = rightOp.getValueInternal(state).getValue(); if (left instanceof Number && right instanceof Number) { @@ -80,19 +68,32 @@ public class OperatorMinus extends Operator { Number op2 = (Number) right; if (op1 instanceof Double || op2 instanceof Double) { return new TypedValue(op1.doubleValue() - op2.doubleValue(),DOUBLE_TYPE_DESCRIPTOR); - } - else if (op1 instanceof Float || op2 instanceof Float) { - return new TypedValue(op1.floatValue() - op2.floatValue(),FLOAT_TYPE_DESCRIPTOR); - } - else if (op1 instanceof Long || op2 instanceof Long) { + } else if (op1 instanceof Long || op2 instanceof Long) { return new TypedValue(op1.longValue() - op2.longValue(),LONG_TYPE_DESCRIPTOR); - } - else { + } else { return new TypedValue(op1.intValue() - op2.intValue(),INTEGER_TYPE_DESCRIPTOR); } + } else if (left instanceof String && right instanceof Integer && ((String)left).length()==1) { + String theString = (String) left; + Integer theInteger = (Integer) right; + // implements character - int (ie. b - 1 = a) + return new TypedValue(Character.toString((char) (theString.charAt(0) - theInteger)),STRING_TYPE_DESCRIPTOR); } return state.operate(Operation.SUBTRACT, left, right); } } + @Override + public String getOperatorName() { + return "-"; + } + + @Override + public String toStringAST() { + if (getRightOperand() == null) { // unary minus + return new StringBuilder().append("-").append(getLeftOperand().toStringAST()).toString(); + } + return super.toStringAST(); + } + } diff --git a/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/OperatorModulus.java b/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/OperatorModulus.java index b3e71e064f0dc4a3c7dd03e3851f08ea22a61990..20789c75f5f1f445e8c4447227e23521f5809fa9 100644 --- a/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/OperatorModulus.java +++ b/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/OperatorModulus.java @@ -48,14 +48,9 @@ public class OperatorModulus extends Operator { Number op2 = (Number) operandTwo; if (op1 instanceof Double || op2 instanceof Double) { return new TypedValue(op1.doubleValue() % op2.doubleValue(),DOUBLE_TYPE_DESCRIPTOR); - } - else if (op1 instanceof Float || op2 instanceof Float) { - return new TypedValue(op1.floatValue() % op2.floatValue(),FLOAT_TYPE_DESCRIPTOR); - } - else if (op1 instanceof Long || op2 instanceof Long) { + } else if (op1 instanceof Long || op2 instanceof Long) { return new TypedValue(op1.longValue() % op2.longValue(),LONG_TYPE_DESCRIPTOR); - } - else { + } else { return new TypedValue(op1.intValue() % op2.intValue(),INTEGER_TYPE_DESCRIPTOR); } } diff --git a/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/OperatorMultiply.java b/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/OperatorMultiply.java index 0f9ee0a0f41f5b368bb95d74c09daeb4c78a0341..e788f7e33865ea10857950be8b966c566a276566 100644 --- a/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/OperatorMultiply.java +++ b/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/OperatorMultiply.java @@ -32,6 +32,8 @@ import org.springframework.expression.spel.ExpressionState; * Otherwise, if either operand is of type long, the other is converted to long.
* Otherwise, both operands are converted to type int. * + *

+ * * @author Andy Clement * @since 3.0 */ @@ -55,28 +57,22 @@ public class OperatorMultiply extends Operator { Object operandOne = getLeftOperand().getValueInternal(state).getValue(); Object operandTwo = getRightOperand().getValueInternal(state).getValue(); if (operandOne instanceof Number && operandTwo instanceof Number) { - Number op1 = (Number) operandOne; - Number op2 = (Number) operandTwo; - if (op1 instanceof Double || op2 instanceof Double) { - return new TypedValue(op1.doubleValue() * op2.doubleValue(),DOUBLE_TYPE_DESCRIPTOR); - } - else if (op1 instanceof Float || op2 instanceof Float) { - return new TypedValue(op1.floatValue() * op2.floatValue(),FLOAT_TYPE_DESCRIPTOR); - } - else if (op1 instanceof Long || op2 instanceof Long) { - return new TypedValue(op1.longValue() * op2.longValue(),LONG_TYPE_DESCRIPTOR); + Number leftNumber = (Number) operandOne; + Number rightNumber = (Number) operandTwo; + if (leftNumber instanceof Double || rightNumber instanceof Double) { + return new TypedValue(leftNumber.doubleValue() * rightNumber.doubleValue(), DOUBLE_TYPE_DESCRIPTOR); + } else if (leftNumber instanceof Long || rightNumber instanceof Long) { + return new TypedValue(leftNumber.longValue() * rightNumber.longValue(), LONG_TYPE_DESCRIPTOR); + } else { + return new TypedValue(leftNumber.intValue() * rightNumber.intValue(), INTEGER_TYPE_DESCRIPTOR); } - else { - return new TypedValue(op1.intValue() * op2.intValue(),INTEGER_TYPE_DESCRIPTOR); - } - } - else if (operandOne instanceof String && operandTwo instanceof Integer) { + } else if (operandOne instanceof String && operandTwo instanceof Integer) { int repeats = (Integer) operandTwo; StringBuilder result = new StringBuilder(); for (int i = 0; i < repeats; i++) { result.append(operandOne); } - return new TypedValue(result.toString(),STRING_TYPE_DESCRIPTOR); + return new TypedValue(result.toString(), STRING_TYPE_DESCRIPTOR); } return state.operate(Operation.MULTIPLY, operandOne, operandTwo); } diff --git a/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/OperatorPlus.java b/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/OperatorPlus.java index 38111078cad1fb1dee9743d701b7950b94ef03ef..51160516d16edc2705760b6811598949ee1b9189 100644 --- a/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/OperatorPlus.java +++ b/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/OperatorPlus.java @@ -23,6 +23,17 @@ import org.springframework.expression.TypedValue; import org.springframework.expression.spel.ExpressionState; /** + * The plus operator will: + *

+ * It can be used as a unary operator for numbers (double/long/int). The standard promotions are performed + * when the operand types vary (double+int=double). + * For other options it defers to the registered overloader. + * * @author Andy Clement * @since 3.0 */ @@ -39,7 +50,13 @@ public class OperatorPlus extends Operator { if (rightOp == null) { // If only one operand, then this is unary plus Object operandOne = leftOp.getValueInternal(state).getValue(); if (operandOne instanceof Number) { - return new TypedValue(((Number) operandOne).intValue(),INTEGER_TYPE_DESCRIPTOR); + if (operandOne instanceof Double) { + return new TypedValue(((Double) operandOne).doubleValue(), DOUBLE_TYPE_DESCRIPTOR); + } else if (operandOne instanceof Long) { + return new TypedValue(((Long) operandOne).longValue(), LONG_TYPE_DESCRIPTOR); + } else { + return new TypedValue(((Integer) operandOne).intValue(), INTEGER_TYPE_DESCRIPTOR); + } } return state.operate(Operation.ADD, operandOne, null); } @@ -51,28 +68,23 @@ public class OperatorPlus extends Operator { Number op2 = (Number) operandTwo; if (op1 instanceof Double || op2 instanceof Double) { return new TypedValue(op1.doubleValue() + op2.doubleValue(),DOUBLE_TYPE_DESCRIPTOR); - } - else if (op1 instanceof Float || op2 instanceof Float) { - return new TypedValue(op1.floatValue() + op2.floatValue(),FLOAT_TYPE_DESCRIPTOR); - } - else if (op1 instanceof Long || op2 instanceof Long) { + } else if (op1 instanceof Long || op2 instanceof Long) { return new TypedValue(op1.longValue() + op2.longValue(),LONG_TYPE_DESCRIPTOR); - } - else { // TODO what about overflow? + } else { // TODO what about overflow? return new TypedValue(op1.intValue() + op2.intValue(),INTEGER_TYPE_DESCRIPTOR); } - } - else if (operandOne instanceof String && operandTwo instanceof String) { + } else if (operandOne instanceof String && operandTwo instanceof String) { return new TypedValue(new StringBuilder((String) operandOne).append((String) operandTwo).toString(),STRING_TYPE_DESCRIPTOR); - } - else if (operandOne instanceof String && operandTwo instanceof Integer) { - String l = (String) operandOne; - Integer i = (Integer) operandTwo; + } else if (operandOne instanceof String && operandTwo instanceof Integer && ((String)operandOne).length()==1) { + String theString = (String) operandOne; + Integer theInteger = (Integer) operandTwo; // implements character + int (ie. a + 1 = b) - if (l.length() == 1) { - return new TypedValue(Character.toString((char) (l.charAt(0) + i)),STRING_TYPE_DESCRIPTOR); - } - return new TypedValue(new StringBuilder(l).append(i).toString(),STRING_TYPE_DESCRIPTOR); + return new TypedValue(Character.toString((char) (theString.charAt(0) + theInteger)),STRING_TYPE_DESCRIPTOR); + } else if (operandOne instanceof Integer && ((operandTwo instanceof String) && ((String)operandTwo).length()==1)) { + String theString = (String) operandTwo; + Integer theInteger = (Integer) operandOne; + // implements character + int (ie. 1 + a = b) + return new TypedValue(Character.toString((char) (theString.charAt(0) + theInteger)),STRING_TYPE_DESCRIPTOR); } return state.operate(Operation.ADD, operandOne, operandTwo); } @@ -86,7 +98,7 @@ public class OperatorPlus extends Operator { @Override public String toStringAST() { if (getRightOperand() == null) { // unary plus - return new StringBuilder().append("+").append(getLeftOperand()).toString(); + return new StringBuilder().append("+").append(getLeftOperand().toStringAST()).toString(); } return super.toStringAST(); } diff --git a/org.springframework.expression/src/test/java/org/springframework/expression/spel/EvaluationTests.java b/org.springframework.expression/src/test/java/org/springframework/expression/spel/EvaluationTests.java index 6427fa7eb213257d256ff7592071cb9e5679feb2..c32ed1de72336a0524aea97dc1e755e007b12025 100644 --- a/org.springframework.expression/src/test/java/org/springframework/expression/spel/EvaluationTests.java +++ b/org.springframework.expression/src/test/java/org/springframework/expression/spel/EvaluationTests.java @@ -16,6 +16,8 @@ package org.springframework.expression.spel; +import java.util.ArrayList; + import org.springframework.expression.Expression; /** @@ -273,9 +275,9 @@ public class EvaluationTests extends ExpressionTestCase { // } // projection and selection - // public void testProjection01() { - // evaluate("{1,2,3,4,5,6,7,8,9,10}.!{#isEven(#this)}", "[n, y, n, y, n, y, n, y, n, y]", ArrayList.class); - // } +// public void testProjection01() { +// evaluate("{1,2,3,4,5,6,7,8,9,10}.!{#isEven(#this)}", "[n, y, n, y, n, y, n, y, n, y]", ArrayList.class); +// } // // public void testProjection02() { // evaluate("#{'a':'y','b':'n','c':'y'}.!{value=='y'?key:null}.nonnull().sort()", "[a, c]", ArrayList.class); @@ -290,10 +292,17 @@ public class EvaluationTests extends ExpressionTestCase { // evaluate("{1,2,3,4,5,6,7,8,9,10}.!{$index>5?'y':'n'}", "[n, n, n, n, n, n, y, y, y, y]", ArrayList.class); // } - // public void testSelection01() { - // evaluate("{1,2,3,4,5,6,7,8,9,10}.?{#isEven(#this) == 'y'}", "[2, 4, 6, 8, 10]", ArrayList.class); - // } - + public void testSelection01() { + // inline list creation not supported: + // evaluate("{1,2,3,4,5,6,7,8,9,10}.?{#isEven(#this) == 'y'}", "[2, 4, 6, 8, 10]", ArrayList.class); + } + + public void testSelection02() { + evaluate("testMap.keySet().?{#this matches '.*o.*'}", "[monday]", ArrayList.class); + evaluate("testMap.keySet().?{#this matches '.*r.*'}.contains('saturday')", "true", Boolean.class); + evaluate("testMap.keySet().?{#this matches '.*r.*'}.size()", "3", Integer.class); + } + // public void testSelectionError_NonBooleanSelectionCriteria() { // evaluateAndCheckError("{1,2,3,4,5,6,7,8,9,10}.?{'nonboolean'}", // SpelMessages.RESULT_OF_SELECTION_CRITERIA_IS_NOT_BOOLEAN); diff --git a/org.springframework.expression/src/test/java/org/springframework/expression/spel/OperatorTests.java b/org.springframework.expression/src/test/java/org/springframework/expression/spel/OperatorTests.java index 9a8a8b7d87d4f7423d920d8577f82e23cb5bdd88..c193e1a309d344a0551deb0b65ce7e7b158cbead 100644 --- a/org.springframework.expression/src/test/java/org/springframework/expression/spel/OperatorTests.java +++ b/org.springframework.expression/src/test/java/org/springframework/expression/spel/OperatorTests.java @@ -51,8 +51,8 @@ public class OperatorTests extends ExpressionTestCase { evaluate("3L <= 5L", true, Boolean.class); evaluate("5L <= 3L", false, Boolean.class); evaluate("5L <= 5L", true, Boolean.class); - evaluate("3.0d < 5.0d", true, Boolean.class); - evaluate("5.0d < 3.0d", false, Boolean.class); + evaluate("3.0d <= 5.0d", true, Boolean.class); + evaluate("5.0d <= 3.0d", false, Boolean.class); evaluate("5.0d <= 5.0d", true, Boolean.class); evaluate("'abc' <= 'def'",true,Boolean.class); evaluate("'def' <= 'abc'",false,Boolean.class); @@ -63,6 +63,7 @@ public class OperatorTests extends ExpressionTestCase { evaluate("3 == 5", false, Boolean.class); evaluate("5 == 3", false, Boolean.class); evaluate("6 == 6", true, Boolean.class); + evaluate("'abc' == null", false, Boolean.class); } public void testNotEqual() { @@ -74,7 +75,17 @@ public class OperatorTests extends ExpressionTestCase { public void testGreaterThanOrEqual() { evaluate("3 >= 5", false, Boolean.class); evaluate("5 >= 3", true, Boolean.class); - evaluate("6 >= 6", true, Boolean.class); + evaluate("6 >= 6", true, Boolean.class); + evaluate("3L >= 5L", false, Boolean.class); + evaluate("5L >= 3L", true, Boolean.class); + evaluate("5L >= 5L", true, Boolean.class); + evaluate("3.0d >= 5.0d", false, Boolean.class); + evaluate("5.0d >= 3.0d", true, Boolean.class); + evaluate("5.0d <= 5.0d", true, Boolean.class); + evaluate("'abc' >= 'def'",false,Boolean.class); + evaluate("'def' >= 'abc'",true,Boolean.class); + evaluate("'abc' >= 'abc'",true,Boolean.class); + } public void testGreaterThan() { @@ -104,9 +115,49 @@ public class OperatorTests extends ExpressionTestCase { evaluate("2 + 4", "6", Integer.class); evaluate("5 - 4", "1", Integer.class); evaluate("3 * 5", 15, Integer.class); + evaluate("3.2d * 5", 16.0d, Double.class); + evaluate("3 * 5f", 15d, Double.class); evaluate("3 / 1", 3, Integer.class); evaluate("3 % 2", 1, Integer.class); } + + public void testPlus() throws Exception { + evaluate("'a' + 2", "c", String.class); + evaluateAndCheckError("'ab' + 2", SpelMessages.OPERATOR_NOT_SUPPORTED_BETWEEN_TYPES); + evaluate("2+'a' ", "c", String.class); + evaluateAndCheckError("2+'ab'",SpelMessages.OPERATOR_NOT_SUPPORTED_BETWEEN_TYPES); + SpelExpression expr = (SpelExpression)parser.parseExpression("+3"); + assertEquals("+3",expr.toStringAST()); + expr = (SpelExpression)parser.parseExpression("2+3"); + assertEquals("(2 + 3)",expr.toStringAST()); + + evaluate("+5d",5d,Double.class); + evaluate("+5L",5L,Long.class); + evaluate("+5",5,Integer.class); + evaluateAndCheckError("+'abc'",SpelMessages.OPERATOR_NOT_SUPPORTED_BETWEEN_TYPES); + } + + public void testMinus() throws Exception { + evaluate("'c' - 2", "a", String.class); + evaluateAndCheckError("'ab' - 2", SpelMessages.OPERATOR_NOT_SUPPORTED_BETWEEN_TYPES); + evaluateAndCheckError("2-'ab'",SpelMessages.OPERATOR_NOT_SUPPORTED_BETWEEN_TYPES); + SpelExpression expr = (SpelExpression)parser.parseExpression("-3"); + assertEquals("-3",expr.toStringAST()); + expr = (SpelExpression)parser.parseExpression("2-3"); + assertEquals("(2 - 3)",expr.toStringAST()); + + evaluate("-5d",-5d,Double.class); + evaluate("-5L",-5L,Long.class); + evaluate("-5",-5,Integer.class); + evaluateAndCheckError("-'abc'",SpelMessages.OPERATOR_NOT_SUPPORTED_BETWEEN_TYPES); + } + + public void testModulus() { + evaluate("3%2",1,Integer.class); + evaluate("3L%2L",1L,Long.class); + evaluate("3.0d%2.0d",1d,Double.class); + evaluateAndCheckError("'abc'%'def'",SpelMessages.OPERATOR_NOT_SUPPORTED_BETWEEN_TYPES); + } public void testDivide() { evaluate("4L/2L",2L,Long.class); @@ -120,10 +171,6 @@ public class OperatorTests extends ExpressionTestCase { evaluateAndAskForReturnType("8/4", new Float(2.0), Float.class); } - // public void testMathOperatorDivide04() { - // evaluateAndAskForReturnType("8.4 / 4", "2", Integer.class); - // } - public void testDoubles() { evaluate("3.0d == 5.0d", false, Boolean.class); evaluate("3.0d == 3.0d", true, Boolean.class); @@ -169,6 +216,19 @@ public class OperatorTests extends ExpressionTestCase { node = getOperatorNode((SpelExpression)parser.parseExpression("3<=4")); assertEquals("<=",node.getOperatorName()); + + node = getOperatorNode((SpelExpression)parser.parseExpression("3*4")); + assertEquals("*",node.getOperatorName()); + + node = getOperatorNode((SpelExpression)parser.parseExpression("3%4")); + assertEquals("%",node.getOperatorName()); + + node = getOperatorNode((SpelExpression)parser.parseExpression("3>=4")); + assertEquals(">=",node.getOperatorName()); + } + + public void testOperatorOverloading() { + evaluateAndCheckError("'a' * '2'", SpelMessages.OPERATOR_NOT_SUPPORTED_BETWEEN_TYPES); } public void testMixedOperands_FloatsAndDoubles() { @@ -201,6 +261,9 @@ public class OperatorTests extends ExpressionTestCase { evaluate("3L == 3L", true, Boolean.class); evaluate("3L != 4L", true, Boolean.class); evaluate("3L != 3L", false, Boolean.class); + evaluate("3L * 50L", 150L, Long.class); + evaluate("3L + 50L", 53L, Long.class); + evaluate("3L - 50L", -47L, Long.class); } private Operator getOperatorNode(SpelExpression e) {