1 package com.github.dexecutor.executor.graph;
2
3 import java.util.ArrayList;
4 import java.util.Collection;
5
6 import com.github.dexecutor.executor.graph.Graph.Node;
7
8
9
10
11
12
13
14 public class CyclicValidator<T extends Comparable<T>> implements Validator<T> {
15
16 private Collection<Graph.Node<T>> processedNodes = new ArrayList<Graph.Node<T>>();
17 private Collection<Graph.Node<T>> onStackNodes = new ArrayList<Graph.Node<T>>();
18
19 public void validate(final Graph<T> graph) {
20 doProcess(graph.allNodes());
21 }
22
23 private void doProcess(final Collection<Graph.Node<T>> nodes) {
24 for (Graph.Node<T> node : nodes) {
25 detectCycle(node);
26 }
27 }
28
29 private void detectCycle(final Node<T> node) {
30 this.processedNodes.add(node);
31 this.onStackNodes.add(node);
32 doDepthFirstTraversal(node);
33 this.onStackNodes.remove(node);
34 }
35
36 private void doDepthFirstTraversal(final Node<T> node) {
37 for (Node<T> adjNode : node.getOutGoingNodes()) {
38 if (!isAlreadyProcessed(adjNode)) {
39 detectCycle(adjNode);
40 } else if (isOnStack(adjNode)) {
41 throw new IllegalArgumentException("Cycle Detected " + node + " With " + adjNode);
42 }
43 }
44 }
45
46 private boolean isAlreadyProcessed(final Node<T> node) {
47 return this.processedNodes.contains(node);
48 }
49
50 private boolean isOnStack(final Node<T> node) {
51 return this.onStackNodes.contains(node);
52 }
53 }