AbstractRegexParser.java
package org.jbehave.core.parsers;
import static java.util.regex.Pattern.DOTALL;
import static java.util.regex.Pattern.compile;
import static java.util.stream.Collectors.toList;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;
import org.apache.commons.lang3.StringUtils;
import org.jbehave.core.configuration.Keywords;
import org.jbehave.core.i18n.LocalizedKeywords;
import org.jbehave.core.steps.StepType;
abstract class AbstractRegexParser {
protected static final String NONE = "";
private static final String CRLF = "\\r?\\n";
private final Keywords keywords;
protected AbstractRegexParser() {
this(new LocalizedKeywords());
}
protected AbstractRegexParser(Keywords keywords) {
this.keywords = keywords;
}
protected Keywords keywords() {
return keywords;
}
protected List<String> splitElements(String text, String keyword) {
List<String> elements = new ArrayList<>();
StringBuilder element = new StringBuilder();
String[] elementsAsText = text.split(keyword);
for (int i = 0; i < elementsAsText.length; i++) {
String elementAsText = elementsAsText[i];
element.append(elementAsText);
if (isLastLineNotComment(elementAsText)) {
addNonEmptyElement(element.toString(), elements, keyword);
element = new StringBuilder();
} else {
if (i == elementsAsText.length - 1) {
addNonEmptyElement(element.toString(), elements, keyword);
} else {
element.append(keyword);
}
}
}
return elements;
}
private static void addNonEmptyElement(String elementToAdd, List<String> elements, String keyword) {
if (elementToAdd.trim().length() > 0) {
elements.add(keyword + "\n" + elementToAdd);
}
}
private boolean isLastLineNotComment(String elementAsText) {
String[] elementLines = elementAsText.split(CRLF, -1);
return !elementLines[elementLines.length - 1].startsWith(keywords.ignorable());
}
protected String startingWithNL(String text) {
if (!text.startsWith("\n")) { // always ensure starts with newline
return "\n" + text;
}
return text;
}
protected List<String> findSteps(String stepsAsText) {
Matcher matcher = findingSteps().matcher(stepsAsText);
List<String> steps = new ArrayList<>();
int startAt = 0;
while (matcher.find(startAt)) {
steps.add(StringUtils.substringAfter(matcher.group(1), "\n"));
startAt = matcher.start(4);
}
return steps;
}
// Regex Patterns
private Pattern findingSteps() {
String startingWords = concatenateStartingWords();
return compile(
"((" + startingWords + ")(.*?))(\\Z|" + startingWords + "|\\n" + keywords().examplesTable() + ")",
DOTALL);
}
protected String concatenateStartingWords() {
List<String> startingWords = Stream.concat(
keywords().startingWords(stepType -> stepType != StepType.IGNORABLE).map(s -> s + "\\s"),
keywords().startingWords(stepType -> stepType == StepType.IGNORABLE)
).collect(toList());
return concatenateWithOr(CRLF, startingWords);
}
protected String concatenateWithOr(String beforeKeyword, List<String> keywords) {
StringBuilder builder = new StringBuilder(beforeKeyword).append("(?:");
for (String keyword : keywords) {
builder.append(keyword).append('|');
}
if (!keywords.isEmpty()) {
builder.deleteCharAt(builder.length() - 1); // remove last "|"
}
return builder.append(')').toString();
}
}