org.springframework.batch.core.jsr.configuration.support.JsrExpressionParser Maven / Gradle / Ivy
/*
* Copyright 2013 the original author or authors.
*
* 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
*
* https://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.springframework.batch.core.jsr.configuration.support;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.springframework.beans.factory.config.BeanExpressionContext;
import org.springframework.beans.factory.config.BeanExpressionResolver;
import org.springframework.util.StringUtils;
/**
*
* Support class for parsing JSR-352 expressions. The JSR-352 expression syntax, for
* example conditional/elvis statements need to be transformed a bit to be valid SPeL expressions.
*
*
* @author Chris Schaefer
* @since 3.0
*/
public class JsrExpressionParser {
private static final String QUOTE = "'";
private static final String NULL = "null";
private static final String ELVIS_RHS = ":";
private static final String ELVIS_LHS = "\\?";
private static final String ELVIS_OPERATOR = "?:";
private static final String EXPRESSION_SUFFIX = "}";
private static final String EXPRESSION_PREFIX = "#{";
private static final String DEFAULT_VALUE_SEPARATOR = ";";
private static final Pattern CONDITIONAL_EXPRESSION = Pattern.compile("(((\\bnull\\b)|(#\\{\\w))[^;]+)");
private BeanExpressionContext beanExpressionContext;
private BeanExpressionResolver beanExpressionResolver;
/**
*
* Creates a new instance of this expression parser without and expression resolver. Creating
* an instance via this constructor will still parse expressions but no resolution of operators
* will occur as its expected the caller will.
*
*/
public JsrExpressionParser() { }
/**
*
* Creates a new instances of this expression parser with the provided expression resolver and context to evaluate
* against.
*
*
* @param beanExpressionResolver the expression resolver to use when resolving expressions
* @param beanExpressionContext the expression context to resolve expressions against
*/
public JsrExpressionParser(BeanExpressionResolver beanExpressionResolver, BeanExpressionContext beanExpressionContext) {
this.beanExpressionContext = beanExpressionContext;
this.beanExpressionResolver = beanExpressionResolver;
}
/**
*
* Parses the provided expression, applying any transformations needed to evaluate as a SPeL expression.
*
*
* @param expression the expression to parse and transform
* @return a JSR-352 transformed expression that can be evaluated by a SPeL parser
*/
public String parseExpression(String expression) {
String expressionToParse = expression;
if (StringUtils.countOccurrencesOf(expressionToParse, ELVIS_OPERATOR) > 0) {
expressionToParse = parseConditionalExpressions(expressionToParse);
}
return evaluateExpression(expressionToParse);
}
private String parseConditionalExpressions(String expression) {
String expressionToParse = expression;
Matcher conditionalExpressionMatcher = CONDITIONAL_EXPRESSION.matcher(expressionToParse);
while (conditionalExpressionMatcher.find()) {
String conditionalExpression = conditionalExpressionMatcher.group(1);
String value = conditionalExpression.split(ELVIS_LHS)[0];
String defaultValue = conditionalExpression.split(ELVIS_RHS)[1];
StringBuilder parsedExpression = new StringBuilder();
if(beanExpressionResolver != null) {
parsedExpression.append(EXPRESSION_PREFIX)
.append(evaluateExpression(value))
.append(ELVIS_OPERATOR)
.append(QUOTE)
.append(evaluateExpression(defaultValue))
.append(QUOTE)
.append(EXPRESSION_SUFFIX);
} else {
if(NULL.equals(value)) {
parsedExpression.append(defaultValue);
} else {
parsedExpression.append(value);
}
}
expressionToParse = expressionToParse.replace(conditionalExpression, parsedExpression);
}
return expressionToParse.replace(DEFAULT_VALUE_SEPARATOR, "");
}
private String evaluateExpression(String expression) {
if(beanExpressionResolver != null) {
return (String) beanExpressionResolver.evaluate(expression, beanExpressionContext);
}
return expression;
}
}