MultiArgExpressionProcessor.java
package org.jbehave.core.expressions;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MultiArgExpressionProcessor<T> implements ExpressionProcessor<T> {
private static final int ARGS_GROUP = 1;
private final Pattern pattern;
private final String expressionName;
private final int minArgNumber;
private final int maxArgNumber;
private final Function<String, ExpressionArguments> argsParser;
private final Function<List<String>, T> evaluator;
public MultiArgExpressionProcessor(String expressionName, int minArgNumber, int maxArgNumber,
Function<String, ExpressionArguments> argsParser, Function<List<String>, T> evaluator) {
this.pattern = Pattern.compile("^" + expressionName + "\\((.*)\\)$", Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
this.expressionName = expressionName;
this.minArgNumber = minArgNumber;
this.maxArgNumber = maxArgNumber;
this.argsParser = argsParser;
this.evaluator = evaluator;
}
public MultiArgExpressionProcessor(String expressionName, int minArgNumber, int maxArgNumber,
Function<List<String>, T> evaluator) {
this(expressionName, minArgNumber, maxArgNumber, ExpressionArguments::new, evaluator);
}
public MultiArgExpressionProcessor(String expressionName, int expectedArgNumber,
Function<List<String>, T> evaluator) {
this(expressionName, expectedArgNumber, expectedArgNumber, evaluator);
}
public MultiArgExpressionProcessor(String expressionName, int expectedArgNumber,
Function<String, ExpressionArguments> argsParser, Function<List<String>, T> evaluator) {
this(expressionName, expectedArgNumber, expectedArgNumber, argsParser, evaluator);
}
@Override
public Optional<T> execute(String expression) {
Matcher expressionMatcher = pattern.matcher(expression);
if (expressionMatcher.find()) {
List<String> args = parseArgs(expressionMatcher.group(ARGS_GROUP));
T expressionResult = evaluator.apply(args);
return Optional.of(expressionResult);
}
return Optional.empty();
}
private List<String> parseArgs(String argsAsString) {
if (minArgNumber == 1 && maxArgNumber == 1) {
return Collections.singletonList(argsAsString);
}
List<String> args = argsParser.apply(argsAsString).getArguments();
int argsNumber = args.size();
if (minArgNumber == maxArgNumber) {
if (argsNumber != minArgNumber) {
throwException(argsAsString, argsNumber, error -> error.append(minArgNumber));
}
} else if (argsNumber < minArgNumber || argsNumber > maxArgNumber) {
throwException(argsAsString, argsNumber, error -> error.append("from ").append(minArgNumber).append(" to "
).append(maxArgNumber));
}
return args;
}
private void throwException(String argsAsString, int argsNumber, Consumer<StringBuilder> expectationsAppender) {
StringBuilder errorMessageBuilder = new StringBuilder("The expected number of arguments for '")
.append(expressionName)
.append("' expression is ");
expectationsAppender.accept(errorMessageBuilder);
errorMessageBuilder.append(", but found ")
.append(argsNumber)
.append(" argument");
if (argsNumber != 1) {
errorMessageBuilder.append('s');
}
if (argsNumber > 0) {
errorMessageBuilder.append(": '").append(argsAsString).append('\'');
}
throw new IllegalArgumentException(errorMessageBuilder.toString());
}
}