package detective.core.dsl; import groovy.lang.GroovyObjectSupport; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import detective.core.Parameters; import detective.core.Scenario; import detective.core.Story; /** *<pre> http://dannorth.net/whats-in-a-story/ Title (one line describing the story) Narrative: In Order to [ ] As a [role] I want [feature] So that [benefit] Acceptance Criteria: (presented as Scenarios) Scenario 1: Title Given [context] And [some more context]... When [event] Then [outcome] And [another outcome]... Scenario 2: ... *</pre> * *<pre> *Story: Returns go to stock In order to keep track of stock As a store owner I want to add items back to stock when they're returned Scenario 1: Refunded items should be returned to stock Given a customer previously bought a black sweater from me And I currently have three black sweaters left in stock When he returns the sweater for a refund Then I should have four black sweaters in stock Scenario 2: Replaced items should be returned to stock Given that a customer buys a blue garment And I have two blue garments in stock And three black garments in stock. When he returns the garment for a replacement in black, Then I should have three blue garments in stock And two black garments in stock *</pre> * * @author James Luo * */ @SuppressWarnings({"rawtypes", "unchecked"}) public class SimpleStory extends GroovyObjectSupport implements Story{ private static final Logger logger = LoggerFactory.getLogger(SimpleStory.class); private String title; private String role; private String feature; private String benefit; private String purpose; private final List<Scenario> scenarios = new ArrayList<Scenario>(); private final List<Scenario> beforeTasks = new ArrayList<Scenario>(); private final List<Scenario> afterTasks = new ArrayList<Scenario>(); private final Parameters sharedDataMap = new ParametersImpl(); //TODO Readonly public SimpleStory(){ } @Override public String toString() { return "story \"" + title + "\" {\n As a " + role + "\n I want " + feature + "\n So that " + benefit + "\n\n " + scenarios + "\n}"; } // public Object getProperty(final String property) { // return super.getProperty(property); // } // // public void setProperty(String property, Object newValue) { // super.setProperty(property, newValue); // } // // public Object invokeMethod(String methodName, Object args) { // return super.invokeMethod(methodName, args); // } /* (non-Javadoc) * @see detective.core.AStory#getTitle() */ public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } /* (non-Javadoc) * @see detective.core.AStory#getRole() */ public String getRole() { return role; } public void setRole(String role) { this.role = role; } /* (non-Javadoc) * @see detective.core.AStory#getFeature() */ public String getFeature() { return feature; } public void setFeature(String feature) { this.feature = feature; } /* (non-Javadoc) * @see detective.core.AStory#getBenefit() */ public String getBenefit() { return benefit; } public void setBenefit(String benefit) { this.benefit = benefit; } /* (non-Javadoc) * @see detective.core.AStory#getScenarios() */ public List<Scenario> getScenarios() { return scenarios; } public String getPurpose() { return purpose; } public void setPurpose(String purpose) { this.purpose = purpose; } public Parameters getSharedDataMap() { return sharedDataMap; } public void putSharedData(String key, Object value) { if (! sharedDataMap.containsKey(key)){ logger.info("A new shared data [" + key + "] created for story [" + title + "]"); if (value == null) value = new SharedVariableImpl(this, key); sharedDataMap.put(key, value); }else{ Object oldValue = sharedDataMap.getUnwrappered(key); try { if (oldValue instanceof SharedVariable) sharedDataMap.put(key, value); else //throw new DslException("Shared data [" + key + "] can only setup once in story [" + title + "]"); logger.info("As shared data [" + key + "] can only setup once in story [" + title + "], your value ignored"); } catch (Exception e) { throw new DslException(e.getMessage() + " current story [" + title + "]", e); } } } public List<Scenario> getBeforeTasks() { return ImmutableList.copyOf(this.beforeTasks); } public List<Scenario> getAfterTasks() { return ImmutableList.copyOf(this.afterTasks); } @Override public void setGlobalParameters(Parameters parameters) { this.sharedDataMap.setParent(parameters); } }