OgnlExpressionParser now supports OGNL collection construction syntax (SWF-274).

This commit is contained in:
Erwin Vervaet
2007-03-28 19:13:19 +00:00
parent cfa0b10806
commit c8af02186c
5 changed files with 147 additions and 17 deletions

View File

@@ -120,7 +120,7 @@ public abstract class AbstractExpressionParser implements ExpressionParser {
* in "${...}" markers. For instance: "foo${expr0}bar${expr1}". The static
* pieces of text will also be returned as Expressions that just return that
* static piece of text. As a result, evaluating all returned expressions
* and concating the results produces the complete evaluated string.
* and concatenating the results produces the complete evaluated string.
* @param expressionString the expression string
* @return the parsed expressions
* @throws ParserException when the expressions cannot be parsed
@@ -137,8 +137,18 @@ public abstract class AbstractExpressionParser implements ExpressionParser {
expressions.add(new StaticExpression(expressionString.substring(startIdx, prefixIndex)));
startIdx = prefixIndex;
}
int suffixIndex = expressionString.indexOf(getExpressionSuffix(), prefixIndex);
if (suffixIndex == -1) {
int nextPrefixIndex = expressionString.indexOf(getExpressionPrefix(),
prefixIndex + getExpressionPrefix().length());
int suffixIndex;
if (nextPrefixIndex == -1) {
// this is the last expression in the expression string
suffixIndex = expressionString.lastIndexOf(getExpressionSuffix());
}
else {
// another expression exists after this one in the expression string
suffixIndex = expressionString.lastIndexOf(getExpressionSuffix(), nextPrefixIndex);
}
if (suffixIndex < (prefixIndex + getExpressionPrefix().length())) {
throw new ParserException(expressionString, "No ending suffix '" + getExpressionSuffix()
+ "' for expression starting at character " + prefixIndex + ": "
+ expressionString.substring(prefixIndex), null);

View File

@@ -15,12 +15,14 @@
*/
package org.springframework.binding.method;
import java.util.LinkedList;
import java.util.List;
import org.springframework.binding.convert.ConversionContext;
import org.springframework.binding.convert.ConversionException;
import org.springframework.binding.convert.ConversionService;
import org.springframework.binding.convert.support.ConversionServiceAwareConverter;
import org.springframework.binding.expression.Expression;
import org.springframework.util.StringUtils;
/**
* Converter that takes an encoded string representation and produces a
@@ -69,27 +71,30 @@ public class TextToMethodSignature extends ConversionServiceAwareConverter {
}
protected Object doConvert(Object source, Class targetClass, ConversionContext context) throws Exception {
String encodedMethodKey = (String)source;
encodedMethodKey = encodedMethodKey.trim();
int openParan = encodedMethodKey.indexOf('(');
String encodedMethodSignature = (String)source;
encodedMethodSignature = encodedMethodSignature.trim();
int openParan = encodedMethodSignature.indexOf('(');
if (openParan == -1) {
return new MethodSignature(encodedMethodKey);
// form "foo"
return new MethodSignature(encodedMethodSignature);
}
else {
String methodName = encodedMethodKey.substring(0, openParan);
int closeParan = encodedMethodKey.lastIndexOf(')');
if (closeParan == -1) {
throw new ConversionException(encodedMethodKey, MethodSignature.class,
// form "foo(...)"
String methodName = encodedMethodSignature.substring(0, openParan);
int closeParan = encodedMethodSignature.lastIndexOf(')');
if (closeParan != (encodedMethodSignature.length() - 1)) {
throw new ConversionException(encodedMethodSignature, MethodSignature.class,
"Syntax error: No close parenthesis specified for method parameter list", null);
}
String delimParamList = encodedMethodKey.substring(openParan + 1, closeParan);
String[] paramArray = StringUtils.commaDelimitedListToStringArray(delimParamList);
String delimitedParams = encodedMethodSignature.substring(openParan + 1, closeParan);
String[] paramArray = splitParameters(encodedMethodSignature, delimitedParams);
Parameters params = new Parameters(paramArray.length);
for (int i = 0; i < paramArray.length; i++) {
// param could be of the form "type name", "name", "type ${name}" or "${name}"
String param = paramArray[i].trim();
int space = param.indexOf(' ');
if (space == -1 || space > param.indexOf('$')) {
int expr = param.indexOf('{');
if (space == -1 || (expr != -1 && space > expr)) {
// "name" or "${name}"
params.add(new Parameter(null, parseExpression(param)));
}
@@ -103,4 +108,41 @@ public class TextToMethodSignature extends ConversionServiceAwareConverter {
return new MethodSignature(methodName, params);
}
}
/**
* Split given parameter string into individual parameter definitions.
*/
private String[] splitParameters(String encodedMethodSignature, String parameters) {
List res = new LinkedList();
int paramStart = 0;
int blockNestingCount = 0;
for (int i = 0; i < parameters.length(); i++) {
switch (parameters.charAt(i)) {
case '{':
blockNestingCount++;
break;
case '}':
blockNestingCount--;
break;
case ',':
if (blockNestingCount == 0) {
// only take comma delimiter into account when not inside
// a block
res.add(parameters.substring(paramStart, i));
paramStart = i + 1;
}
break;
}
}
if (blockNestingCount != 0) {
throw new ConversionException(encodedMethodSignature, MethodSignature.class,
"Syntax error: Curly braces do not match", null);
}
if (paramStart < parameters.length()) {
res.add(parameters.substring(paramStart));
}
return (String[])res.toArray(new String[res.size()]);
}
}