package eu.stratosphere.util.dag; import java.util.Arrays; import java.util.IdentityHashMap; import java.util.Iterator; import java.util.Map; /** * Implementing classes traverse a directed acyclic graph (DAG) with a specific strategy. Unless explicitly stated, no * implementing class should visit a node more than once. * * @author Arvid Heise */ public abstract class AbstractGraphTraverser implements GraphTraverser { /** * Returns all reachable nodes from the start nodes including the start nodes themselves. * * @param startNodes * the initial nodes of the graph * @param navigator * successively returns all connected nodes from the initial nodes * @param <Node> * the class of the nodes * @return all reachable nodes */ public <Node> Iterable<Node> getReachableNodes(final Iterable<? extends Node> startNodes, final ConnectionNavigator<Node> navigator) { return this.getReachableNodes(startNodes.iterator(), navigator); } /** * Returns all reachable nodes from the start nodes including the start nodes themselves. * * @param startNodes * the initial nodes of the graph * @param navigator * successively returns all connected nodes from the initial nodes * @param <Node> * the class of the nodes * @return all reachable nodes */ public <Node> Iterable<Node> getReachableNodes(final Iterator<? extends Node> startNodes, final ConnectionNavigator<Node> navigator) { final Map<Node, Object> visitedNodes = new IdentityHashMap<Node, Object>(); this.traverse(startNodes, navigator, new GraphTraverseListener<Node>() { @Override public void nodeTraversed(final Node node) { visitedNodes.put(node, null); } }); return visitedNodes.keySet(); } /** * Returns all reachable nodes from the start nodes including the start nodes themselves. * * @param startNodes * the initial nodes of the graph * @param navigator * successively returns all connected nodes from the initial nodes * @param <Node> * the class of the nodes * @return all reachable nodes */ public <Node> Iterable<Node> getReachableNodes(final Node[] startNodes, final ConnectionNavigator<Node> navigator) { return this.getReachableNodes(Arrays.asList(startNodes).iterator(), navigator); } /** * Traverses the DAG consisting of the given start nodes and all notes reachable with the navigator and calls the * specified {@link GraphTraverseListener} for each found node. * * @param startNodes * the initial nodes of the graph * @param navigator * successively returns all connected nodes from the initial nodes * @param listener * the callback called for all nodes in the DAG * @param <Node> * the class of the nodes */ public <Node> void traverse(final Iterable<? extends Node> startNodes, final ConnectionNavigator<Node> navigator, final GraphTraverseListener<Node> listener) { this.traverse(startNodes.iterator(), navigator, listener); } /** * Traverses the DAG consisting of the given start nodes and all notes reachable with the navigator and calls the * specified {@link GraphTraverseListener} for each found node. * * @param startNodes * the initial nodes of the graph * @param navigator * successively returns all connected nodes from the initial nodes * @param listener * the callback called for all nodes in the DAG * @param <Node> * the class of the nodes */ public <Node> void traverse(final Node[] startNodes, final ConnectionNavigator<Node> navigator, final GraphTraverseListener<Node> listener) { this.traverse(Arrays.asList(startNodes).iterator(), navigator, listener); } }