AbstractRegexParser.java

  1. package org.jbehave.core.parsers;

  2. import static java.util.regex.Pattern.DOTALL;
  3. import static java.util.regex.Pattern.compile;
  4. import static java.util.stream.Collectors.toList;

  5. import java.util.ArrayList;
  6. import java.util.List;
  7. import java.util.regex.Matcher;
  8. import java.util.regex.Pattern;
  9. import java.util.stream.Stream;

  10. import org.apache.commons.lang3.StringUtils;
  11. import org.jbehave.core.configuration.Keywords;
  12. import org.jbehave.core.i18n.LocalizedKeywords;
  13. import org.jbehave.core.steps.StepType;

  14. abstract class AbstractRegexParser {

  15.     protected static final String NONE = "";
  16.     private static final String CRLF = "\\r?\\n";

  17.     private final Keywords keywords;

  18.     protected AbstractRegexParser() {
  19.         this(new LocalizedKeywords());
  20.     }

  21.     protected AbstractRegexParser(Keywords keywords) {
  22.         this.keywords = keywords;
  23.     }

  24.     protected Keywords keywords() {
  25.         return keywords;
  26.     }

  27.     protected List<String> splitElements(String text, String keyword) {
  28.         List<String> elements = new ArrayList<>();
  29.         StringBuilder element = new StringBuilder();
  30.         String[] elementsAsText = text.split(keyword);
  31.         for (int i = 0; i < elementsAsText.length; i++) {
  32.             String elementAsText = elementsAsText[i];
  33.             element.append(elementAsText);
  34.             if (isLastLineNotComment(elementAsText)) {
  35.                 addNonEmptyElement(element.toString(), elements, keyword);
  36.                 element = new StringBuilder();
  37.             } else {
  38.                 if (i == elementsAsText.length - 1) {
  39.                     addNonEmptyElement(element.toString(), elements, keyword);
  40.                 } else {
  41.                     element.append(keyword);
  42.                 }
  43.             }
  44.         }
  45.         return elements;
  46.     }

  47.     private static void addNonEmptyElement(String elementToAdd, List<String> elements, String keyword) {
  48.         if (elementToAdd.trim().length() > 0) {
  49.             elements.add(keyword + "\n" + elementToAdd);
  50.         }
  51.     }

  52.     private boolean isLastLineNotComment(String elementAsText) {
  53.         String[] elementLines = elementAsText.split(CRLF, -1);
  54.         return !elementLines[elementLines.length - 1].startsWith(keywords.ignorable());
  55.     }

  56.     protected String startingWithNL(String text) {
  57.         if (!text.startsWith("\n")) { // always ensure starts with newline
  58.             return "\n" + text;
  59.         }
  60.         return text;
  61.     }

  62.     protected List<String> findSteps(String stepsAsText) {
  63.         Matcher matcher = findingSteps().matcher(stepsAsText);
  64.         List<String> steps = new ArrayList<>();
  65.         int startAt = 0;
  66.         while (matcher.find(startAt)) {
  67.             steps.add(StringUtils.substringAfter(matcher.group(1), "\n"));
  68.             startAt = matcher.start(4);
  69.         }
  70.         return steps;
  71.     }

  72.     // Regex Patterns

  73.     private Pattern findingSteps() {
  74.         String startingWords = concatenateStartingWords();
  75.         return compile(
  76.                 "((" + startingWords + ")(.*?))(\\Z|" + startingWords + "|\\n" + keywords().examplesTable() + ")",
  77.                 DOTALL);
  78.     }

  79.     protected String concatenateStartingWords() {
  80.         List<String> startingWords = Stream.concat(
  81.                 keywords().startingWords(stepType -> stepType != StepType.IGNORABLE).map(s -> s + "\\s"),
  82.                 keywords().startingWords(stepType -> stepType == StepType.IGNORABLE)
  83.         ).collect(toList());
  84.         return concatenateWithOr(CRLF, startingWords);
  85.     }

  86.     protected String concatenateWithOr(String beforeKeyword, List<String> keywords) {
  87.         StringBuilder builder = new StringBuilder(beforeKeyword).append("(?:");
  88.         for (String keyword : keywords) {
  89.             builder.append(keyword).append('|');
  90.         }
  91.         if (!keywords.isEmpty()) {
  92.             builder.deleteCharAt(builder.length() - 1); // remove last "|"
  93.         }
  94.         return builder.append(')').toString();
  95.     }
  96. }