package net.thucydides.core.requirements.model;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import net.thucydides.core.model.TestTag;
import java.util.Collections;
import java.util.List;
/**
* A capability represents a high-level business goal that will appear in the result summary report.
* This report summarizes the state of the application in terms of what capabilities have been implemented.
* Capabilities are implemented via <em>features</em>, which in turn are tested by scenarios.
*/
public class Requirement implements Comparable {
private String displayName;
private String name;
private String type;
private CustomFieldValue narrative;
private String cardNumber;
private List<Requirement> children;
private String parent;
private List<Example> examples;
private List<String> releaseVersions;
private List<CustomFieldValue> customFields;
public Requirement() {
// Used by Jackson
children = Lists.newArrayList();
examples = Lists.newArrayList();
releaseVersions = Lists.newArrayList();
customFields = Lists.newArrayList();
}
protected Requirement(String name, String displayName, String cardNumber, String parent, String type, CustomFieldValue narrative,
List<Requirement> children, List<Example> examples,
List<String> releaseVersions) {
this(name, displayName, cardNumber, parent, type, narrative, children, examples,releaseVersions, Collections.EMPTY_LIST);
}
protected Requirement(String name, String displayName, String cardNumber, String parent, String type, CustomFieldValue narrative) {
this(name, displayName, cardNumber, parent, type, narrative, Collections.EMPTY_LIST, Collections.EMPTY_LIST,Collections.EMPTY_LIST,
Collections.EMPTY_LIST);
}
protected Requirement(String name, String displayName, String cardNumber, String parent, String type, CustomFieldValue narrative,
List<Requirement> children, List<Example> examples,
List<String> releaseVersions,
List<CustomFieldValue> customFields) {
Preconditions.checkNotNull(name);
Preconditions.checkNotNull(type);
this.name = name;
this.displayName = displayName;
this.cardNumber = cardNumber;
this.type = type;
this.parent = parent;
this.narrative = narrative;
this.children = ImmutableList.copyOf(children);
this.examples = ImmutableList.copyOf(examples);
this.releaseVersions = ImmutableList.copyOf(releaseVersions);
this.customFields = ImmutableList.copyOf(customFields);
}
public String getName() {
return name;
}
public String getDisplayName() {
return displayName;
}
public String getType() {
return type;
}
public String childType() {
return (!children.isEmpty()) ? children.get(0).getType() : null;
}
public CustomFieldValue getNarrative() {
return narrative;
}
public List<String> getReleaseVersions() {
return releaseVersions;
}
@JsonIgnore
public int getChildrenCount() {
return children.size();
}
public String getParent() {
return parent;
}
public List<Requirement> getChildren() {
return ImmutableList.copyOf(children);
}
public List<Example> getExamples() {
return ImmutableList.copyOf(examples);
}
public Boolean hasExamples() {
return !examples.isEmpty();
}
@JsonIgnore
public int getExampleCount() {
return examples.size();
}
public String getCardNumber() {
return cardNumber;
}
public int compareTo(Object otherRequirement) {
return name.compareTo(((Requirement) otherRequirement).getName());
}
public static RequirementBuilderNameStep named(String name) {
return new RequirementBuilderNameStep(name);
}
public Requirement withChildren(List<Requirement> children) {
return new Requirement(this.name, this.displayName, this.cardNumber, this.parent, this.type, this.narrative, children, examples, releaseVersions);
}
public Requirement withParent(String parent) {
return new Requirement(this.name, this.displayName, this.cardNumber, parent, this.type, this.narrative, children, examples, releaseVersions);
}
public Requirement withType(String type) {
return new Requirement(this.name, this.displayName, this.cardNumber, this.parent, type, this.narrative, children, examples, releaseVersions);
}
public Requirement withExample(Example example) {
List<Example> updatedExamples = Lists.newArrayList(examples);
updatedExamples.add(example);
return new Requirement(this.name, this.displayName, this.cardNumber, this.parent, this.type, this.narrative, children, updatedExamples, releaseVersions);
}
public Requirement withExamples(List<Example> examples) {
return new Requirement(this.name, this.displayName, this.cardNumber, this.parent, this. type,this.narrative, children, examples, releaseVersions);
}
public Requirement withReleaseVersions(List<String> releaseVersions) {
return new Requirement(this.name, this.displayName, this.cardNumber, this.parent, this.type, this.narrative, children, examples, releaseVersions);
}
public boolean hasChildren() {
return (children != null) && (!children.isEmpty());
}
public List<Requirement> getNestedChildren() {
List<Requirement> nestedChildren = Lists.newArrayList();
for(Requirement child : children) {
nestedChildren.add(child);
nestedChildren.addAll(child.getNestedChildren());
}
return ImmutableList.copyOf(nestedChildren);
}
public TestTag asTag() {
return TestTag.withName(qualifiedName()).andType(getType());
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Requirement that = (Requirement) o;
if (name != null ? !name.equals(that.name) : that.name != null) return false;
if (parent != null ? !parent.equals(that.parent) : that.parent != null) return false;
if (type != null ? !type.equals(that.type) : that.type != null) return false;
return true;
}
public boolean matches(Requirement that) {
if (name != null ? !name.equals(that.name) : that.name != null) return false;
if (type != null ? !type.equals(that.type) : that.type != null) return false;
if (cardNumber != null ? !cardNumber.equals(that.cardNumber) : that.cardNumber != null) return false;
return true;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + (type != null ? type.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "Requirement{" +
"name='" + name + '\'' +
", type='" + type + '\'' + " parent = '" + parent + '\'' +
", cardNumber='" + cardNumber + '\'' +
'}';
}
public Requirement withChild(Requirement child) {
List<Requirement> newChildren = Lists.newArrayList(children);
newChildren.remove(child);
newChildren.add(child);
return new Requirement(name,displayName,cardNumber,parent, type, narrative, newChildren, examples,releaseVersions);
}
public CustomFieldSetter withCustomField(String fieldName) {
return new CustomFieldSetter(this, fieldName);
}
public List<CustomFieldValue> getCustomFieldValues() {
return ImmutableList.copyOf(customFields);
}
public Optional<CustomFieldValue> getCustomField(String fieldName) {
for(CustomFieldValue field : customFields) {
if (field.getName().equals(fieldName)) {
return Optional.of(field);
}
}
return Optional.absent();
}
public List<String> getCustomFields() {
List<String> customFieldNames = Lists.newArrayList();
for(CustomFieldValue field : customFields) {
customFieldNames.add(field.getName());
}
return customFieldNames;
}
public String qualifiedName() {
return (qualifier() != null) ? qualifier() + "/" + getName() : getName();
}
public String qualifier() {
if (getCardNumber() != null) {
return getCardNumber();
}
return (getParent() != null) ? getParent() : null;
// if (getCardNumber() != null) {
// return getCardNumber();
// } else
// if (getParent() != null) {
// return getParent();
// } else {
// return null;
// }
}
public boolean matchesTag(TestTag testTag) {
TestTag requirementTag = asTag();
return requirementTag.isAsOrMoreSpecificThan(testTag);
}
public class CustomFieldSetter {
Requirement requirement;
String fieldName;
public CustomFieldSetter(Requirement requirement, String fieldName) {
this.requirement = requirement;
this.fieldName = fieldName;
}
public Requirement setTo(String value, String renderedValue) {
List<CustomFieldValue> customFields = Lists.newArrayList(requirement.getCustomFieldValues());
customFields.add(new CustomFieldValue(fieldName, value, renderedValue));
return new Requirement(requirement.name, requirement.displayName,
requirement.cardNumber, requirement.parent, requirement.type, requirement.narrative,
requirement.children, requirement.examples, requirement.releaseVersions,
customFields);
}
public Requirement setTo(String value) {
return setTo(value, null);
}
}
}