1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.expression.spel.ast;
18
19 import org.springframework.asm.MethodVisitor;
20 import org.springframework.expression.EvaluationException;
21 import org.springframework.expression.TypedValue;
22 import org.springframework.expression.spel.CodeFlow;
23 import org.springframework.expression.spel.ExpressionState;
24 import org.springframework.expression.spel.SpelEvaluationException;
25
26
27
28
29
30
31
32 public class CompoundExpression extends SpelNodeImpl {
33
34 public CompoundExpression(int pos,SpelNodeImpl... expressionComponents) {
35 super(pos, expressionComponents);
36 if (expressionComponents.length < 2) {
37 throw new IllegalStateException("Do not build compound expressions with less than two entries: " +
38 expressionComponents.length);
39 }
40 }
41
42
43 @Override
44 protected ValueRef getValueRef(ExpressionState state) throws EvaluationException {
45 if (getChildCount() == 1) {
46 return this.children[0].getValueRef(state);
47 }
48
49 SpelNodeImpl nextNode = this.children[0];
50 try {
51 TypedValue result = nextNode.getValueInternal(state);
52 int cc = getChildCount();
53 for (int i = 1; i < cc - 1; i++) {
54 try {
55 state.pushActiveContextObject(result);
56 nextNode = this.children[i];
57 result = nextNode.getValueInternal(state);
58 }
59 finally {
60 state.popActiveContextObject();
61 }
62 }
63 try {
64 state.pushActiveContextObject(result);
65 nextNode = this.children[cc-1];
66 return nextNode.getValueRef(state);
67 }
68 finally {
69 state.popActiveContextObject();
70 }
71 }
72 catch (SpelEvaluationException ex) {
73
74 ex.setPosition(nextNode.getStartPosition());
75 throw ex;
76 }
77 }
78
79
80
81
82
83
84
85 @Override
86 public TypedValue getValueInternal(ExpressionState state) throws EvaluationException {
87 ValueRef ref = getValueRef(state);
88 TypedValue result = ref.getValue();
89 this.exitTypeDescriptor = this.children[this.children.length - 1].exitTypeDescriptor;
90 return result;
91 }
92
93 @Override
94 public void setValue(ExpressionState state, Object value) throws EvaluationException {
95 getValueRef(state).setValue(value);
96 }
97
98 @Override
99 public boolean isWritable(ExpressionState state) throws EvaluationException {
100 return getValueRef(state).isWritable();
101 }
102
103 @Override
104 public String toStringAST() {
105 StringBuilder sb = new StringBuilder();
106 for (int i = 0; i < getChildCount(); i++) {
107 if (i > 0) {
108 sb.append(".");
109 }
110 sb.append(getChild(i).toStringAST());
111 }
112 return sb.toString();
113 }
114
115 @Override
116 public boolean isCompilable() {
117 for (SpelNodeImpl child: this.children) {
118 if (!child.isCompilable()) {
119 return false;
120 }
121 }
122 return true;
123 }
124
125 @Override
126 public void generateCode(MethodVisitor mv, CodeFlow cf) {
127
128 for (int i = 0; i < this.children.length;i++) {
129 SpelNodeImpl child = this.children[i];
130 if (child instanceof TypeReference && (i + 1) < this.children.length &&
131 this.children[i + 1] instanceof MethodReference) {
132 continue;
133 }
134 child.generateCode(mv, cf);
135 }
136 cf.pushDescriptor(this.exitTypeDescriptor);
137 }
138
139 }