com.softicar.platform.common.math.topology.TopologicalSorter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of platform-common Show documentation
Show all versions of platform-common Show documentation
The SoftiCAR Platform is a lightweight, Java-based library to create interactive business web applications.
package com.softicar.platform.common.math.topology;
import com.softicar.platform.common.core.exceptions.SofticarDeveloperException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class TopologicalSorter {
private final Map nodes;
private List sortedElements;
public TopologicalSorter() {
this.nodes = new HashMap<>();
}
public TopologicalSorter(Collection elements) {
this();
addAll(elements);
}
public TopologicalSorter add(T element) {
nodes.put(element, new Node(element));
return this;
}
public TopologicalSorter addAll(Collection elements) {
elements.forEach(it -> nodes.put(it, new Node(it)));
return this;
}
public TopologicalSorter addEdge(T elementA, T elementB) {
nodes//
.computeIfAbsent(elementA, Node::new)
.addTargetNode(nodes.computeIfAbsent(elementB, Node::new));
return this;
}
public Collection getSorted() {
this.sortedElements = new ArrayList<>();
for (Node node: nodes.values()) {
visit(node);
}
Collections.reverse(sortedElements);
return sortedElements;
}
private void visit(Node node) {
if (node.visited) {
throw new CyclicTopologyException();
}
if (!node.done) {
node.visited = true;
for (Node targetNode: node.targetNodes) {
visit(targetNode);
}
node.visited = false;
node.done = true;
sortedElements.add(node.element);
}
}
private class Node {
private final T element;
private Collection targetNodes;
private boolean visited;
private boolean done;
public Node(T element) {
this.element = element;
this.targetNodes = Collections.emptyList();
this.visited = false;
this.done = false;
}
public void addTargetNode(Node targetNode) {
if (targetNodes.isEmpty()) {
targetNodes = new ArrayList<>();
}
targetNodes.add(targetNode);
}
}
public static class CyclicTopologyException extends SofticarDeveloperException {
public CyclicTopologyException() {
super("There are cycles in the dependeny graph.");
}
}
}