- package org.jbehave.core.parsers.gherkin;
- import static java.util.regex.Pattern.DOTALL;
- import static java.util.regex.Pattern.compile;
- import java.util.List;
- import java.util.regex.Matcher;
- import org.jbehave.core.i18n.LocalizedKeywords;
- import org.jbehave.core.parsers.RegexStoryParser;
- import org.jbehave.core.parsers.StoryParser;
- import org.jbehave.core.parsers.StoryTransformer;
- import org.jbehave.core.parsers.TransformingStoryParser;
- import gherkin.formatter.Formatter;
- import gherkin.formatter.model.Background;
- import gherkin.formatter.model.Examples;
- import gherkin.formatter.model.Feature;
- import gherkin.formatter.model.Row;
- import gherkin.formatter.model.Scenario;
- import gherkin.formatter.model.ScenarioOutline;
- import gherkin.formatter.model.Step;
- import gherkin.formatter.model.Tag;
- import gherkin.parser.Parser;
- public class GherkinStoryParser extends TransformingStoryParser {
- public GherkinStoryParser() {
- this(new RegexStoryParser());
- }
- public GherkinStoryParser(StoryParser delegate) {
- super(delegate, new GherkinTransformer());
- }
- public static class GherkinTransformer implements StoryTransformer {
- private LocalizedKeywords keywords;
- public GherkinTransformer() {
- this(new LocalizedKeywords());
- }
- public GherkinTransformer(LocalizedKeywords keywords) {
- this.keywords = keywords;
- }
- @Override
- public String transform(String storyAsText) {
- final StringBuffer out = new StringBuffer();
- Formatter formatter = new Formatter() {
- @Override
- public void uri(String uri) {
- out.append(uri).append("\n");
- }
- @Override
- public void feature(Feature feature) {
- out.append(feature.getName()).append("\n\n");
- writeNarrative(feature.getDescription());
- writeMeta(feature.getTags());
- }
- private void writeMeta(List<Tag> tags) {
- if (tags.isEmpty()) {
- return;
- }
- out.append(keywords.meta()).append(" ");
- for (Tag tag : tags) {
- out.append(tag.getName()).append(" ");
- }
- out.append("\n");
- }
- private void writeNarrative(String description) {
- boolean matches = false;
- Matcher findingNarrative = compile(".*" + keywords.narrative() + "(.*?)", DOTALL).matcher(
- description);
- if (findingNarrative.matches()) {
- String narrative = findingNarrative.group(1).trim();
- matches = writeNarrativeWithDefaultSyntax(out, narrative);
- if (!matches) {
- matches = writeNarrativeWithAlternativeSyntax(out, narrative);
- }
- }
- if (!matches) {
- // if narrative format does not match, write description as part of story description
- out.append(description);
- }
- }
- @SuppressWarnings("checkstyle:LocalVariableName")
- private boolean writeNarrativeWithDefaultSyntax(final StringBuffer out, String narrative) {
- boolean matches = false;
- Matcher findingElements = compile(
- ".*" + keywords.inOrderTo() + "(.*)\\s*" + keywords.asA() + "(.*)\\s*" + keywords.iWantTo()
- + "(.*)", DOTALL).matcher(narrative);
- if (findingElements.matches()) {
- String inOrderTo = findingElements.group(1).trim();
- String asA = findingElements.group(2).trim();
- String iWantTo = findingElements.group(3).trim();
- out.append(keywords.narrative()).append("\n");
- out.append(keywords.inOrderTo()).append(" ").append(inOrderTo).append("\n");
- out.append(keywords.asA()).append(" ").append(asA).append("\n");
- out.append(keywords.iWantTo()).append(" ").append(iWantTo).append("\n\n");
- matches = true;
- }
- return matches;
- }
- @SuppressWarnings("checkstyle:LocalVariableName")
- private boolean writeNarrativeWithAlternativeSyntax(final StringBuffer out, String narrative) {
- boolean matches = false;
- Matcher findingElements = compile(
- ".*" + keywords.asA() + "(.*)\\s*" + keywords.iWantTo() + "(.*)\\s*" + keywords.soThat()
- + "(.*)", DOTALL).matcher(narrative);
- if (findingElements.matches()) {
- String asA = findingElements.group(1).trim();
- String iWantTo = findingElements.group(2).trim();
- String soThat = findingElements.group(3).trim();
- out.append(keywords.narrative()).append("\n")
- .append(keywords.asA()).append(" ").append(asA).append("\n")
- .append(keywords.iWantTo()).append(" ").append(iWantTo).append("\n\n")
- .append(keywords.soThat()).append(" ").append(soThat).append("\n");
- matches = true;
- }
- return matches;
- }
- @Override
- public void background(Background background) {
- out.append(keywords.lifecycle())
- .append(background.getName())
- .append("\n")
- .append(keywords.before())
- .append("\n");
- }
- @Override
- public void scenario(Scenario scenario) {
- out.append("\n")
- .append(keywords.scenario())
- .append(scenario.getName())
- .append("\n\n");
- writeMeta(scenario.getTags());
- }
- @Override
- public void scenarioOutline(ScenarioOutline scenarioOutline) {
- out.append("\n")
- .append(keywords.scenario())
- .append(scenarioOutline.getName())
- .append("\n\n");
- writeMeta(scenarioOutline.getTags());
- }
- @Override
- public void examples(Examples examples) {
- out.append("\n")
- .append(keywords.examplesTable())
- .append(examples.getName())
- .append("\n");
- writeRows(examples.getRows());
- }
- @Override
- public void step(Step step) {
- out.append(step.getKeyword())
- .append(step.getName())
- .append("\n");
- writeRows(step.getRows());
- }
- @Override
- public void eof() {
- }
- @Override
- public void syntaxError(String state, String event,
- List<String> legalEvents, String uri, Integer line) {
- }
- @Override
- public void done() {
- }
- @Override
- public void close() {
- }
- private void writeRows(List<? extends Row> rows) {
- if (rows != null && rows.size() > 0) {
- for (Row row : rows) {
- out.append("|");
- for (String c : row.getCells()) {
- out.append(c).append("|");
- }
- out.append("\n");
- }
- }
- }
- };
- new Parser(formatter).parse(storyAsText, "", 0);
- return out.toString();
- }
- }
- }