/*
* Copyright 2004-2005 Revolution Systems Inc.
*
* 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 com.revolsys.util;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.jexl.Expression;
import org.apache.commons.jexl.ExpressionFactory;
import org.apache.commons.jexl.JexlContext;
import org.apache.log4j.Logger;
/**
* The JexlUtil is a utility class for processing strings that contain patterns
* from the Jakarta Commons Jexl library.
*
* @author Paul Austin
*/
public final class JexlUtil {
/** The default expression pattern matching expressions in the form ${el}. */
public static final String DEFAULT_EXPRESSION_PATTERN = "\\$\\{([^\\}]+)\\}";
private static final Logger LOG = Logger.getLogger(JexlUtil.class);
/**
* Add the text to the Jexl expression, wrapping the text in a '' string.
*
* @param jexlExpression The expression to add the test to.
* @param text The text to add.
*/
private static void addText(final StringBuilder jexlExpression, final String text) {
jexlExpression.append("'").append(text.replaceAll("'", "' + \"'\" + '")).append("'");
}
public static Object evaluateExpression(final JexlContext context, final Expression expression) {
try {
return expression.evaluate(context);
} catch (final Exception e) {
LOG.error(
"Unable to evaluate expression '" + expression.getExpression() + "': " + e.getMessage(), e);
return null;
}
}
/**
* Convert expressions into valid JexlExpressions, if the string does not
* contain any expressions in the form ${el} then null will be returned and
* the caller can use the raw string.
*
* @param expression The string containing expressions.
* @return The expression object for the string expression.
* @throws Exception If there was an error creating the expression.
*/
public static Expression newExpression(final String expression) throws Exception {
return newExpression(expression, DEFAULT_EXPRESSION_PATTERN);
}
/**
* <p>
* Convert expressions into valid JexlExpressions, if the string does not
* contain any expressions that match the expressionPattern then null will be
* returned and the caller can use the raw string.
* </p>
* <p>
* The expressionPattern can be used to define an alternate pattern than the
* {@link #DEFAULT_EXPRESSION_PATTERN} that defines expressions in the form
* ${el}. The pattern is defined as a Java Regular expression. The contents of
* the expression part of the pattern must be enclosed in () to define the
* group. The characters outside the first group will be removed from the
* string and the expression portion will be added to the expression.
* </p>
*
* @param expression The string containing expressions.
* @param expressionPattern The regular expression pattern used to identify
* expressions in the string. The first group in the expression will
* be used as the expression.
* @return The expression object for the string expression.
* @throws Exception If there was an error creating the expression.
*/
public static Expression newExpression(final String expression, final String expressionPattern)
throws Exception {
final String newExpression = expression.replaceAll("\n", "");
// Wrap the entires expression in '' and replace the expressions in the
// form "${expr)" to ' + expr + '
final Pattern compiledPattern = Pattern.compile(expressionPattern);
final Matcher matcher = compiledPattern.matcher(newExpression);
int lastEnd = 0;
if (matcher.find()) {
final StringBuilder jexlExpression = new StringBuilder();
do {
final int startIndex = matcher.start();
if (startIndex != lastEnd) {
final String text = newExpression.substring(lastEnd, startIndex);
addText(jexlExpression, text);
jexlExpression.append(" + ");
}
final String matchedExpression = matcher.group(1);
jexlExpression.append(matchedExpression).append(" + ");
lastEnd = matcher.end();
} while (matcher.find());
addText(jexlExpression, newExpression.substring(lastEnd));
// Remove any empty strings from the expression to improve
// performance
String expr = jexlExpression.toString();
expr = expr.replaceAll(" \\+ '' \\+ ", " + ");
expr = expr.replaceAll("^'' \\+ ", "");
expr = expr.replaceAll("\\+ ''$", "");
return ExpressionFactory.createExpression(expr);
} else {
return null;
}
}
/**
* Construct a new JexlUtil.
*/
private JexlUtil() {
}
}