/*****************************************************************************
* Copyright (c) 2013 Obeo.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Obeo - initial API and implementation
*****************************************************************************/
package fr.obeo.intent.specification.parser;
import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import com.google.common.collect.Iterators;
import com.google.common.collect.Lists;
import com.google.common.collect.UnmodifiableIterator;
import fr.obeo.intent.specification.Action;
import fr.obeo.intent.specification.AutomationLayer;
import fr.obeo.intent.specification.Behaviour;
import fr.obeo.intent.specification.Benefit;
import fr.obeo.intent.specification.Capability;
import fr.obeo.intent.specification.Context;
import fr.obeo.intent.specification.Feature;
import fr.obeo.intent.specification.NamedElement;
import fr.obeo.intent.specification.Parameter;
import fr.obeo.intent.specification.Role;
import fr.obeo.intent.specification.Scenario;
import fr.obeo.intent.specification.ScenarioElement;
import fr.obeo.intent.specification.Specification;
import fr.obeo.intent.specification.SpecificationFactory;
import fr.obeo.intent.specification.Story;
import fr.obeo.intent.specification.TestGenerationNote;
import fr.obeo.intent.specification.TestType;
import fr.obeo.intent.specification.Value;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.common.CommonPlugin;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.xmi.impl.XMLResourceFactoryImpl;
import org.eclipse.mylyn.docs.intent.collab.common.query.ModelingUnitQuery;
import org.eclipse.mylyn.docs.intent.collab.handlers.adapters.RepositoryAdapter;
import org.eclipse.mylyn.docs.intent.core.document.IntentSection;
import org.eclipse.mylyn.docs.intent.core.modelingunit.ExternalContentReference;
import org.eclipse.mylyn.docs.intent.core.modelingunit.ModelingUnit;
import org.eclipse.mylyn.docs.intent.core.modelingunit.ModelingUnitFactory;
import org.eclipse.mylyn.docs.intent.external.parser.contribution.ExternalParserCompletionProposal;
import org.eclipse.mylyn.docs.intent.external.parser.contribution.IExternalParser;
/**
* This parser is able to parse the specification syntax and create the
* corresponding specification model.
*
* @author <a href="mailto:melanie.bats@obeo.fr">Melanie Bats</a>
*/
public class SpecificationParser implements IExternalParser {
private static final String VARIABLE = "$";
private static final String AROBASE = "@";
/**
* Comma.
*/
private static final String COMMA = ",";
/**
* Closed bracket.
*/
private static final String CLOSE_BRACKET = "]";
/**
* Opened bracket.
*/
private static final String OPEN_BRACKET = "[";
/**
* Colon.
*/
private static final String COLON = ":";
/**
* Specification factory.
*/
private SpecificationFactory specificationFactory = SpecificationFactory.eINSTANCE;
/**
* Specification.
*/
private Specification specification;
/**
* Automation layer.
*/
private AutomationLayer automationLayer;
/**
* List of parsed elements.
*/
private List<ParsedElement> parsedElements = Lists.newArrayList();
/**
* Resource set.
*/
private ResourceSet resourceSet;
/**
* Specification resource.
*/
private Resource resource;
/**
* Specification parser keywords.
*/
private enum SpecificationKeyword {
FEATURE("Feature"), STORY("Story"), AS("As"), I_WANT("I want"), SO_THAT(
"So that"), SCENARIO("Scenario"), GIVEN("Given"), WHEN("When"), THEN(
"Then");
/**
* Value.
*/
protected String value;
/**
* Default constructor.
*
* @param value
* Value
*/
private SpecificationKeyword(String value) {
this.value = value;
}
}
/**
* Default constructor.
*/
public SpecificationParser() {
resourceSet = new ResourceSetImpl();
init();
}
@Override
public void parse(IntentSection intentSection, String descriptionUnitToParse) {
// Only parse sections with a title
if (intentSection.getTitle() != null) {
// Get valid elements
StringBuffer validElements = new StringBuffer();
for (String element : Splitter.onPattern("\r?\n").trimResults()
.omitEmptyStrings().split(descriptionUnitToParse)) {
if (isValidElement(element)) {
validElements.append(element + "\n");
}
}
// Parse features
parseFeatures(intentSection, validElements);
// Parse stories
parseStories(intentSection, validElements);
// Parse scenarios
parseScenarios(intentSection, validElements);
}
}
/**
* Parse the stories.
*
* @param intentSection
* Intent Section
* @param validElements
* Valid elements
*/
private void parseStories(final IntentSection intentSection,
final StringBuffer validElements) {
// Get valid stories
StringBuffer validStories = new StringBuffer();
for (String element : Splitter.onPattern("\r?\n").trimResults()
.omitEmptyStrings().split(validElements)) {
if (isStory(element)) {
validStories.append(element + "\n");
}
}
// "Story:"
final String storyPattern = SpecificationKeyword.STORY.value + COLON;
for (String description : Splitter.onPattern(storyPattern)
.trimResults().omitEmptyStrings().split(validStories)) {
Map<String, String> result = Splitter.onPattern("\r?\n")
.trimResults().omitEmptyStrings()
.withKeyValueSeparator(COLON)
.split(storyPattern + description);
String storyDescription = result
.get(SpecificationKeyword.STORY.value);
final String storyName = storyDescription.substring(0,
storyDescription.indexOf(OPEN_BRACKET)).trim();
NamedElement namedElement = getNamedElement(storyName, Story.class);
Story story = null;
if (namedElement == null) {
story = specificationFactory.createStory();
story.setName(storyName);
specification.getStories().add((Story) story);
parsedElements.add(new ParsedElement(intentSection, story));
} else if (namedElement instanceof Story) {
story = (Story) namedElement;
} else {
throw new UnsupportedOperationException();
}
String features = storyDescription.substring(
storyDescription.indexOf(OPEN_BRACKET) + 1,
storyDescription.indexOf(CLOSE_BRACKET));
for (String featureName : Splitter.on(COMMA).trimResults()
.omitEmptyStrings().split(features)) {
namedElement = getNamedElement(featureName, Feature.class);
Feature feature = null;
if (namedElement == null) {
feature = specificationFactory.createFeature();
feature.setName(featureName);
specification.getFeatures().add(feature);
parsedElements
.add(new ParsedElement(intentSection, feature));
} else if (namedElement instanceof Feature) {
feature = (Feature) namedElement;
} else {
throw new UnsupportedOperationException();
}
feature.getStories().add((Story) story);
}
if (result.containsKey(SpecificationKeyword.AS.value)) {
String roleName = result.get(SpecificationKeyword.AS.value)
.trim();
namedElement = getNamedElement(roleName, Role.class);
Role role = null;
if (namedElement == null) {
role = specificationFactory.createRole();
role.setName(roleName);
specification.getRoles().add(role);
} else if (namedElement instanceof Role) {
role = (Role) namedElement;
} else {
throw new UnsupportedOperationException();
}
story.setAs(role);
String capabilityName = result.get(
SpecificationKeyword.I_WANT.value).trim();
namedElement = getNamedElement(capabilityName, Capability.class);
Capability capability = null;
if (namedElement == null) {
capability = specificationFactory.createCapability();
capability.setName(capabilityName);
specification.getCapabilities().add(capability);
} else if (namedElement instanceof Capability) {
capability = (Capability) namedElement;
} else {
throw new UnsupportedOperationException();
}
story.setIWant(capability);
String benefitName = result.get(
SpecificationKeyword.SO_THAT.value).trim();
namedElement = getNamedElement(benefitName, Benefit.class);
Benefit benefit = null;
if (namedElement == null) {
benefit = specificationFactory.createBenefit();
benefit.setName(benefitName);
specification.getBenefits().add(benefit);
} else if (namedElement instanceof Benefit) {
benefit = (Benefit) namedElement;
} else {
throw new UnsupportedOperationException();
}
story.setSoThat(benefit);
}
}
}
private void parseScenarios(IntentSection intentSection,
StringBuffer validElements) {
// Get valid scenarios
StringBuffer validScenarios = new StringBuffer();
for (String element : Splitter.onPattern("\r?\n").trimResults()
.omitEmptyStrings().split(validElements)) {
if (isScenario(element)) {
validScenarios.append(element + "\n");
}
}
// "Scenario:"
final String scenarioPattern = SpecificationKeyword.SCENARIO.value
+ COLON;
for (String description : Splitter.onPattern(scenarioPattern)
.trimResults().omitEmptyStrings().split(validScenarios)) {
Iterable<String> results = Splitter.onPattern("\r?\n")
.trimResults().omitEmptyStrings()
.split(scenarioPattern + description);
Scenario scenario = null;
for (String result : results) {
if (result.startsWith(SpecificationKeyword.SCENARIO.value)) {
String scenarioDescription = Splitter
.on(SpecificationKeyword.SCENARIO.value + COLON)
.trimResults().omitEmptyStrings().split(result)
.iterator().next();
// Scenario: Name [Parent Story]
final String scenarioName = scenarioDescription.substring(
0, scenarioDescription.indexOf(OPEN_BRACKET))
.trim();
NamedElement namedElement = getNamedElement(scenarioName,
Scenario.class);
if (namedElement == null) {
scenario = specificationFactory.createScenario();
scenario.setName(scenarioName);
parsedElements.add(new ParsedElement(intentSection,
scenario));
} else if (namedElement instanceof Scenario) {
scenario = (Scenario) namedElement;
} else {
throw new UnsupportedOperationException();
}
// Scenario: Name [Parent Story] @ui
TestGenerationNote testNote = specificationFactory
.createTestGenerationNote();
scenario.getNotes().add(testNote);
if (scenarioDescription.contains(AROBASE)) {
final String scenarioTestType = scenarioDescription
.substring(scenarioDescription.indexOf(AROBASE));
if (scenarioTestType.contains(TestType.UI.getName()
.toLowerCase())) {
testNote.setType(TestType.UI);
} else if (scenarioTestType.contains(TestType.UNIT
.getName().toLowerCase())) {
testNote.setType(TestType.UNIT);
} else if (scenarioTestType.contains(TestType.PLUGIN
.getName().toLowerCase())) {
testNote.setType(TestType.PLUGIN);
}
}
String stories = scenarioDescription.substring(
scenarioDescription.indexOf(OPEN_BRACKET) + 1,
scenarioDescription.indexOf(CLOSE_BRACKET));
for (String storyName : Splitter.on(COMMA).trimResults()
.omitEmptyStrings().split(stories)) {
namedElement = getNamedElement(storyName, Story.class);
Story story = null;
if (namedElement == null) {
story = specificationFactory.createStory();
story.setName(storyName);
specification.getStories().add(story);
parsedElements.add(new ParsedElement(intentSection,
story));
} else if (namedElement instanceof Story) {
story = (Story) namedElement;
} else {
throw new UnsupportedOperationException();
}
story.getScenarios().add(scenario);
}
} else if (result.startsWith(SpecificationKeyword.GIVEN.value)) {
String contextName = null;
if (result.contains(VARIABLE)) {
contextName = Splitter
.on(SpecificationKeyword.GIVEN.value + COLON)
.trimResults()
.omitEmptyStrings()
.split(result.substring(0,
result.indexOf(VARIABLE))).iterator()
.next();
} else {
// Given: MyContext [ParentContext]
if (result.contains(OPEN_BRACKET)) {
contextName = Splitter
.on(SpecificationKeyword.GIVEN.value
+ COLON)
.trimResults()
.omitEmptyStrings()
.split(result.substring(0,
result.indexOf(OPEN_BRACKET)))
.iterator().next();
} else {
// Given: MyContext
contextName = Splitter
.on(SpecificationKeyword.GIVEN.value
+ COLON).trimResults()
.omitEmptyStrings().split(result)
.iterator().next();
}
}
Context parentContext = null;
// Given: MyContext [ParentContext]
if (result.contains(OPEN_BRACKET)
&& result.contains(CLOSE_BRACKET)) {
String parentContextName = result.substring(
result.indexOf(OPEN_BRACKET) + 1,
result.indexOf(CLOSE_BRACKET));
NamedElement namedElement = getNamedElement(
parentContextName, Context.class);
if (namedElement == null) {
parentContext = specificationFactory
.createContext();
parentContext.setName(parentContextName);
automationLayer.getContext().add(parentContext);
} else if (namedElement instanceof Context) {
parentContext = (Context) namedElement;
}
}
NamedElement namedElement = getNamedElement(contextName,
Context.class);
Context context = null;
if (namedElement == null) {
context = specificationFactory.createContext();
context.setName(contextName);
if (parentContext != null) {
context.getContexts().add(parentContext);
}
automationLayer.getContext().add(context);
} else if (namedElement instanceof Context) {
context = (Context) namedElement;
} else {
throw new UnsupportedOperationException();
}
parseParameters(result, context, scenario);
scenario.getGiven().add(context);
} else if (result.startsWith(SpecificationKeyword.WHEN.value)) {
String actionName = null;
if (result.contains(VARIABLE)) {
actionName = Splitter
.on(SpecificationKeyword.WHEN.value + COLON)
.trimResults()
.omitEmptyStrings()
.split(result.substring(0,
result.indexOf(VARIABLE))).iterator()
.next();
} else {
actionName = Splitter
.on(SpecificationKeyword.WHEN.value + COLON)
.trimResults().omitEmptyStrings().split(result)
.iterator().next();
}
NamedElement namedElement = getNamedElement(actionName,
Action.class);
Action action = null;
if (namedElement == null) {
action = specificationFactory.createAction();
action.setName(actionName);
automationLayer.getActions().add(action);
} else if (namedElement instanceof Action) {
action = (Action) namedElement;
} else {
throw new UnsupportedOperationException();
}
parseParameters(result, action, scenario);
scenario.getWhen().add(action);
} else if (result.startsWith(SpecificationKeyword.THEN.value)) {
String behaviourName = null;
if (result.contains(VARIABLE)) {
behaviourName = Splitter
.on(SpecificationKeyword.THEN.value + COLON)
.trimResults()
.omitEmptyStrings()
.split(result.substring(0,
result.indexOf(VARIABLE))).iterator()
.next();
} else {
behaviourName = Splitter
.on(SpecificationKeyword.THEN.value + COLON)
.trimResults().omitEmptyStrings().split(result)
.iterator().next();
}
NamedElement namedElement = getNamedElement(behaviourName,
Behaviour.class);
Behaviour behaviour = null;
if (namedElement == null) {
behaviour = specificationFactory.createBehaviour();
behaviour.setName(behaviourName);
automationLayer.getBehaviours().add(behaviour);
} else if (namedElement instanceof Behaviour) {
behaviour = (Behaviour) namedElement;
} else {
throw new UnsupportedOperationException();
}
parseParameters(result, behaviour, scenario);
scenario.getThen().add(behaviour);
}
}
}
}
/**
* Parse the parameters.
*
* @param description
* Description to parse
* @param element
* Parent scenario element
* @param scenario
*/
private void parseParameters(String description, ScenarioElement element,
Scenario scenario) {
// Given: Action $Variable1 $Variable2
if (description.contains(VARIABLE)) {
Iterable<String> params = Splitter.on(VARIABLE).omitEmptyStrings()
.split(description);
// Ignore the first value as it is the action name
Iterator<String> iter = params.iterator();
iter.next();
int count = 0;
for (Iterator<String> iterator = iter; iterator.hasNext();) {
String param = (String) iterator.next();
String parameterName = element.getName() + count;
Parameter parameter = getParameter(parameterName, element);
if (parameter == null) {
parameter = specificationFactory.createParameter();
parameter.setName(parameterName);
element.getParameters().add(parameter);
}
Value value = specificationFactory.createValue();
value.setValue(param.substring(param.indexOf("'") + 1,
param.lastIndexOf("'")).replaceAll("\\\\", ""));
value.setParameter(parameter);
scenario.getValues().add(value);
count++;
}
}
}
private Parameter getParameter(final String parameterName,
final ScenarioElement element) {
UnmodifiableIterator<Parameter> it = Iterators.filter(element
.getParameters().iterator(), new Predicate<Parameter>() {
public boolean apply(Parameter parameter) {
if (parameter != null && parameter instanceof Parameter) {
return parameterName.equals(((NamedElement) parameter)
.getName());
}
return false;
}
});
if (it.hasNext()) {
return (Parameter) it.next();
}
return null;
}
/**
* Text to parse : "Feature: MyFeature1
* [ReferencedFeature1,ReferencedFeature2] Feature: MyFeature2
* [ReferencedFeature2,ReferencedFeature3]"
*
* @param intentSection
* @param validElements
* @return
*/
private void parseFeatures(IntentSection intentSection,
StringBuffer validElements) {
// Get valid features
StringBuffer validFeatures = new StringBuffer();
for (String element : Splitter.onPattern("\r?\n").trimResults()
.omitEmptyStrings().split(validElements)) {
if (isFeature(element)) {
validFeatures.append(element + "\n");
}
}
// "Feature:"
final String featurePattern = SpecificationKeyword.FEATURE.value
+ COLON;
for (String description : Splitter.onPattern(featurePattern)
.trimResults().omitEmptyStrings().split(validFeatures)) {
Map<String, String> result = Splitter.onPattern("\r?\n")
.trimResults().omitEmptyStrings()
.withKeyValueSeparator(COLON)
.split(featurePattern + description);
String featureDescription = result
.get(SpecificationKeyword.FEATURE.value);
String featureName;
if (featureDescription.contains(OPEN_BRACKET)) {
featureName = featureDescription.substring(0,
featureDescription.indexOf(OPEN_BRACKET)).trim();
} else {
featureName = featureDescription;
}
NamedElement namedElement = getNamedElement(featureName,
Feature.class);
Feature feature = null;
if (namedElement == null) {
feature = specificationFactory.createFeature();
feature.setName(featureName);
specification.getFeatures().add((Feature) feature);
parsedElements.add(new ParsedElement(intentSection, feature));
} else if (namedElement instanceof Feature) {
feature = (Feature) namedElement;
} else {
throw new UnsupportedOperationException();
}
if (featureDescription.contains(OPEN_BRACKET)) {
String features = featureDescription.substring(
featureDescription.indexOf(OPEN_BRACKET) + 1,
featureDescription.indexOf(CLOSE_BRACKET));
for (String refFeatureName : Splitter.on(COMMA).trimResults()
.omitEmptyStrings().split(features)) {
namedElement = getNamedElement(refFeatureName,
Feature.class);
Feature refFeature = null;
if (namedElement == null) {
refFeature = specificationFactory.createFeature();
refFeature.setName(refFeatureName);
specification.getFeatures().add(refFeature);
parsedElements.add(new ParsedElement(intentSection,
refFeature));
} else if (namedElement instanceof Feature) {
refFeature = (Feature) namedElement;
} else {
throw new UnsupportedOperationException();
}
refFeature.getRefFeatures().add((Feature) feature);
}
}
}
}
/**
* Check if an element is a feature.
*
* @param element
* Element
* @return True if the element is a feature
*/
private boolean isFeature(String element) {
return element.startsWith(SpecificationKeyword.FEATURE.value);
}
/**
* Check if an element is a story.
*
* @param element
* Element
* @return True if the element is a story
*/
private boolean isStory(String element) {
return element.startsWith(SpecificationKeyword.STORY.value)
|| element.startsWith(SpecificationKeyword.AS.value)
|| element.startsWith(SpecificationKeyword.I_WANT.value)
|| element.startsWith(SpecificationKeyword.SO_THAT.value);
}
/**
* Check if an element is a scenario.
*
* @param element
* Element
* @return True if the element is a scenario
*/
private boolean isScenario(String element) {
return element.startsWith(SpecificationKeyword.SCENARIO.value)
|| element.startsWith(SpecificationKeyword.GIVEN.value)
|| element.startsWith(SpecificationKeyword.WHEN.value)
|| element.startsWith(SpecificationKeyword.THEN.value);
}
/**
* Check if an element is a specification element (feature, story,
* scenario...).
*
* @param element
* Element
* @return True if the element is a specification element
*/
private boolean isValidElement(String element) {
for (SpecificationKeyword keyword : SpecificationKeyword.class
.getEnumConstants()) {
if (element.startsWith(keyword.value + COLON)) {
return true;
}
}
return false;
}
/**
* Get a named element defined in the specification.
*
* @param elementName
* Name of the element to search
* @param type
* Type of the element
* @return Named element or null if does not exist in the current
* specification
*/
@SuppressWarnings("rawtypes")
private NamedElement getNamedElement(final String elementName,
final Class type) {
UnmodifiableIterator<EObject> it = Iterators.filter(
specification.eAllContents(), new Predicate<EObject>() {
public boolean apply(EObject eObject) {
if (eObject != null
&& eObject instanceof NamedElement
&& type.getSimpleName().equals(
eObject.eClass().getName())) {
return elementName.equals(((NamedElement) eObject)
.getName());
}
return false;
}
});
if (it.hasNext()) {
return (NamedElement) it.next();
}
return null;
}
@Override
public void init() {
parsedElements.clear();
specification = specificationFactory.createSpecification();
specification.setName("UML Designer");
automationLayer = specificationFactory.createAutomationLayer();
automationLayer.setBasePackage("org.obeonetwork.dsl.uml2.design.tests");
specification.setAutomationLayer(automationLayer);
}
@Override
public void parsePostOperations(RepositoryAdapter repositoryAdapter) {
for (ParsedElement parsedElement : parsedElements) {
// Create a reference in the section if not exists
ModelingUnitQuery query = new ModelingUnitQuery(repositoryAdapter);
Collection<ExternalContentReference> externalContentReferences = query
.getAllExternalContentReferences();
NamedElement namedElement = parsedElement.getNamedElement();
Set<TestType> testTypes = SpecificationUtils
.getTestTypes(namedElement);
for (TestType testType : testTypes) {
if (!TestType.MANUAL.equals(testType)) {
URI uri = SpecificationUtils.getTestURI(
parsedElement.getNamedElement(), testType,
specification);
if (!referenceExists(externalContentReferences, uri)) {
createReference(parsedElement.getIntentSection(), uri);
}
}
}
}
// Serialize intent.specification
resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap()
.put("specification", new XMLResourceFactoryImpl());
URI uri = URI.createURI(repositoryAdapter.getRepository()
.getRepositoryURI() + "/intent.specification");
try {
if (resource != null) {
resource.delete(null);
}
} catch (IOException e) {
SpecificationParserActivator.log(Status.ERROR, "The resource "
+ uri.devicePath() + "cannot be deleted", e);
}
resource = resourceSet.createResource(uri);
resource.getContents().add(specification);
try {
resource.save(null);
} catch (IOException e) {
SpecificationParserActivator.log(Status.ERROR, "The resource "
+ uri.devicePath() + "cannot be saved", e);
}
}
/**
* Create a reference.
*
* @param intentSection
* Intent section
* @param uri
* URI of the file to reference
*/
private void createReference(IntentSection intentSection, URI uri) {
ModelingUnit modelingUnit = ModelingUnitFactory.eINSTANCE
.createModelingUnit();
ExternalContentReference referenceInstruction = ModelingUnitFactory.eINSTANCE
.createExternalContentReference();
referenceInstruction.setUri(uri);
referenceInstruction.setMarkedAsMerged(true);
modelingUnit.getInstructions().add(referenceInstruction);
intentSection.getIntentContent().add(
intentSection.getIntentContent().size(), modelingUnit);
}
/**
* Check if a reference exists in the given reference list.
*
* @param externalContentReferences
* Existing references
* @param uri
* URI to check
* @return True if reference exists in the given list otherwise false
*/
private boolean referenceExists(
final Collection<ExternalContentReference> externalContentReferences,
final URI uri) {
if (externalContentReferences.size() == 0) {
return false;
}
for (ExternalContentReference externalContentReference : externalContentReferences) {
if (uri.equals(externalContentReference.getUri())) {
return true;
}
}
return false;
}
@Override
public List<ExternalParserCompletionProposal> getCompletionVariablesProposals(
final Iterable<String> currentSentences) {
// Get last written sentence
Iterator<String> iterator = currentSentences.iterator();
String currentSentence = null;
while (iterator.hasNext()) {
currentSentence = (String) iterator.next();
}
List<ExternalParserCompletionProposal> variables = Lists.newArrayList();
if ((currentSentence.contains(SpecificationKeyword.FEATURE.value) || currentSentence
.contains(SpecificationKeyword.STORY.value))
&& currentSentence.contains(OPEN_BRACKET)) {
// Feature: Name[Features] or Story: Name [Features]
variables.addAll(getAllFeatures());
} else if ((currentSentence
.contains(SpecificationKeyword.SCENARIO.value))
&& currentSentence.contains(CLOSE_BRACKET)) {
// Scenario: Name[Stories]@
variables.addAll(getAllTestTypes());
} else if ((currentSentence
.contains(SpecificationKeyword.SCENARIO.value))
&& currentSentence.contains(OPEN_BRACKET)) {
// Scenario: Name[Stories]
variables.addAll(getAllStories());
} else if (currentSentence.contains(SpecificationKeyword.AS.value)) {
// As:
variables.addAll(getAllRoles());
} else if (currentSentence.contains(SpecificationKeyword.I_WANT.value)) {
// I want:
variables.addAll(getAllCapabilities());
} else if (currentSentence.contains(SpecificationKeyword.SO_THAT.value)) {
// So that:
variables.addAll(getAllBenefits());
} else if (currentSentence.contains(SpecificationKeyword.GIVEN.value)) {
// Given:
variables.addAll(getAllContexts());
} else if (currentSentence.contains(SpecificationKeyword.WHEN.value)) {
// When:
variables.addAll(getAllActions());
} else if (currentSentence.contains(SpecificationKeyword.THEN.value)) {
// Then:
variables.addAll(getAllBehaviours());
}
// Sorting proposals by alphabetical order
Collections.sort(variables,
new Comparator<ExternalParserCompletionProposal>() {
@Override
public int compare(
final ExternalParserCompletionProposal o1,
final ExternalParserCompletionProposal o2) {
return CommonPlugin.INSTANCE.getComparator().compare(
o1.getName(), o2.getName());
}
});
return variables;
}
/**
* Get all the possible test types.
*
* @return List of test types
*/
private List<ExternalParserCompletionProposal> getAllTestTypes() {
List<ExternalParserCompletionProposal> types = Lists.newArrayList();
types.add(new ExternalParserCompletionProposal(AROBASE
+ TestType.UI.getName().toLowerCase(),
"Define type of generated test", null,
SpecificationParserActivator.getDefault().getImage(
"icon/specification/TestGenerationNote.gif")));
types.add(new ExternalParserCompletionProposal(AROBASE
+ TestType.UNIT.getName().toLowerCase(),
"Define type of generated test", null,
SpecificationParserActivator.getDefault().getImage(
"icon/specification/TestGenerationNote.gif")));
types.add(new ExternalParserCompletionProposal(AROBASE
+ TestType.PLUGIN.getName().toLowerCase(),
"Define type of generated test", null,
SpecificationParserActivator.getDefault().getImage(
"icon/specification/TestGenerationNote.gif")));
types.add(new ExternalParserCompletionProposal(AROBASE
+ TestType.MANUAL.getName().toLowerCase(),
"Define type of generated test", null,
SpecificationParserActivator.getDefault().getImage(
"icon/specification/TestGenerationNote.gif")));
return types;
}
/**
* Get all roles defined in the specification.
*
* @return All roles defined in the specification or an empty list
*/
private List<ExternalParserCompletionProposal> getAllRoles() {
Specification spec = (Specification) resource.getContents().get(0);
List<ExternalParserCompletionProposal> results = Lists.newArrayList();
for (Role role : spec.getRoles()) {
results.add(new ExternalParserCompletionProposal(role.getName(),
Role.class.getSimpleName(), null,
SpecificationParserActivator.getDefault().getImage(
"icon/specification/Role.gif")));
}
return results;
}
/**
* Get all benefits defined in the specification.
*
* @return All benefits defined in the specification or en empty list
*/
private List<ExternalParserCompletionProposal> getAllBenefits() {
Specification spec = (Specification) resource.getContents().get(0);
List<ExternalParserCompletionProposal> results = Lists.newArrayList();
for (Benefit benefit : spec.getBenefits()) {
results.add(new ExternalParserCompletionProposal(benefit.getName(),
Benefit.class.getSimpleName(), null,
SpecificationParserActivator.getDefault().getImage(
"icon/specification/Benefit.gif")));
}
return results;
}
/**
* Get all capabilities defined in the specification.
*
* @return All capabilities defined in the specification or an empty list
*/
private List<ExternalParserCompletionProposal> getAllCapabilities() {
Specification spec = (Specification) resource.getContents().get(0);
List<ExternalParserCompletionProposal> results = Lists.newArrayList();
for (Capability capability : spec.getCapabilities()) {
results.add(new ExternalParserCompletionProposal(capability
.getName(), Capability.class.getSimpleName(), null,
SpecificationParserActivator.getDefault().getImage(
"icon/specification/Capability.gif")));
}
return results;
}
/**
* Get all contexts defined in the specification.
*
* @return All contexts defined in the specification or an empty list
*/
private List<ExternalParserCompletionProposal> getAllContexts() {
Specification spec = (Specification) resource.getContents().get(0);
List<ExternalParserCompletionProposal> results = Lists.newArrayList();
for (Context context : spec.getAutomationLayer().getContext()) {
results.add(new ExternalParserCompletionProposal(context.getName(),
Context.class.getSimpleName(), null,
SpecificationParserActivator.getDefault().getImage(
"icon/specification/Context.gif")));
}
return results;
}
/**
* Get all behaviours defined in the specification.
*
* @return All behaviours defined in the specification or an empty list
*/
private List<ExternalParserCompletionProposal> getAllBehaviours() {
Specification spec = (Specification) resource.getContents().get(0);
List<ExternalParserCompletionProposal> results = Lists.newArrayList();
for (Behaviour behaviour : spec.getAutomationLayer().getBehaviours()) {
results.add(new ExternalParserCompletionProposal(behaviour
.getName(), Behaviour.class.getSimpleName(), null,
SpecificationParserActivator.getDefault().getImage(
"icon/specification/Behaviour.gif")));
}
return results;
}
/**
* Get all actions defined in the specification.
*
* @return All actions defined in the specification or an empty list
*/
private List<ExternalParserCompletionProposal> getAllActions() {
Specification spec = (Specification) resource.getContents().get(0);
List<ExternalParserCompletionProposal> results = Lists.newArrayList();
for (Action action : spec.getAutomationLayer().getActions()) {
results.add(new ExternalParserCompletionProposal(action.getName(),
Action.class.getSimpleName(), null,
SpecificationParserActivator.getDefault().getImage(
"icon/specification/Action.gif")));
}
return results;
}
/**
* Get all features defined in the specification.
*
* @return All features defined in the specification or an empty list
*/
private List<ExternalParserCompletionProposal> getAllFeatures() {
Specification spec = (Specification) resource.getContents().get(0);
List<ExternalParserCompletionProposal> results = Lists.newArrayList();
for (Feature feature : spec.getFeatures()) {
results.add(new ExternalParserCompletionProposal(feature.getName(),
Feature.class.getSimpleName(), null,
SpecificationParserActivator.getDefault().getImage(
"icon/specification/Feature.gif")));
}
return results;
}
/**
* Get all stories defined in the specification.
*
* @return All stories defined in the specification or an empty list
*/
private List<ExternalParserCompletionProposal> getAllStories() {
Specification spec = (Specification) resource.getContents().get(0);
List<ExternalParserCompletionProposal> results = Lists.newArrayList();
for (Story story : spec.getStories()) {
results.add(new ExternalParserCompletionProposal(story.getName(),
Story.class.getSimpleName(), null,
SpecificationParserActivator.getDefault().getImage(
"icon/specification/Story.gif")));
}
return results;
}
@Override
public List<ExternalParserCompletionProposal> getCompletionTemplatesProposals(
Iterable<String> currentSentences) {
List<ExternalParserCompletionProposal> templates = Lists.newArrayList();
Iterator<String> iterator = currentSentences.iterator();
String currentSentence = null;
while (iterator.hasNext()) {
currentSentence = (String) iterator.next();
}
if (currentSentence
.endsWith(SpecificationKeyword.FEATURE.value + COLON)) {
// Feature:
templates.add(new ExternalParserCompletionProposal("Feature",
"Declare a new feature", " ${Name} [${ParentFeature}]",
SpecificationParserActivator.getDefault().getImage(
"icon/specification/Feature.gif")));
} else if (currentSentence.endsWith(SpecificationKeyword.STORY.value
+ COLON)) {
// Story:
templates
.add(new ExternalParserCompletionProposal(
"Story",
"Declare a new story",
" ${Name} [${ReferencingFeature}]\n\tAs: ${Role}\n\tI want: ${Capability}\n\tSo that: ${Benefit}",
SpecificationParserActivator.getDefault().getImage(
"icon/specification/Story.gif")));
} else {
// Add all the possible templates
templates.add(new ExternalParserCompletionProposal("Feature",
"Declare a new feature",
"Feature: ${Name} [${ParentFeature}]",
SpecificationParserActivator.getDefault().getImage(
"icon/specification/Feature.gif")));
templates
.add(new ExternalParserCompletionProposal(
"Story",
"Declare a new story",
"Story: ${Name} [${ReferencingFeature}]\n\tAs: ${Role}\n\tI want: ${Capability}\n\tSo that: ${Benefit}",
SpecificationParserActivator.getDefault().getImage(
"icon/specification/Story.gif")));
templates
.add(new ExternalParserCompletionProposal(
"Scenario",
"Declare a new scenario",
"Scenario: ${Name} [${ParentStory}]\n\tGiven: ${Context}\n\tWhen: ${Action}\n\tThen: ${Behaviour}",
SpecificationParserActivator.getDefault().getImage(
"icon/specification/Scenario.gif")));
}
return templates;
}
}