package org.mef.sprig.util;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
//http://chianti.ucsd.edu/svn/core3/model-impl/tags/model-impl-parent-3.0.0-alpha3/impl/src/main/java/org/cytoscape/model/internal/tsort/TopologicalSort.java
/**
* Implements topological sorting of nodes in a graph.
* See for example http://en.wikipedia.org/wiki/Topological_sorting (the Tarjan algorithm)
*/
public class TopologicalSort {
/**
* @param nodes the list of all nodes
* @param edges the edges that connect the nodes that need to be sorted.
* @return the topological order
* @throws IllegalStateException if a cycle has been detected
* N.B. it might be a good idea to make sure that whatever the concrete type of the nodes in
* "nodes" are has a toString() method that returns the name of a node since this method
* will be used if a cycle has been detected to report one of the nodes in the cycle.
*/
public static List<TSortNode> sort(final Collection<TSortNode> nodes)
throws IllegalStateException
{
final List<TSortNode> order = new ArrayList<TSortNode>();
final Set<TSortNode> visited = new HashSet<TSortNode>();
final Set<TSortNode> alreadySeen = new HashSet<TSortNode>();
for (final TSortNode n : nodes) {
alreadySeen.clear();
visit(n, alreadySeen, visited, order);
}
return order;
}
private static void visit(final TSortNode n, final Set<TSortNode> alreadySeen,
final Set<TSortNode> visited, final List<TSortNode> order)
{
if (alreadySeen.contains(n))
throw new IllegalStateException("cycle containing " + n + " found!");
alreadySeen.add(n);
if (!visited.contains(n)) {
visited.add(n);
for (final TSortNode m : n.getDependents())
visit(m, alreadySeen, visited, order);
order.add(n);
}
alreadySeen.remove(n);
}
}