blob: f86a890cc2ba2f55be68d65de75af2a45a14796b [file] [log] [blame]
/*
* Copyright 2002,2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.jelly.expression;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.collections.iterators.SingletonIterator;
import org.apache.commons.jelly.JellyContext;
import org.apache.commons.jelly.JellyException;
/**
* <p><code>CompositeExpression</code> is a Composite expression made up of several
* Expression objects which are concatenated into a single String.</p>
*
* @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
* @version $Revision: 1.4 $
*/
public class CompositeExpression extends ExpressionSupport {
/** The expressions */
private List expressions;
public CompositeExpression() {
this.expressions = new ArrayList();
}
public CompositeExpression(List expressions) {
this.expressions = expressions;
}
public String toString() {
return super.toString() + "[expressions=" + expressions +"]";
}
/**
* Parses the given String to be either a ConstantExpresssion, an Expression denoted as
* "${foo}" or some String with embedded expresssions such as "abc${something}def${else}xyz"
* which results in a CompositeExpression being returned.
*
* @param text is the String to parse into expressions
* @param factory is the Factory of Expression objects used to create expresssions for the contents
* of the String "foo" inside expressions such as "${foo}"
*
* @return the Expresssion for the given String.
* @throws JellyException if the text is invalid (such as missing '}' character).
* @throws JellyException if there was some problem creating the underlying Expression object
* from the ExpressionFactory
*/
public static Expression parse(String text, ExpressionFactory factory) throws JellyException {
int len = text.length();
int startIndex = text.indexOf( "${" );
if ( startIndex < 0) {
return new ConstantExpression(text);
}
int endIndex = text.indexOf( "}", startIndex+2 );
if ( endIndex < 0 ) {
throw new JellyException( "Missing '}' character at the end of expression: " + text );
}
if ( startIndex == 0 && endIndex == len - 1 ) {
return factory.createExpression(text.substring(2, endIndex));
}
CompositeExpression answer = new CompositeExpression();
int cur = 0;
char c = 0;
StringBuffer chars = new StringBuffer();
StringBuffer expr = new StringBuffer();
MAIN:
while ( cur < len ) {
c = text.charAt( cur );
switch ( c ) {
case('$'):
if ( cur+1<len ) {
++cur;
c = text.charAt( cur );
switch ( c ) {
case('$'):
chars.append( c );
break;
case('{'):
if ( chars.length() > 0 ) {
answer.addTextExpression( chars.toString() );
chars.delete(0, chars.length() );
}
if (cur+1<len) {
++cur;
while (cur<len) {
c = text.charAt(cur);
switch ( c ) {
case('"'):
expr.append( c );
++cur;
DOUBLE_QUOTE:
while(cur<len) {
c = text.charAt(cur);
switch ( c ) {
case('\\'):
++cur;
expr.append(c);
break;
case('"'):
++cur;
expr.append(c);
break DOUBLE_QUOTE;
default:
++cur;
expr.append(c);
} // switch
} // while
break;
case('\''):
expr.append( c );
++cur;
SINGLE_QUOTE:
while(cur<len) {
c = text.charAt(cur);
switch ( c ) {
case('\\'):
++cur;
expr.append(c);
break;
case('\''):
++cur;
expr.append(c);
break SINGLE_QUOTE;
default:
++cur;
expr.append(c);
} // switch
} // while
break;
case('}'):
answer.addExpression(factory.createExpression(expr.toString()));
expr.delete(0, expr.length());
++cur;
continue MAIN;
default:
expr.append( c );
++cur;
}
}
}
break;
default:
chars.append(c);
}
}
else
{
chars.append(c);
}
break;
default:
chars.append( c );
}
++cur;
}
if ( chars.length() > 0 )
{
answer.addTextExpression( chars.toString() );
}
return answer;
}
// Properties
//-------------------------------------------------------------------------
/**
* @return the Expression objects that make up this
* composite expression
*/
public List getExpressions() {
return expressions;
}
/**
* Sets the Expression objects that make up this
* composite expression
*/
public void setExpressions(List expressions) {
this.expressions = expressions;
}
/**
* Adds a new expression to the end of the expression list
*/
public void addExpression(Expression expression) {
expressions.add(expression);
}
/**
* A helper method to add a new constant text expression
*/
public void addTextExpression(String text) {
addExpression(new ConstantExpression(text));
}
// Expression interface
//-------------------------------------------------------------------------
public String getExpressionText() {
StringBuffer buffer = new StringBuffer();
for (Iterator iter = expressions.iterator(); iter.hasNext(); ) {
Expression expression = (Expression) iter.next();
buffer.append( expression.getExpressionText() );
}
return buffer.toString();
}
// inherit javadoc from interface
public Object evaluate(JellyContext context) {
return evaluateAsString(context);
}
// inherit javadoc from interface
public String evaluateAsString(JellyContext context) {
StringBuffer buffer = new StringBuffer();
for (Iterator iter = expressions.iterator(); iter.hasNext(); ) {
Expression expression = (Expression) iter.next();
String value = expression.evaluateAsString(context);
if ( value != null ) {
buffer.append( value );
}
}
return buffer.toString();
}
// inherit javadoc from interface
public Iterator evaluateAsIterator(JellyContext context) {
String value = evaluateAsString(context);
if ( value == null ) {
return Collections.EMPTY_LIST.iterator();
}
else {
return new SingletonIterator( value );
}
}
}