ExpressionResolver.java
- package org.jbehave.core.expressions;
- import java.util.Arrays;
- import java.util.Iterator;
- import java.util.List;
- import java.util.Optional;
- import java.util.Set;
- import java.util.regex.Matcher;
- import java.util.regex.Pattern;
- public class ExpressionResolver {
- private static final Pattern GREEDY_EXPRESSION_PATTERN = Pattern.compile("#\\{((?:(?!#\\{|\\$\\{).)*)}",
- Pattern.DOTALL);
- private static final Pattern RELUCTANT_EXPRESSION_PATTERN = Pattern.compile(
- "#\\{((?:(?![#{])[^)](?![()]))*?|(?:(?!#\\{|\\$\\{).)*?\\)|(?:(?!#\\{|\\$\\{).)*?)}",
- Pattern.DOTALL);
- private static final List<Pattern> PATTERNS = Arrays.asList(RELUCTANT_EXPRESSION_PATTERN,
- GREEDY_EXPRESSION_PATTERN);
- private static final String REPLACEMENT_PATTERN = "\\#\\{%s\\}";
- private final Set<ExpressionProcessor<?>> expressionProcessors;
- private final ExpressionResolverMonitor expressionResolverMonitor;
- public ExpressionResolver(Set<ExpressionProcessor<?>> expressionProcessors,
- ExpressionResolverMonitor expressionResolverMonitor) {
- this.expressionProcessors = expressionProcessors;
- this.expressionResolverMonitor = expressionResolverMonitor;
- }
- /**
- * Evaluates expressions including nested ones.
- * <br>
- * Syntax:
- * <br>
- * <code>
- * #{expression(arguments...)}
- * #{expression(arguments..., #{expression(arguments...)})}
- * #{expression(arguments..., #{expression})}
- * </code>
- * <br>
- * Example:
- * <br>
- * <code>
- * #{shiftDate("1942-12-02T01:23:40+04:00", "yyyy-MM-dd'T'HH:mm:ssz", "P43Y4M3W3D")}
- * <br>
- * #{encodeToBase64(#{fromEpochSecond(-523641111)})}
- * </code>
- *
- * @param stringWithExpressions the string with expressions to evaluate
- * @return the resulting string with expression placeholders replaced with expressions evaluation results
- */
- public Object resolveExpressions(boolean dryRun, String stringWithExpressions) {
- if (dryRun) {
- return stringWithExpressions;
- }
- try {
- return resolveExpressions(stringWithExpressions, PATTERNS.iterator());
- } catch (RuntimeException e) {
- expressionResolverMonitor.onExpressionProcessingError(stringWithExpressions, e);
- throw e;
- }
- }
- private Object resolveExpressions(String value, Iterator<Pattern> expressionPatterns) {
- String processedValue = value;
- Matcher expressionMatcher = expressionPatterns.next().matcher(processedValue);
- boolean expressionFound = false;
- while (expressionMatcher.find()) {
- expressionFound = true;
- String expression = expressionMatcher.group(1);
- Object expressionResult = apply(expression);
- if (!(expressionResult instanceof String) && ("#{" + expression + "}").equals(processedValue)) {
- return expressionResult;
- }
- if (!expressionResult.equals(expression)) {
- String regex = String.format(REPLACEMENT_PATTERN, Pattern.quote(expression));
- processedValue = processedValue.replaceFirst(regex,
- Matcher.quoteReplacement(String.valueOf(expressionResult)));
- expressionFound = false;
- expressionMatcher.reset(processedValue);
- }
- }
- if (expressionFound && expressionPatterns.hasNext()) {
- return resolveExpressions(processedValue, expressionPatterns);
- }
- return processedValue;
- }
- private Object apply(String expression) {
- for (ExpressionProcessor<?> processor : expressionProcessors) {
- Optional<?> optional = processor.execute(expression);
- if (optional.isPresent()) {
- return optional.get();
- }
- }
- return expression;
- }
- }