MultiArgExpressionProcessor.java

  1. package org.jbehave.core.expressions;

  2. import java.util.Collections;
  3. import java.util.List;
  4. import java.util.Optional;
  5. import java.util.function.Consumer;
  6. import java.util.function.Function;
  7. import java.util.regex.Matcher;
  8. import java.util.regex.Pattern;

  9. public class MultiArgExpressionProcessor<T> implements ExpressionProcessor<T> {

  10.     private static final int ARGS_GROUP = 1;

  11.     private final Pattern pattern;
  12.     private final String expressionName;
  13.     private final int minArgNumber;
  14.     private final int maxArgNumber;
  15.     private final Function<String, ExpressionArguments> argsParser;
  16.     private final Function<List<String>, T> evaluator;

  17.     public MultiArgExpressionProcessor(String expressionName, int minArgNumber, int maxArgNumber,
  18.             Function<String, ExpressionArguments> argsParser, Function<List<String>, T> evaluator) {
  19.         this.pattern = Pattern.compile("^" + expressionName + "\\((.*)\\)$", Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
  20.         this.expressionName = expressionName;
  21.         this.minArgNumber = minArgNumber;
  22.         this.maxArgNumber = maxArgNumber;
  23.         this.argsParser = argsParser;
  24.         this.evaluator = evaluator;
  25.     }

  26.     public MultiArgExpressionProcessor(String expressionName, int minArgNumber, int maxArgNumber,
  27.             Function<List<String>, T> evaluator) {
  28.         this(expressionName, minArgNumber, maxArgNumber, ExpressionArguments::new, evaluator);
  29.     }

  30.     public MultiArgExpressionProcessor(String expressionName, int expectedArgNumber,
  31.             Function<List<String>, T> evaluator) {
  32.         this(expressionName, expectedArgNumber, expectedArgNumber, evaluator);
  33.     }

  34.     public MultiArgExpressionProcessor(String expressionName, int expectedArgNumber,
  35.             Function<String, ExpressionArguments> argsParser, Function<List<String>, T> evaluator) {
  36.         this(expressionName, expectedArgNumber, expectedArgNumber, argsParser, evaluator);
  37.     }

  38.     @Override
  39.     public Optional<T> execute(String expression) {
  40.         Matcher expressionMatcher = pattern.matcher(expression);
  41.         if (expressionMatcher.find()) {
  42.             List<String> args = parseArgs(expressionMatcher.group(ARGS_GROUP));
  43.             T expressionResult = evaluator.apply(args);
  44.             return Optional.of(expressionResult);
  45.         }
  46.         return Optional.empty();
  47.     }

  48.     private List<String> parseArgs(String argsAsString) {
  49.         if (minArgNumber == 1 && maxArgNumber == 1) {
  50.             return Collections.singletonList(argsAsString);
  51.         }
  52.         List<String> args = argsParser.apply(argsAsString).getArguments();
  53.         int argsNumber = args.size();
  54.         if (minArgNumber == maxArgNumber) {
  55.             if (argsNumber != minArgNumber) {
  56.                 throwException(argsAsString, argsNumber, error -> error.append(minArgNumber));
  57.             }
  58.         } else if (argsNumber < minArgNumber || argsNumber > maxArgNumber) {
  59.             throwException(argsAsString, argsNumber, error -> error.append("from ").append(minArgNumber).append(" to "
  60.             ).append(maxArgNumber));
  61.         }
  62.         return args;
  63.     }

  64.     private void throwException(String argsAsString, int argsNumber, Consumer<StringBuilder> expectationsAppender) {
  65.         StringBuilder errorMessageBuilder = new StringBuilder("The expected number of arguments for '")
  66.                 .append(expressionName)
  67.                 .append("' expression is ");
  68.         expectationsAppender.accept(errorMessageBuilder);
  69.         errorMessageBuilder.append(", but found ")
  70.                 .append(argsNumber)
  71.                 .append(" argument");
  72.         if (argsNumber != 1) {
  73.             errorMessageBuilder.append('s');
  74.         }
  75.         if (argsNumber > 0) {
  76.             errorMessageBuilder.append(": '").append(argsAsString).append('\'');
  77.         }
  78.         throw new IllegalArgumentException(errorMessageBuilder.toString());
  79.     }
  80. }