package esl.datastructures.graph;
import org.apache.log4j.Logger;
import java.util.AbstractMap;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;
public class DFSTraverser<N extends Node, E extends Edge> implements Traverser<N, E> {
private Logger logger = Logger.getLogger(DFSTraverser.class);
private NodeVisitor nodeVisitor = null;
private EdgeVisitor edgeVisitor = null;
private TraversalContext traversalContext = null;
public void setTraversalContext (TraversalContext object) {
this.traversalContext = object;
}
private void traverseDFS(Graph<N, E> graph) {
HashMap<String, Integer> seenMap = new HashMap<String, Integer>();
Stack<Map.Entry<N, E>> nodeStack = new Stack<Map.Entry<N, E>>();
nodeStack.add(new AbstractMap.SimpleEntry<N, E>(graph.getStartNode(), null));
boolean allSeen;
while( !nodeStack.empty() ) {
Map.Entry<N, E> entry = nodeStack.peek();
N n = entry.getKey();
if (seenMap.get(n.name()) == null) seenMap.put(n.name(), 0);
if (seenMap.get(n.name()) != 0) {
nodeStack.pop();
continue;
}
if (entry.getValue() != null) edgeVisitor.visit(entry.getValue(), traversalContext);
nodeVisitor.visit(n, traversalContext);
seenMap.put(n.name(), 1);
if (graph.getOutgoingEdges(n) == null || graph.getOutgoingEdges(n).size() == 0) {
nodeStack.pop();
continue;
}
allSeen = true;
for (E e: graph.getOutgoingEdges(n)) {
N dest = graph.getDestinationNode(e);
if ( seenMap.get(dest.name()) == null || seenMap.get(dest.name()) == 0 ) {
nodeStack.push(new AbstractMap.SimpleEntry<N, E>(dest, e));
allSeen = false;
}
}
if (allSeen) nodeStack.pop();
}
}
@Override
public void setNodeVisitorCallback(NodeVisitor visitorCallback) {
this.nodeVisitor = visitorCallback;
}
@Override
public void setEdgeVisitorCallback(EdgeVisitor visitorCallback) {
this.edgeVisitor = visitorCallback;
}
@Override
public void start(Graph<N, E> graph) {
if (edgeVisitor == null || nodeVisitor == null)
throw new RuntimeException("Edge and Node Visitors not set before traversal");
traverseDFS(graph);
}
}