- Revision
- 877
- Author
- sirenian
- Date
- 2008-07-24 07:53:56 -0500 (Thu, 24 Jul 2008)
Log Message
[Liz]: DollarStepPatternBuilder -> PrefixCapturingPatternBuilder, can configure with a prefix; also escapes all regexp characters
Modified Paths
- trunk/jbehave-core/src/behaviour/org/jbehave/scenario/steps/CandidateStepBehaviour.java
- trunk/jbehave-core/src/java/org/jbehave/scenario/steps/StepPatternBuilder.java
- trunk/jbehave-core/src/java/org/jbehave/scenario/steps/Steps.java
Added Paths
- trunk/jbehave-core/src/behaviour/org/jbehave/scenario/steps/PrefixCapturingPatternBuilderBehaviour.java
- trunk/jbehave-core/src/java/org/jbehave/scenario/steps/PrefixCapturingPatternBuilder.java
Removed Paths
Diff
Modified: trunk/jbehave-core/src/behaviour/org/jbehave/scenario/steps/CandidateStepBehaviour.java (876 => 877)
--- trunk/jbehave-core/src/behaviour/org/jbehave/scenario/steps/CandidateStepBehaviour.java 2008-07-22 17:11:43 UTC (rev 876) +++ trunk/jbehave-core/src/behaviour/org/jbehave/scenario/steps/CandidateStepBehaviour.java 2008-07-24 12:53:56 UTC (rev 877) @@ -11,7 +11,7 @@ public class CandidateStepBehaviour { - private static final StepPatternBuilder PATTERN_BUILDER = new DollarStepPatternBuilder(); + private static final StepPatternBuilder PATTERN_BUILDER = new PrefixCapturingPatternBuilder(); private static final StepMonitor MONITOR = new SilentStepMonitor(); private static final String NL = System.getProperty("line.separator");
Deleted: trunk/jbehave-core/src/behaviour/org/jbehave/scenario/steps/DollarStepPatternBuilderBehaviour.java (876 => 877)
--- trunk/jbehave-core/src/behaviour/org/jbehave/scenario/steps/DollarStepPatternBuilderBehaviour.java 2008-07-22 17:11:43 UTC (rev 876) +++ trunk/jbehave-core/src/behaviour/org/jbehave/scenario/steps/DollarStepPatternBuilderBehaviour.java 2008-07-24 12:53:56 UTC (rev 877) @@ -1,67 +0,0 @@ -package org.jbehave.scenario.steps; - -import static org.hamcrest.CoreMatchers.equalTo; -import static org.jbehave.Ensure.ensureThat; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.junit.Test; - - -public class DollarStepPatternBuilderBehaviour { - - private static final String NL = System.getProperty("line.separator"); - - @Test - public void shouldReplaceAllDollarArgumentsWithCaptures() { - StepPatternBuilder builder = new DollarStepPatternBuilder(); - ensureThat(builder.buildPattern("a house with $numberOfDoors doors and $some windows").matcher("a house with 3 doors and 4 windows").matches()); - ensureThat(builder.buildPattern("the house on $street").matcher("the house on Easy Street").matches()); - ensureThat(builder.buildPattern("$number houses").matcher("5 houses").matches()); - ensureThat(builder.buildPattern("my house").matcher("my house").matches()); - } - - @Test - public void shouldEscapeExistingBrackets() { - StepPatternBuilder matcher = new DollarStepPatternBuilder(); - ensureThat(matcher.buildPattern("I toggle the cell at ($column, $row)").matcher("I toggle the cell at (3, 4)").matches()); - } - - @Test - public void shouldNotCareSoMuchAboutWhitespace() { - StepPatternBuilder matcher = new DollarStepPatternBuilder(); - Pattern pattern = matcher.buildPattern("The grid looks like $grid"); - - // Given an argument on a new line - Matcher matched = pattern.matcher( - "The grid looks like" + NL + - ".." + NL + - ".." + NL - ); - ensureThat(matched.matches()); - ensureThat(matched.group(1), equalTo( - ".." + NL + - ".." + NL)); - - // Given an argument on a new line with extra spaces - matched = pattern.matcher( - "The grid looks like " + NL + - ".." + NL + - ".." + NL - ); - ensureThat(matched.matches()); - ensureThat(matched.group(1), equalTo( - ".." + NL + - ".." + NL)); - - // Given an argument with extra spaces - matched = pattern.matcher( - "The grid looks like ."); - ensureThat(matched.matches()); - ensureThat(matched.group(1), equalTo( - ".")); - - } - -}
Added: trunk/jbehave-core/src/behaviour/org/jbehave/scenario/steps/PrefixCapturingPatternBuilderBehaviour.java (0 => 877)
--- trunk/jbehave-core/src/behaviour/org/jbehave/scenario/steps/PrefixCapturingPatternBuilderBehaviour.java (rev 0) +++ trunk/jbehave-core/src/behaviour/org/jbehave/scenario/steps/PrefixCapturingPatternBuilderBehaviour.java 2008-07-24 12:53:56 UTC (rev 877) @@ -0,0 +1,75 @@ +package org.jbehave.scenario.steps; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.jbehave.Ensure.ensureThat; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.junit.Test; + + +public class PrefixCapturingPatternBuilderBehaviour { + + private static final String NL = System.getProperty("line.separator"); + + @Test + public void shouldReplaceAllDollarArgumentsWithCaptures() { + StepPatternBuilder builder = new PrefixCapturingPatternBuilder(); + ensureThat(builder.buildPattern("a house with $numberOfDoors doors and $some windows").matcher("a house with 3 doors and 4 windows").matches()); + ensureThat(builder.buildPattern("the house on $street").matcher("the house on Easy Street").matches()); + ensureThat(builder.buildPattern("$number houses").matcher("5 houses").matches()); + ensureThat(builder.buildPattern("my house").matcher("my house").matches()); + } + + @Test + public void shouldEscapeExistingPunctuationUsedInRegexps() { + StepPatternBuilder builder = new PrefixCapturingPatternBuilder(); + ensureThat(builder.buildPattern("I toggle the cell at ($column, $row)").matcher("I toggle the cell at (3, 4)").matches()); + ensureThat(builder.buildPattern("$name should ask, \"Why?\"").matcher("Fred should ask, \"Why?\"").matches()); + ensureThat(builder.buildPattern("$thousands x 10^3").matcher("2 x 10^3").matches()); + + Matcher aMatcherWithAllTheRegexpPunctuation = builder + .buildPattern("$regexp should not be confused by []{}?^.*()+\\") + .matcher("[]{}?^.*()+\\ should not be confused by []{}?^.*()+\\"); + ensureThat(aMatcherWithAllTheRegexpPunctuation.matches()); + ensureThat(aMatcherWithAllTheRegexpPunctuation.group(1), equalTo("[]{}?^.*()+\\")); + } + + @Test + public void shouldNotCareSoMuchAboutWhitespace() { + StepPatternBuilder matcher = new PrefixCapturingPatternBuilder(); + Pattern pattern = matcher.buildPattern("The grid looks like $grid"); + + // Given an argument on a new line + Matcher matched = pattern.matcher( + "The grid looks like" + NL + + ".." + NL + + ".." + NL + ); + ensureThat(matched.matches()); + ensureThat(matched.group(1), equalTo( + ".." + NL + + ".." + NL)); + + // Given an argument on a new line with extra spaces + matched = pattern.matcher( + "The grid looks like " + NL + + ".." + NL + + ".." + NL + ); + ensureThat(matched.matches()); + ensureThat(matched.group(1), equalTo( + ".." + NL + + ".." + NL)); + + // Given an argument with extra spaces + matched = pattern.matcher( + "The grid looks like ."); + ensureThat(matched.matches()); + ensureThat(matched.group(1), equalTo( + ".")); + + } + +}
Deleted: trunk/jbehave-core/src/java/org/jbehave/scenario/steps/DollarStepPatternBuilder.java (876 => 877)
--- trunk/jbehave-core/src/java/org/jbehave/scenario/steps/DollarStepPatternBuilder.java 2008-07-22 17:11:43 UTC (rev 876) +++ trunk/jbehave-core/src/java/org/jbehave/scenario/steps/DollarStepPatternBuilder.java 2008-07-24 12:53:56 UTC (rev 877) @@ -1,64 +0,0 @@ -package org.jbehave.scenario.steps; - -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class DollarStepPatternBuilder implements StepPatternBuilder { - - private static final String ANY_WORD_BEGINNING_WITH_DOLLAR = "(\\$\\w*)(\\W|\\Z)"; - - public Pattern buildPattern(String matchThis) { - String matchThisButLeaveBrackets = escapeBrackets(matchThis); - List<Replacement> replacements = findArgumentsToReplace(matchThisButLeaveBrackets); - String patternToMatchAgainst = replaceIdentifiedArgsWithCapture(matchThisButLeaveBrackets, replacements); - String matchThisButIgnoreWhitespace = anyWhitespaceWillDo(patternToMatchAgainst); - return Pattern.compile(matchThisButIgnoreWhitespace, Pattern.DOTALL); - } - - private String anyWhitespaceWillDo(String matchThis) { - return matchThis.replaceAll("\\s+", "\\\\s+"); - } - - private List<Replacement> findArgumentsToReplace( - String matchThisButLeaveBrackets) { - Matcher findingAllTheDollarWords = Pattern.compile(ANY_WORD_BEGINNING_WITH_DOLLAR, Pattern.DOTALL).matcher(matchThisButLeaveBrackets); - List<Replacement> replacements = new ArrayList<Replacement>(); - while(findingAllTheDollarWords.find()) { - replacements.add(new Replacement(findingAllTheDollarWords.start(), findingAllTheDollarWords.end(), findingAllTheDollarWords.group(2))); - } - return replacements; - } - - private String replaceIdentifiedArgsWithCapture(String escapedMatch, - List<Replacement> replacements) { - String matchTemp = escapedMatch; - for (int i = replacements.size(); i > 0; i--) { - String start = matchTemp.substring(0, replacements.get(i - 1).start); - String end = matchTemp.substring(replacements.get(i - 1).end); - String whitespaceIfAny = replacements.get(i - 1).whitespaceIfAny; - matchTemp = start + "(.*)" + whitespaceIfAny + end; - } - return matchTemp; - } - - private String escapeBrackets(String matchThis) { - String escapedMatch = matchThis.replace("(", "\\("); - escapedMatch = escapedMatch.replace(")", "\\)"); - return escapedMatch; - } - - private static class Replacement { - private final int start; - private final int end; - private final String whitespaceIfAny; - - public Replacement(int start, int end, String whitespaceIfAny) { - this.start = start; - this.end = end; - this.whitespaceIfAny = whitespaceIfAny; - } - } - -}
Added: trunk/jbehave-core/src/java/org/jbehave/scenario/steps/PrefixCapturingPatternBuilder.java (0 => 877)
--- trunk/jbehave-core/src/java/org/jbehave/scenario/steps/PrefixCapturingPatternBuilder.java (rev 0) +++ trunk/jbehave-core/src/java/org/jbehave/scenario/steps/PrefixCapturingPatternBuilder.java 2008-07-24 12:53:56 UTC (rev 877) @@ -0,0 +1,85 @@ +package org.jbehave.scenario.steps; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Provides a pattern which will capture arguments starting with the given + * prefix in any matching step. Default prefix is $. + * + * @author Elizabeth Keogh + */ +public class PrefixCapturingPatternBuilder implements StepPatternBuilder { + + private String anyWordBeginningWithThePrefix = "(\\$\\w*)(\\W|\\Z)"; + + /** + * Creates a pattern which captures arguments starting with $ in + * a matching step. + */ + public PrefixCapturingPatternBuilder() { + this("$"); + } + + /** + * Creates a pattern which captures arguments starting with a given + * prefix in a matching step. + */ + public PrefixCapturingPatternBuilder(String prefix) { + anyWordBeginningWithThePrefix = "(\\" + prefix + "\\w*)(\\W|\\Z)"; + } + + public Pattern buildPattern(String matchThis) { + String matchThisButLeaveBrackets = escapeRegexpPunctuation(matchThis); + List<Replacement> replacements = findArgumentsToReplace(matchThisButLeaveBrackets); + String patternToMatchAgainst = replaceIdentifiedArgsWithCapture(matchThisButLeaveBrackets, replacements); + String matchThisButIgnoreWhitespace = anyWhitespaceWillDo(patternToMatchAgainst); + return Pattern.compile(matchThisButIgnoreWhitespace, Pattern.DOTALL); + } + + private String anyWhitespaceWillDo(String matchThis) { + return matchThis.replaceAll("\\s+", "\\\\s+"); + } + + private List<Replacement> findArgumentsToReplace( + String matchThisButLeaveBrackets) { + Matcher findingAllTheDollarWords = Pattern.compile(anyWordBeginningWithThePrefix, Pattern.DOTALL).matcher(matchThisButLeaveBrackets); + List<Replacement> replacements = new ArrayList<Replacement>(); + while(findingAllTheDollarWords.find()) { + replacements.add(new Replacement(findingAllTheDollarWords.start(), findingAllTheDollarWords.end(), findingAllTheDollarWords.group(2))); + } + return replacements; + } + + private String replaceIdentifiedArgsWithCapture(String escapedMatch, + List<Replacement> replacements) { + String matchTemp = escapedMatch; + for (int i = replacements.size(); i > 0; i--) { + String start = matchTemp.substring(0, replacements.get(i - 1).start); + String end = matchTemp.substring(replacements.get(i - 1).end); + String whitespaceIfAny = replacements.get(i - 1).whitespaceIfAny; + matchTemp = start + "(.*)" + whitespaceIfAny + end; + } + return matchTemp; + } + + private String escapeRegexpPunctuation(String matchThis) { + String escapedMatch = matchThis.replaceAll("([\\[\\]\\{\\}\\?\\^\\.\\*\\(\\)\\+\\\\])", "\\\\$1"); + return escapedMatch; + } + + private static class Replacement { + private final int start; + private final int end; + private final String whitespaceIfAny; + + public Replacement(int start, int end, String whitespaceIfAny) { + this.start = start; + this.end = end; + this.whitespaceIfAny = whitespaceIfAny; + } + } + +}
Modified: trunk/jbehave-core/src/java/org/jbehave/scenario/steps/StepPatternBuilder.java (876 => 877)
--- trunk/jbehave-core/src/java/org/jbehave/scenario/steps/StepPatternBuilder.java 2008-07-22 17:11:43 UTC (rev 876) +++ trunk/jbehave-core/src/java/org/jbehave/scenario/steps/StepPatternBuilder.java 2008-07-24 12:53:56 UTC (rev 877) @@ -4,11 +4,23 @@ /** * Builds a regex pattern from a template step, as provided in the annotations, - * which will in turn match real steps conforming to the template. Eg: "When I - * give $money to $name" becomes "When I give (.*) to (.*)" + * which will in turn match real steps conforming to the template. Eg: "I + * give $money to $name" becomes "I give (.*) to (.*)", which matches + * "I give £10 to Fred". The captured arguments will be "£10" + * and "Fred".</p> + * + * <p>To create your own pattern builder, the text in the annotation should + * be converted to a pattern that matches a real step in the scenario with + * any precursor words removed. The arguments in the real step should + * be the only captured groups.</p> */ public interface StepPatternBuilder { + /** + * Builds a regexp pattern from a template step. + * @param matchThis the template step + * @return a regexp pattern which will capture the arguments associated with a matching real step + */ Pattern buildPattern(String matchThis); }
Modified: trunk/jbehave-core/src/java/org/jbehave/scenario/steps/Steps.java (876 => 877)
--- trunk/jbehave-core/src/java/org/jbehave/scenario/steps/Steps.java 2008-07-22 17:11:43 UTC (rev 876) +++ trunk/jbehave-core/src/java/org/jbehave/scenario/steps/Steps.java 2008-07-24 12:53:56 UTC (rev 877) @@ -14,7 +14,7 @@ private final String[] startingWords; public Steps() { - this(new DollarStepPatternBuilder(), new SilentStepMonitor(), "Given", "When", "Then", "And"); + this(new PrefixCapturingPatternBuilder(), new SilentStepMonitor(), "Given", "When", "Then", "And"); } public Steps(StepPatternBuilder patternBuilder, StepMonitor monitor, String... startingWords) {
To unsubscribe from this list please visit:
