package org.jbehave.examples.core.steps;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.jbehave.core.annotations.Alias;
import org.jbehave.core.annotations.Aliases;
import org.jbehave.core.annotations.AsParameterConverter;
import org.jbehave.core.annotations.Given;
import org.jbehave.core.annotations.Named;
import org.jbehave.core.annotations.Then;
import org.jbehave.core.annotations.When;
import org.jbehave.core.model.ExamplesTable;
import org.jbehave.core.model.OutcomesTable;
import org.jbehave.core.steps.CandidateSteps;
import org.jbehave.core.steps.InstanceStepsFactory;
import org.jbehave.core.steps.Parameters;
import org.jbehave.examples.core.CoreStory;
import org.jbehave.examples.core.model.Stock;
import org.jbehave.examples.core.model.Stock.AlertStatus;
import org.jbehave.examples.core.model.Trader;
import org.jbehave.examples.core.persistence.TraderPersister;
import org.jbehave.examples.core.service.TradingService;
import static java.util.Arrays.asList;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
/**
* POJO holding the candidate steps for the trader example.
* The {@link CandidateSteps} instance wrapping this are created via the {@link InstanceStepsFactory}
* in the {@link CoreStory}.
*/
public class TraderSteps {
private TradingService service;
private Stock stock;
private Trader trader;
private List<Trader> traders = new ArrayList<Trader>();
private List<Trader> searchedTraders;
private Date date;
private ExamplesTable ranksTable;
private String stockExchange;
private String assetClass;
private TradeType tradeType;
public TraderSteps() {
this(new TradingService());
}
public TraderSteps(TradingService service) {
this.service = service;
}
public TradingService getService() {
return this.service;
}
@Given("a date of %date")
public void aDate(Date date) {
this.date = date;
}
@When("%days days pass")
public void daysPass(int days) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.add(Calendar.DAY_OF_YEAR, days);
date = calendar.getTime();
}
@Then("the date is %date")
public void theDate(Date date) {
assertThat(date, equalTo(this.date));
}
@Given("a trader of {name|id} %trader")
public void aTrader(Trader trader) {
this.trader = trader;
}
@Given("the trader ranks: %ranksTable")
@Alias("the traders: %ranksTable")
public void theTraderRanks(ExamplesTable ranksTable) {
this.ranksTable = ranksTable;
traders.clear();
traders.addAll(toTraders(ranksTable));
}
@When("traders are subset to \"%regex\" by name")
@Alias("traders are filtered by \"%regex\"")
public void subsetTradersByName(String regex) {
searchedTraders = new ArrayList<Trader>();
for (Trader trader : traders) {
if (trader.getName().matches(regex)) {
searchedTraders.add(trader);
}
}
}
@Then("the current trader activity is: %activityTable")
public void theTradersActivityIs(ExamplesTable activityTable) {
for (int i = 0; i < activityTable.getRowCount(); i++) {
Parameters row = activityTable.withDefaults(this.ranksTable.getRowAsParameters(i)).getRowAsParameters(i);
System.out.println(row.valueAs("name", Trader.class) + " ("
+ row.valueAs("rank", String.class, "N/A") + ") has done " + row.valueAs("trades", Integer.class)
+ " trades");
}
}
@Then("the traders returned are: %tradersTable")
public void theTradersReturnedAre(ExamplesTable tradersTable) {
OutcomesTable outcomes = new OutcomesTable();
outcomes.addOutcome("traders", searchedTraders.toString(), equalTo(toTraders(tradersTable).toString()));
outcomes.addOutcome("a success", "Any Value", equalTo("Any Value"));
outcomes.verify();
}
private List<Trader> toTraders(ExamplesTable table) {
List<Trader> traders = new ArrayList<Trader>();
List<Map<String, String>> rows = table.getRows();
for (Map<String, String> row : rows) {
String name = row.get("name");
String rank = row.get("rank");
traders.add(getService().newTrader(name, rank));
}
Collections.sort(traders);
return traders;
}
@Given("the stock exchange %stockExchange")
@Alias("the stock exchange <stockExchange>")
public void theStockExchange(@Named("stockExchange") String stockExchange) {
this.stockExchange = stockExchange;
}
@Given("the asset class %assetClass")
@Alias("the asset class <assetClass>")
public void theAssetClass(@Named("assetClass") String assetClass) {
this.assetClass = assetClass;
}
@Given("a stock of symbol %symbol and a threshold of %threshold")
@Alias("a stock of <symbol> and a <threshold>")
// alias used with examples table
public void aStock(@Named("symbol") String symbol, @Named("threshold") double threshold) {
stock = getService().newStock(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",
"the stock is traded with <price>" })
// multiple aliases, one used with examples table
public void theStockIsTraded(@Named("price") double price) {
stock.tradeAt(price);
}
@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")
@Alias("the trader is alerted with <status>")
// alias used with examples table
public void theAlertStatusIs(@Named("status") String status) {
assertThat(stock.getStatus().name(), equalTo(status));
}
@Then(value = "the alert status is currently %status", priority = 1)
// prioritise over potential match with previous method
public void theAlertStatusIsCurrently(@Named("status") String status) {
assertThat(stock.getStatus().name(), equalTo(status));
}
@When("the trader sells all stocks")
public void theTraderSellsAllStocks() {
trader.sellAllStocks();
}
@Then("the trader is left with no stocks")
public void theTraderIsLeftWithNoStocks() {
assertThat(trader.getStocks().size(), equalTo(0));
}
@Given("a trade type %tradeType")
public void givenATradeType(TradeType type) {
this.tradeType = type;
}
@Then("the current trade type is %type")
public void thenTheCurrentTradeTypeIs(String type) {
assertThat(this.tradeType.name(), equalTo(type));
}
@Then("the list of trade types is %types")
public void thenTheListTradeTypesIs(List<TradeType> types) {
List<String> values = new ArrayList<String>();
for (TradeType type : TradeType.values()) {
values.add(type.name());
}
assertThat(types.toString(), equalTo(values.toString()));
}
enum TradeType {
BUY, SELL;
}
// Method used as dynamical parameter converter
@AsParameterConverter
public Trader retrieveTrader(String name) {
for (Trader trader : traders) {
if (trader.getName().equals(name)) {
return trader;
}
}
return mockTradePersister().retrieveTrader(name);
}
static TraderPersister mockTradePersister() {
return new TraderPersister(new Trader("Mauro", asList(new Stock("STK1", 10.d))));
}
}