View Javadoc

1   /*
2    * Copyright 2002,2004 The Apache Software Foundation.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
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                                                     } // switch
140                                                 } // while
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                                                     } // switch
163                                                 } // while
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     // Properties
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     // Expression interface
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     // inherit javadoc from interface
247     public Object evaluate(JellyContext context) {
248         return evaluateAsString(context);
249     }
250 
251     // inherit javadoc from interface
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     // inherit javadoc from interface
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 }