package brainslug.flow.definition;
import brainslug.flow.node.FlowNodeDefinition;
import java.util.ArrayList;
import java.util.List;
/**
* A FlowDefinition is used to describe paths of actions for
* a desired outcome. It consists of a set of nodes which are typed to define their behaviour
* and which are connected according to the sequence of execution.
*/
public class FlowDefinition {
private Identifier id;
private String name;
List<FlowNodeDefinition> startNodes = new ArrayList<FlowNodeDefinition>();
List<FlowNodeDefinition> nodes = new ArrayList<FlowNodeDefinition>();
public FlowDefinition() {
}
public <T extends FlowNodeDefinition> T addNode(T flowNodeDefinition) {
nodes.add(flowNodeDefinition);
return flowNodeDefinition;
}
public <T extends FlowNodeDefinition> T addStartNode(T flowNodeDefinition) {
startNodes.add(flowNodeDefinition);
nodes.add(flowNodeDefinition);
return flowNodeDefinition;
}
public FlowNodeDefinition<?> getNode(Identifier id) {
for (FlowNodeDefinition node: nodes) {
if(node.getId().equals(id)) {
return node;
}
}
throw new IllegalArgumentException("Node with id " + id + " does not exist.");
}
public <T extends FlowNodeDefinition> List<FlowNodeDefinition<T>> getNodesByType(Class<T> clazz) {
List<FlowNodeDefinition<T>> nodesWithType = new ArrayList<FlowNodeDefinition<T>>();
for (FlowNodeDefinition node: nodes) {
if(clazz.isAssignableFrom(node.getClass())) {
nodesWithType.add(node);
}
}
return nodesWithType;
}
public <T extends FlowNodeDefinition> T getNode(Identifier id, Class<T> clazz) {
FlowNodeDefinition<?> node = getNode(id);
if (!clazz.isAssignableFrom(node.getClass())) {
throw new IllegalArgumentException("Requested node should have type " + clazz.getName());
}
return (T) node;
}
public FlowNodeDefinition<?> requireSingleStartNode() {
if (getStartNodes().size() != 1) {
throw new IllegalArgumentException("required single start node, but there are " + getNodes().size());
}
return getStartNodes().get(0);
}
public List<FlowNodeDefinition> getNodes() {
return nodes;
}
public List<FlowNodeDefinition> getStartNodes() {
return startNodes;
}
public boolean contains(FlowNodeDefinition<?> flowNodeDefinition) {
return getNodes().contains(flowNodeDefinition);
}
public Identifier getId() {
return id;
}
public String getName() {
return name;
}
public FlowDefinition name(String name) {
this.name = name;
return this;
}
public FlowDefinition id(Identifier id) {
this.id = id;
return this;
}
}