package io.lumify.core.util;
import java.util.ArrayList;
import java.util.List;
public class AutoDependencyTreeRunner {
private static final LumifyLogger LOGGER = LumifyLoggerFactory.getLogger(AutoDependencyTreeRunner.class);
private List<DependencyNode> dependencyNodes = new ArrayList<DependencyNode>();
public void add(Runnable... newRunnables) {
for (int i = 0; i < newRunnables.length; i++) {
if (i == 0) {
addDependencyNode(newRunnables[i], null);
} else {
addDependencyNode(newRunnables[i], newRunnables[i - 1]);
}
}
}
private void addDependencyNode(Runnable runnable, Runnable dependency) {
DependencyNode dependencyNode = findOrAddDependencyNode(runnable);
if (dependency != null) {
dependencyNode.addDependency(findOrAddDependencyNode(dependency));
}
}
private DependencyNode findOrAddDependencyNode(Runnable runnable) {
DependencyNode dependencyNode = findDependencyNode(runnable);
if (dependencyNode == null) {
dependencyNode = new DependencyNode(runnable);
dependencyNodes.add(dependencyNode);
}
return dependencyNode;
}
private DependencyNode findDependencyNode(Runnable runnable) {
for (DependencyNode dependencyNode : dependencyNodes) {
if (dependencyNode.equals(runnable)) {
return dependencyNode;
}
}
return null;
}
public void dryRun() {
run(true);
}
public void run() {
run(false);
}
private void run(boolean dryRun) {
List<DependencyNode> ranNodes = new ArrayList<DependencyNode>();
for (DependencyNode dependencyNode : dependencyNodes) {
run(dependencyNode, ranNodes, dryRun);
}
}
private void run(DependencyNode dependencyNode, List<DependencyNode> ranNodes, boolean dryRun) {
for (DependencyNode dependent : dependencyNode.getDependents()) {
if (ranNodes.contains(dependent)) {
continue;
}
run(dependent, ranNodes, dryRun);
ranNodes.add(dependent);
}
if (!ranNodes.contains(dependencyNode)) {
LOGGER.debug("Running " + dependencyNode);
if (!dryRun) {
dependencyNode.getRunnable().run();
}
ranNodes.add(dependencyNode);
}
}
private static class DependencyNode {
private final Runnable runnable;
private final List<DependencyNode> dependents = new ArrayList<DependencyNode>();
public DependencyNode(Runnable runnable) {
this.runnable = runnable;
}
public void addDependency(DependencyNode dependentNode) {
dependents.add(dependentNode);
}
public List<DependencyNode> getDependents() {
return dependents;
}
public Runnable getRunnable() {
return runnable;
}
@Override
public String toString() {
return getRunnable().toString();
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Runnable) {
return obj == this.runnable;
} else if (obj instanceof DependencyNode) {
return ((DependencyNode) obj).getRunnable() == this.runnable;
} else {
throw new RuntimeException("Not supported");
}
}
}
}