1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.commons.jelly.expression;
17
18 import java.util.ArrayList;
19 import java.util.Collections;
20 import java.util.Iterator;
21 import java.util.List;
22
23 import org.apache.commons.collections.iterators.SingletonIterator;
24
25 import org.apache.commons.jelly.JellyContext;
26 import org.apache.commons.jelly.JellyException;
27
28 /***
29 * <p><code>CompositeExpression</code> is a Composite expression made up of several
30 * Expression objects which are concatenated into a single String.</p>
31 *
32 * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
33 * @version $Revision: 155420 $
34 */
35 public class CompositeExpression extends ExpressionSupport {
36
37 /*** The expressions */
38 private List expressions;
39
40 public CompositeExpression() {
41 this.expressions = new ArrayList();
42 }
43
44 public CompositeExpression(List expressions) {
45 this.expressions = expressions;
46 }
47
48 public String toString() {
49 return super.toString() + "[expressions=" + expressions +"]";
50 }
51
52 /***
53 * Parses the given String to be either a ConstantExpresssion, an Expression denoted as
54 * "${foo}" or some String with embedded expresssions such as "abc${something}def${else}xyz"
55 * which results in a CompositeExpression being returned.
56 *
57 * @param text is the String to parse into expressions
58 * @param factory is the Factory of Expression objects used to create expresssions for the contents
59 * of the String "foo" inside expressions such as "${foo}"
60 *
61 * @return the Expresssion for the given String.
62 * @throws JellyException if the text is invalid (such as missing '}' character).
63 * @throws JellyException if there was some problem creating the underlying Expression object
64 * from the ExpressionFactory
65 */
66 public static Expression parse(String text, ExpressionFactory factory) throws JellyException {
67
68 int len = text.length();
69
70 int startIndex = text.indexOf( "${" );
71
72 if ( startIndex < 0) {
73 return new ConstantExpression(text);
74 }
75
76 int endIndex = text.indexOf( "}", startIndex+2 );
77
78 if ( endIndex < 0 ) {
79 throw new JellyException( "Missing '}' character at the end of expression: " + text );
80 }
81 if ( startIndex == 0 && endIndex == len - 1 ) {
82 return factory.createExpression(text.substring(2, endIndex));
83 }
84
85 CompositeExpression answer = new CompositeExpression();
86
87 int cur = 0;
88 char c = 0;
89
90 StringBuffer chars = new StringBuffer();
91 StringBuffer expr = new StringBuffer();
92
93 MAIN:
94 while ( cur < len ) {
95 c = text.charAt( cur );
96
97 switch ( c ) {
98 case('$'):
99 if ( cur+1<len ) {
100 ++cur;
101 c = text.charAt( cur );
102
103 switch ( c ) {
104 case('$'):
105 chars.append( c );
106 break;
107 case('{'):
108 if ( chars.length() > 0 ) {
109 answer.addTextExpression( chars.toString() );
110 chars.delete(0, chars.length() );
111 }
112
113 if (cur+1<len) {
114 ++cur;
115
116 while (cur<len) {
117 c = text.charAt(cur);
118 switch ( c ) {
119 case('"'):
120 expr.append( c );
121 ++cur;
122
123 DOUBLE_QUOTE:
124 while(cur<len) {
125 c = text.charAt(cur);
126
127 switch ( c ) {
128 case('//'):
129 ++cur;
130 expr.append(c);
131 break;
132 case('"'):
133 ++cur;
134 expr.append(c);
135 break DOUBLE_QUOTE;
136 default:
137 ++cur;
138 expr.append(c);
139 }
140 }
141 break;
142 case('\''):
143 expr.append( c );
144 ++cur;
145
146 SINGLE_QUOTE:
147 while(cur<len) {
148 c = text.charAt(cur);
149
150 switch ( c ) {
151 case('//'):
152 ++cur;
153 expr.append(c);
154 break;
155 case('\''):
156 ++cur;
157 expr.append(c);
158 break SINGLE_QUOTE;
159 default:
160 ++cur;
161 expr.append(c);
162 }
163 }
164 break;
165 case('}'):
166 answer.addExpression(factory.createExpression(expr.toString()));
167 expr.delete(0, expr.length());
168 ++cur;
169 continue MAIN;
170 default:
171 expr.append( c );
172 ++cur;
173 }
174 }
175 }
176 break;
177 default:
178 chars.append(c);
179 }
180 }
181 else
182 {
183 chars.append(c);
184 }
185 break;
186 default:
187 chars.append( c );
188 }
189 ++cur;
190 }
191
192 if ( chars.length() > 0 )
193 {
194 answer.addTextExpression( chars.toString() );
195 }
196
197 return answer;
198 }
199
200
201
202
203 /***
204 * @return the Expression objects that make up this
205 * composite expression
206 */
207 public List getExpressions() {
208 return expressions;
209 }
210
211 /***
212 * Sets the Expression objects that make up this
213 * composite expression
214 */
215 public void setExpressions(List expressions) {
216 this.expressions = expressions;
217 }
218
219 /***
220 * Adds a new expression to the end of the expression list
221 */
222 public void addExpression(Expression expression) {
223 expressions.add(expression);
224 }
225
226 /***
227 * A helper method to add a new constant text expression
228 */
229 public void addTextExpression(String text) {
230 addExpression(new ConstantExpression(text));
231 }
232
233
234
235
236 public String getExpressionText() {
237 StringBuffer buffer = new StringBuffer();
238 for (Iterator iter = expressions.iterator(); iter.hasNext(); ) {
239 Expression expression = (Expression) iter.next();
240 buffer.append( expression.getExpressionText() );
241 }
242 return buffer.toString();
243 }
244
245
246
247 public Object evaluate(JellyContext context) {
248 return evaluateAsString(context);
249 }
250
251
252 public String evaluateAsString(JellyContext context) {
253 StringBuffer buffer = new StringBuffer();
254 for (Iterator iter = expressions.iterator(); iter.hasNext(); ) {
255 Expression expression = (Expression) iter.next();
256 String value = expression.evaluateAsString(context);
257 if ( value != null ) {
258 buffer.append( value );
259 }
260 }
261 return buffer.toString();
262
263 }
264
265
266 public Iterator evaluateAsIterator(JellyContext context) {
267 String value = evaluateAsString(context);
268 if ( value == null ) {
269 return Collections.EMPTY_LIST.iterator();
270 }
271 else {
272 return new SingletonIterator( value );
273 }
274 }
275 }