in src/main/java/org/apache/openejb/tools/release/util/References.java [33:111]
public static <T> List<T> sort(final List<T> objects, final Visitor<T> visitor) {
if (objects.size() <= 1) {
return objects;
}
final Map<String, Node> nodes = new LinkedHashMap<String, Node>();
// Create nodes
for (final T obj : objects) {
final String name = visitor.getName(obj);
final Node node = new Node(name, obj);
nodes.put(name, node);
}
// Link nodes
for (final Node node : nodes.values()) {
for (final String name : visitor.getReferences((T) node.object)) {
final Node ref = nodes.get(name);
if (ref == null) throw new IllegalArgumentException("No such object in list: " + name);
node.references.add(ref);
node.initialReferences.add(ref);
}
}
boolean circuitFounded = false;
for (final Node node : nodes.values()) {
final Set<Node> visitedNodes = new HashSet<Node>();
if (!normalizeNodeReferences(node, node, visitedNodes)) {
circuitFounded = true;
break;
}
node.references.addAll(visitedNodes);
}
//detect circus
if (circuitFounded) {
final Set<Circuit> circuits = new LinkedHashSet<Circuit>();
for (final Node node : nodes.values()) {
findCircuits(circuits, node, new java.util.Stack<Node>());
}
final ArrayList<Circuit> list = new ArrayList<Circuit>(circuits);
Collections.sort(list);
final List<List> all = new ArrayList<List>();
for (final Circuit circuit : list) {
all.add(unwrap(circuit.nodes));
}
throw new CircularReferencesException(all);
}
//Build Double Link Node List
final Node rootNode = new Node(null, null);
rootNode.previous = rootNode;
rootNode.next = nodes.values().iterator().next();
for (final Node node : nodes.values()) {
node.previous = rootNode.previous;
rootNode.previous.next = node;
node.next = rootNode;
rootNode.previous = node;
}
for (final Node node : nodes.values()) {
for (final Node reference : node.references) {
swap(node, reference, rootNode);
}
}
final List sortedList = new ArrayList(nodes.size());
Node currentNode = rootNode.next;
while (currentNode != rootNode) {
sortedList.add(currentNode.object);
currentNode = currentNode.next;
}
return sortedList;
}