poussecafe.doc.model.DomainProcessSteps Maven / Gradle / Ivy
package poussecafe.doc.model;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import poussecafe.doc.model.domainprocessdoc.Step;
import poussecafe.doc.model.domainprocessdoc.StepName;
import poussecafe.doc.model.domainprocessdoc.ToStep;
import static java.util.stream.Collectors.toList;
public class DomainProcessSteps {
public DomainProcessSteps(Map steps) {
Objects.requireNonNull(steps);
this.steps = steps;
}
private Map steps;
public Map steps() {
return steps;
}
public List orderedSteps() {
if(orderedSteps == null) {
Map> graph = buildGraphMap();
List orderedStepNames = topologicalOrdering(graph);
orderedSteps = orderedStepNames
.stream()
.map(StepName::new)
.map(stepName -> steps.get(stepName))
.collect(toList());
}
return orderedSteps;
}
private List orderedSteps;
private Map> buildGraphMap() {
Map> graph = new HashMap<>();
for(Step step : steps.values()) {
if(!graph.containsKey(step.componentDoc().name())) {
graph.put(step.componentDoc().name(), new ArrayList<>());
}
for(ToStep to : step.tos()) {
List froms = graph.get(to.name().stringValue());
if(froms == null) {
froms = new ArrayList<>();
graph.put(to.name().stringValue(), froms);
}
froms.add(step.componentDoc().name());
}
}
return graph;
}
private List topologicalOrdering(Map> graph) {
List orderedNodes = new ArrayList<>();
Map> partialGraph = new HashMap<>(graph);
while(partialGraph.size() > 0) {
String nodeWithoutFrom = findNodeWithoutFrom(partialGraph);
orderedNodes.add(nodeWithoutFrom);
removeNode(partialGraph, nodeWithoutFrom);
}
return orderedNodes;
}
private String findNodeWithoutFrom(Map> graph) {
for(Entry> e : graph.entrySet()) {
if(e.getValue().isEmpty()) {
return e.getKey();
}
}
return graph.entrySet().iterator().next().getKey();
}
private void removeNode(Map> graph, String nodeName) {
Iterator>> iterator = graph.entrySet().iterator();
while(iterator.hasNext()) {
Entry> entry = iterator.next();
if(entry.getKey().equals(nodeName)) {
iterator.remove();
} else {
entry.getValue().remove(nodeName);
}
}
}
public Step getStep(StepName name) {
return steps.get(name);
}
}