Index: jbehave-core/src/java/org/jbehave/scenario/steps/CandidateStep.java =================================================================== --- jbehave-core/src/java/org/jbehave/scenario/steps/CandidateStep.java (revisão 1392) +++ jbehave-core/src/java/org/jbehave/scenario/steps/CandidateStep.java (cópia de trabalho) @@ -27,259 +27,303 @@ */ public class CandidateStep { - private final String patternAsString; - private final StepType stepType; - private final Method method; - private final CandidateSteps steps; - private final ParameterConverters parameterConverters; - private final Map startingWordsByType; - private final Pattern pattern; - private final String[] groupNames; + private final String patternAsString; + private final StepType stepType; + private final Method method; + private final CandidateSteps steps; + private final ParameterConverters parameterConverters; + private final Map startingWordsByType; + private final Pattern pattern; + private final String[] groupNames; - private StepMonitor stepMonitor = new SilentStepMonitor(); - private Paranamer paranamer = new NullParanamer(); + private StepMonitor stepMonitor = new SilentStepMonitor(); + private Paranamer paranamer = new NullParanamer(); - public CandidateStep(String patternAsString, StepType stepType, Method method, CandidateSteps steps, - StepPatternBuilder patternBuilder, ParameterConverters parameterConverters, - Map startingWords) { - this.patternAsString = patternAsString; - this.stepType = stepType; - this.method = method; - this.steps = steps; - this.parameterConverters = parameterConverters; - this.startingWordsByType = startingWords; - this.pattern = patternBuilder.buildPattern(patternAsString); - this.groupNames = patternBuilder.extractGroupNames(patternAsString); - } + public CandidateStep(String patternAsString, StepType stepType, + Method method, CandidateSteps steps, + StepPatternBuilder patternBuilder, + ParameterConverters parameterConverters, + Map startingWords) { + this.patternAsString = patternAsString; + this.stepType = stepType; + this.method = method; + this.steps = steps; + this.parameterConverters = parameterConverters; + this.startingWordsByType = startingWords; + this.pattern = patternBuilder.buildPattern(patternAsString); + this.groupNames = patternBuilder.extractGroupNames(patternAsString); + } - public void useStepMonitor(StepMonitor stepMonitor) { - this.stepMonitor = stepMonitor; - } + public void useStepMonitor(StepMonitor stepMonitor) { + this.stepMonitor = stepMonitor; + } - public void useParanamer(Paranamer paranamer) { - this.paranamer = paranamer; - } + public void useParanamer(Paranamer paranamer) { + this.paranamer = paranamer; + } - public boolean matches(String stepAsString) { - try { - Matcher matcher = matcherForStep(stepAsString); - boolean matches = matcher.matches(); - stepMonitor.stepMatchesPattern(stepAsString, matches, pattern.pattern()); - return matches; - } catch (StartingWordNotFound e) { - return false; - } - } + public boolean matches(String stepAsString) { + try { + Matcher matcher = matcherForStep(stepAsString); + boolean matches = matcher.matches(); + stepMonitor.stepMatchesPattern(stepAsString, matches, pattern + .pattern()); + return matches; + } catch (StartingWordNotFound e) { + return false; + } + } - private String trimStartingWord(String word, String step) { - return step.substring(word.length() + 1); // 1 for the space after - } + private String trimStartingWord(String word, String step) { + return step.substring(word.length() + 1); // 1 for the space after + } - public Step createFrom(Map tableRow, final String stepAsString) { - Matcher matcher = matcherForStep(stepAsString); - matcher.find(); - Type[] types = method.getGenericParameterTypes(); - String[] annotationNames = annotatedParameterNames(); - String[] parameterNames = paranamer.lookupParameterNames(method, false); - Object[] args = argsForStep(tableRow, matcher, types, annotationNames, parameterNames); - return createStep(stepAsString, args); - } + public Step createFrom(Map tableRow, + final String stepAsString) { + Matcher matcher = matcherForStep(stepAsString); + matcher.find(); + Type[] types = method.getGenericParameterTypes(); + String[] annotationNames = annotatedParameterNames(); + String[] parameterNames = paranamer.lookupParameterNames(method, false); + Object[] args = argsForStep(tableRow, matcher, types, annotationNames, + parameterNames); + return createStep(stepAsString, args); + } - private Matcher matcherForStep(final String stepAsString) { - String startingWord = findStartingWord(stepAsString); - String trimmed = trimStartingWord(startingWord, stepAsString); - return pattern.matcher(trimmed); - } + private Matcher matcherForStep(final String stepAsString) { + String startingWord = findStartingWord(stepAsString); + String trimmed = trimStartingWord(startingWord, stepAsString); + return pattern.matcher(trimmed); + } - private Object[] argsForStep(Map tableRow, Matcher matcher, Type[] types, String[] annotationNames, - String[] parameterNames) { - final Object[] args = new Object[types.length]; - for (int position = 0; position < types.length; position++) { - String arg = argForPosition(position, annotationNames, parameterNames, tableRow, matcher); - args[position] = parameterConverters.convert(arg, types[position]); - } - return args; - } + private Object[] argsForStep(Map tableRow, Matcher matcher, + Type[] types, String[] annotationNames, String[] parameterNames) { + final Object[] args = new Object[types.length]; + for (int position = 0; position < types.length; position++) { + String arg = argForPosition(position, annotationNames, + parameterNames, tableRow, matcher); + args[position] = parameterConverters.convert(arg, types[position]); + } + return args; + } - private String argForPosition(int position, String[] annotationNames, String[] parameterNames, - Map tableRow, Matcher matcher) { - int annotatedNamePosition = parameterPosition(annotationNames, position); - int parameterNamePosition = parameterPosition(parameterNames, position); - String arg = null; - if (annotatedNamePosition != -1 && isGroupName(annotationNames[position])) { - String name = annotationNames[position]; - stepMonitor.usingAnnotatedNameForArg(name, position); - arg = getGroup(matcher, name); - } else if (parameterNamePosition != -1 && isGroupName(parameterNames[position])) { - String name = parameterNames[position]; - stepMonitor.usingParameterNameForArg(name, position); - arg = getGroup(matcher, name); - } else if (annotatedNamePosition != -1 && isTableFieldName(tableRow, annotationNames[position])) { - String name = annotationNames[position]; - stepMonitor.usingTableAnnotatedNameForArg(name, position); - arg = getTableValue(tableRow, name); - } else if (parameterNamePosition != -1 && isTableFieldName(tableRow, parameterNames[position])) { - String name = parameterNames[position]; - stepMonitor.usingTableParameterNameForArg(name, position); - arg = getTableValue(tableRow, name); - } else { - stepMonitor.usingNaturalOrderForArg(position); - arg = matcher.group(position + 1); - } - stepMonitor.foundArg(arg, position); - return arg; - } + private String argForPosition(int position, String[] annotationNames, + String[] parameterNames, Map tableRow, + Matcher matcher) { + int annotatedNamePosition = parameterPosition(annotationNames, position); + int parameterNamePosition = parameterPosition(parameterNames, position); + String arg = null; + if (annotatedNamePosition != -1 + && isGroupName(annotationNames[position])) { + String name = annotationNames[position]; + stepMonitor.usingAnnotatedNameForArg(name, position); + arg = getGroup(matcher, name); + if (tableRow != null && !tableRow.isEmpty()) { + arg = getTableValueFromTextualFieldName(tableRow, arg); + } + } else if (parameterNamePosition != -1 + && isGroupName(parameterNames[position])) { + String name = parameterNames[position]; + stepMonitor.usingParameterNameForArg(name, position); + arg = getGroup(matcher, name); + if (tableRow != null && !tableRow.isEmpty()) { + arg = getTableValueFromTextualFieldName(tableRow, arg); + } + } else if (annotatedNamePosition != -1 + && isTableFieldName(tableRow, annotationNames[position])) { + String name = annotationNames[position]; + stepMonitor.usingTableAnnotatedNameForArg(name, position); + arg = getTableValue(tableRow, name); + } else if (parameterNamePosition != -1 + && isTableFieldName(tableRow, parameterNames[position])) { + String name = parameterNames[position]; + stepMonitor.usingTableParameterNameForArg(name, position); + arg = getTableValue(tableRow, name); + } else { + stepMonitor.usingNaturalOrderForArg(position); + arg = matcher.group(position + 1); + if (tableRow != null && !tableRow.isEmpty()) { + arg = getTableValueFromTextualFieldName(tableRow, arg); + } + } + stepMonitor.foundArg(arg, position); + return arg; + } - private String getTableValue(Map tableRow, String name) { - return tableRow.get(name); - } + private String getTableValueFromTextualFieldName(Map tableRow, + String arg) { + String columnArgument = arg; + Pattern argPattern = Pattern.compile("[\\[\\{\\(<](\\w+)[\\]\\}\\)>]"); + Matcher m = argPattern.matcher(arg); + if (m.find()) { + String textualStepFieldName = m.group(1); + if (isTableFieldName(tableRow, textualStepFieldName)) + { + columnArgument = getTableValue(tableRow, textualStepFieldName); + } + } + return columnArgument; + } - private boolean isTableFieldName(Map tableRow, String name) { - return tableRow.get(name) != null; - } + private String getTableValue(Map tableRow, String name) { + return tableRow.get(name); + } - private String getGroup(Matcher matcher, String name) { - for (int i = 0; i < groupNames.length; i++) { - String groupName = groupNames[i]; - if (name.equals(groupName)) { - return matcher.group(i + 1); - } - } - throw new NoGroupFoundForName(name, groupNames); - } + private boolean isTableFieldName(Map tableRow, String name) { + return tableRow.get(name) != null; + } - private boolean isGroupName(String name) { - for (String groupName : groupNames) { - if (name.equals(groupName)) { - return true; - } - } - return false; - } + private String getGroup(Matcher matcher, String name) { + for (int i = 0; i < groupNames.length; i++) { + String groupName = groupNames[i]; + if (name.equals(groupName)) { + return matcher.group(i + 1); + } + } + throw new NoGroupFoundForName(name, groupNames); + } - private int parameterPosition(String[] names, int position) { - if (names.length == 0) { - return -1; - } - String name = names[position]; - for (int i = 0; i < names.length; i++) { - String annotatedName = names[i]; - if (annotatedName != null && name.equals(annotatedName)) { - return i; - } - } - return -1; - } + private boolean isGroupName(String name) { + for (String groupName : groupNames) { + if (name.equals(groupName)) { + return true; + } + } + return false; + } - /** - * Extract annotated parameter names from the @Named parameter annotations - * - * @return An array of annotated parameter names, which may include - * null values for parameters that are not annotated - */ - private String[] annotatedParameterNames() { - Annotation[][] parameterAnnotations = method.getParameterAnnotations(); - String[] names = new String[parameterAnnotations.length]; - for (int x = 0; x < parameterAnnotations.length; x++) { - Annotation[] annotations = parameterAnnotations[x]; - for (int y = 0; y < annotations.length; y++) { - Annotation annotation = annotations[y]; - if (annotation.annotationType().isAssignableFrom(Named.class)) { - names[x] = ((Named) annotation).value(); - } - } - } - return names; - } + private int parameterPosition(String[] names, int position) { + if (names.length == 0) { + return -1; + } + String name = names[position]; + for (int i = 0; i < names.length; i++) { + String annotatedName = names[i]; + if (annotatedName != null && name.equals(annotatedName)) { + return i; + } + } + return -1; + } - private String findStartingWord(final String stepAsString) throws StartingWordNotFound { - String wordForType = startingWordFor(stepType); - if (stepAsString.startsWith(wordForType)) { - return wordForType; - } - String andWord = startingWordFor(StepType.AND); - if (stepAsString.startsWith(andWord)) { - return andWord; - } - throw new StartingWordNotFound(stepAsString, stepType, startingWordsByType); - } + /** + * Extract annotated parameter names from the @Named parameter annotations + * + * @return An array of annotated parameter names, which may include + * null values for parameters that are not annotated + */ + private String[] annotatedParameterNames() { + Annotation[][] parameterAnnotations = method.getParameterAnnotations(); + String[] names = new String[parameterAnnotations.length]; + for (int x = 0; x < parameterAnnotations.length; x++) { + Annotation[] annotations = parameterAnnotations[x]; + for (int y = 0; y < annotations.length; y++) { + Annotation annotation = annotations[y]; + if (annotation.annotationType().isAssignableFrom(Named.class)) { + names[x] = ((Named) annotation).value(); + } + } + } + return names; + } - private String startingWordFor(StepType stepType) { - String startingWord = startingWordsByType.get(stepType); - if (startingWord == null) { - throw new StartingWordNotFound(stepType, startingWordsByType); - } - return startingWord; - } + private String findStartingWord(final String stepAsString) + throws StartingWordNotFound { + String wordForType = startingWordFor(stepType); + if (stepAsString.startsWith(wordForType)) { + return wordForType; + } + String andWord = startingWordFor(StepType.AND); + if (stepAsString.startsWith(andWord)) { + return andWord; + } + throw new StartingWordNotFound(stepAsString, stepType, + startingWordsByType); + } - private Step createStep(final String stepAsString, final Object[] args) { - return new Step() { - public StepResult perform() { - try { - stepMonitor.performing(stepAsString); - method.invoke(steps, args); - return StepResult.success(stepAsString); - } catch (Throwable t) { - return failureWithOriginalException(stepAsString, t); - } - } + private String startingWordFor(StepType stepType) { + String startingWord = startingWordsByType.get(stepType); + if (startingWord == null) { + throw new StartingWordNotFound(stepType, startingWordsByType); + } + return startingWord; + } - private StepResult failureWithOriginalException(final String stepAsString, Throwable t) { - if (t instanceof InvocationTargetException && t.getCause() != null) { - if (t.getCause() instanceof PendingError) { - return StepResult.pending(stepAsString, (PendingError) t.getCause()); - } else { - return StepResult.failure(stepAsString, t.getCause()); - } - } - return StepResult.failure(stepAsString, t); - } + private Step createStep(final String stepAsString, final Object[] args) { + return new Step() { + public StepResult perform() { + try { + stepMonitor.performing(stepAsString); + method.invoke(steps, args); + return StepResult.success(stepAsString); + } catch (Throwable t) { + return failureWithOriginalException(stepAsString, t); + } + } - public StepResult doNotPerform() { - return StepResult.notPerformed(stepAsString); - } + private StepResult failureWithOriginalException( + final String stepAsString, Throwable t) { + if (t instanceof InvocationTargetException + && t.getCause() != null) { + if (t.getCause() instanceof PendingError) { + return StepResult.pending(stepAsString, + (PendingError) t.getCause()); + } else { + return StepResult.failure(stepAsString, t.getCause()); + } + } + return StepResult.failure(stepAsString, t); + } - }; - } + public StepResult doNotPerform() { + return StepResult.notPerformed(stepAsString); + } - public StepType getStepType() { - return stepType; - } + }; + } - public String getPatternAsString() { - return patternAsString; - } + public StepType getStepType() { + return stepType; + } - public Pattern getPattern() { - return pattern; - } + public String getPatternAsString() { + return patternAsString; + } - @Override - public String toString() { - return stepType + " " + patternAsString; - } + public Pattern getPattern() { + return pattern; + } - @SuppressWarnings("serial") - public static class NoGroupFoundForName extends RuntimeException { + @Override + public String toString() { + return stepType + " " + patternAsString; + } - public NoGroupFoundForName(String name, String[] groupNames) { - super("No group found for name " + name + " amongst " + asList(groupNames)); - } + @SuppressWarnings("serial") + public static class NoGroupFoundForName extends RuntimeException { - } + public NoGroupFoundForName(String name, String[] groupNames) { + super("No group found for name " + name + " amongst " + + asList(groupNames)); + } - @SuppressWarnings("serial") - public static class StartingWordNotFound extends RuntimeException { + } - public StartingWordNotFound(String step, StepType stepType, Map startingWordsByType) { - super("No starting word found for step " + step + " of type " + stepType + " amongst " - + startingWordsByType); - } + @SuppressWarnings("serial") + public static class StartingWordNotFound extends RuntimeException { - public StartingWordNotFound(StepType stepType, Map startingWordsByType) { - super("No starting word found of type " + stepType + " amongst " + startingWordsByType); - } + public StartingWordNotFound(String step, StepType stepType, + Map startingWordsByType) { + super("No starting word found for step " + step + " of type " + + stepType + " amongst " + startingWordsByType); + } - } + public StartingWordNotFound(StepType stepType, + Map startingWordsByType) { + super("No starting word found of type " + stepType + " amongst " + + startingWordsByType); + } + } + } Index: examples/trader/src/main/java/org/jbehave/examples/trader/TraderSteps.java =================================================================== --- examples/trader/src/main/java/org/jbehave/examples/trader/TraderSteps.java (revisão 1392) +++ examples/trader/src/main/java/org/jbehave/examples/trader/TraderSteps.java (cópia de trabalho) @@ -32,110 +32,112 @@ public class TraderSteps extends Steps { private static final StepsConfiguration configuration = new StepsConfiguration(); - private Stock stock; - private Trader trader; - private List traders = new ArrayList(); - private List searchedTraders; + private Stock stock; + private Trader trader; + private List traders = new ArrayList(); + private List searchedTraders; - public TraderSteps() { - super(configuration); - StepMonitor monitor = new SilentStepMonitor(); - configuration.useParameterConverters(new ParameterConverters( - monitor, new TraderConverter(mockTradePersister()))); // define converter for custom type Trader - configuration.usePatternBuilder(new PrefixCapturingPatternBuilder("%")); // use '%' instead of '$' to identify parameters - configuration.useMonitor(monitor); - } + public TraderSteps() { + super(configuration); + StepMonitor monitor = new SilentStepMonitor(); + configuration.useParameterConverters(new ParameterConverters(monitor, + new TraderConverter(mockTradePersister()))); // define converter + // for custom + // type Trader + configuration.usePatternBuilder(new PrefixCapturingPatternBuilder("%")); // use + // '%' + // instead + // of + // '$' + // to + // identify + // parameters + configuration.useMonitor(monitor); + } - private TraderPersister mockTradePersister() { - return new TraderPersister(new Trader("Mauro", asList(new Stock("STK1", 10.d)))); - } + private TraderPersister mockTradePersister() { + return new TraderPersister(new Trader("Mauro", asList(new Stock("STK1", + 10.d)))); + } - @Given("a trader of name %trader") - public void aTrader(Trader trader) { - this.trader = trader; - } + @Given("a trader of name %trader") + public void aTrader(Trader trader) { + this.trader = trader; + } - @Given("the traders: %tradersTable") - public void theTraders(ExamplesTable tradersTable) { - traders.clear(); - traders.addAll(toTraders(tradersTable)); - } + @Given("the traders: %tradersTable") + public void theTraders(ExamplesTable tradersTable) { + traders.clear(); + traders.addAll(toTraders(tradersTable)); + } - @When("a wildcard search \"%regex\" is executed") - public void aWildcardSearchIsExecuted(String regex) { - searchedTraders = new ArrayList(); - for (Trader trader : traders) { - if ( trader.getName().matches(regex) ){ - searchedTraders.add(trader); - } - } - } - - @Then("the traders returned are: %tradersTable") - public void theTradersReturnedAre(ExamplesTable tradersTable) { - List expected = toTraders(tradersTable); - assertEquals(expected.toString(), searchedTraders.toString()); - } + @When("a wildcard search \"%regex\" is executed") + public void aWildcardSearchIsExecuted(String regex) { + searchedTraders = new ArrayList(); + for (Trader trader : traders) { + if (trader.getName().matches(regex)) { + searchedTraders.add(trader); + } + } + } - private List toTraders(ExamplesTable table) { - List traders = new ArrayList(); - List> rows = table.getRows(); - for (Map row : rows) { - String name = row.get("name"); - String rank = row.get("rank"); - traders.add(new Trader(name, rank)); - } - Collections.sort(traders); - return traders; - } - - @Given("a stock of and a ") - public void aStockWithTableParams(@Named("symbol") String symbol, @Named("threshold") double threshold) { - stock = new Stock(symbol, threshold); - } + @Then("the traders returned are: %tradersTable") + public void theTradersReturnedAre(ExamplesTable tradersTable) { + List expected = toTraders(tradersTable); + assertEquals(expected.toString(), searchedTraders.toString()); + } - @Given("a stock of symbol %symbol and a threshold of %threshold") - public void aStockWithNamedParams(@Named("symbol") String symbol, @Named("threshold") double threshold) { - stock = new Stock(symbol, threshold); - } + private List toTraders(ExamplesTable table) { + List traders = new ArrayList(); + List> rows = table.getRows(); + for (Map row : rows) { + String name = row.get("name"); + String rank = row.get("rank"); + traders.add(new Trader(name, rank)); + } + Collections.sort(traders); + return traders; + } - @When("the stock is traded with ") - public void theStockIsTradedAtWithTableParam(@Named("price") double price) { - stock.tradeAt(price); - } + @Given("a stock of symbol %symbol and a threshold of %threshold") + @Alias("a stock of %symbol and a %threshold") + public void aStockWithNamedParams(@Named("symbol") String symbol, + @Named("threshold") double threshold) { + stock = new Stock(symbol, threshold); + } - @When("the stock is traded at price %price") - @Aliases(values={"the stock is sold at price %price", "the stock is exchanged at price %price"}) // multiple aliases - public void theStockIsTradedAtWithNamedParam(@Named("price") double price) { - stock.tradeAt(price); - } + @When("the stock is traded at price %price") + @Aliases(values = { "the stock is traded with %price", + "the stock is sold at price %price", + "the stock is exchanged at price %price" }) + // multiple aliases + public void theStockIsTradedAtWithNamedParam(@Named("price") double price) { + stock.tradeAt(price); + } - @Then("the trader is alerted with ") - public void theAlertStatusIsWithTableParam(@Named("status") String status) { - ensureThat(stock.getStatus().name(), equalTo(status)); - } + @Given("the alert status is %status") + // shows that matching pattern need only be unique for step type + public void theAlertStatusIsReset(@Named("status") String status) { + if (AlertStatus.OFF.name().startsWith(status) && stock != null) { + stock.resetAlert(); + } + } - @Given("the alert status is %status") // shows that matching pattern need only be unique for step type - public void theAlertStatusIsReset(@Named("status") String status) { - if ( AlertStatus.OFF.name().startsWith(status) && stock != null ){ - stock.resetAlert(); - } - } + @Then("the alert status is %status") + @Aliases(values = { "the trader is alerted with %status", + "the alert status will be %status" }) + public void theAlertStatusIsWithNamedParam(@Named("status") String status) { + ensureThat(stock.getStatus().name(), equalTo(status)); + } - @Then("the alert status is %status") - @Alias("the alert status will be %status") // single alias - public void theAlertStatusIsWithNamedParam(@Named("status") String status) { - ensureThat(stock.getStatus().name(), equalTo(status)); - } + @When("the trader sells all stocks") + public void theTraderSellsAllStocks() { + trader.sellAllStocks(); + } - @When("the trader sells all stocks") - public void theTraderSellsAllStocks() { - trader.sellAllStocks(); - } + @Then("the trader is left with no stocks") + public void theTraderIsLeftWithNoStocks() { + ensureThat(trader.getStocks().size(), equalTo(0)); + } - @Then ("the trader is left with no stocks") - public void theTraderIsLeftWithNoStocks() { - ensureThat(trader.getStocks().size(), equalTo(0)); - } - } Index: examples/trader/src/main/java/org/jbehave/examples/trader/scenarios/trader_is_alerted_of_status.scenario =================================================================== --- examples/trader/src/main/java/org/jbehave/examples/trader/scenarios/trader_is_alerted_of_status.scenario (revisão 1392) +++ examples/trader/src/main/java/org/jbehave/examples/trader/scenarios/trader_is_alerted_of_status.scenario (cópia de trabalho) @@ -16,9 +16,9 @@ As a trader I want to monitor stock prices -Given a stock of and a -When the stock is traded with -Then the trader is alerted with +Given a stock of and a {threshold} +When the stock is traded with [price] +Then the trader is alerted with (status) Examples: |symbol|threshold|price|status|