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 }