2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.yangtools.yang.parser.util;
10 import com.google.common.base.Preconditions;
11 import com.google.common.collect.Lists;
12 import com.google.common.collect.Sets;
13 import java.util.List;
17 * Utility class that provides topological sort
19 public final class TopologicalSort {
22 * It isn't desirable to create instance of this class
24 private TopologicalSort() {
28 * Topological sort of dependent nodes in acyclic graphs.
30 * @param nodes graph nodes
31 * @return Sorted {@link List} of {@link Node}s. Order: Nodes with no
32 * dependencies starting.
33 * @throws IllegalStateException
34 * when cycle is present in the graph
36 public static List<Node> sort(Set<Node> nodes) {
37 List<Node> sortedNodes = Lists.newArrayList();
39 Set<Node> dependentNodes = getDependentNodes(nodes);
41 while (!dependentNodes.isEmpty()) {
42 Node n = dependentNodes.iterator().next();
43 dependentNodes.remove(n);
47 for (Edge e : n.getInEdges()) {
49 m.getOutEdges().remove(e);
51 if (m.getOutEdges().isEmpty()) {
52 dependentNodes.add(m);
62 private static Set<Node> getDependentNodes(Set<Node> nodes) {
63 Set<Node> dependentNodes = Sets.newHashSet();
64 for (Node n : nodes) {
65 if (n.getOutEdges().isEmpty()) {
66 dependentNodes.add(n);
69 return dependentNodes;
72 private static void detectCycles(Set<Node> nodes) {
74 boolean cycle = false;
75 Node cycledNode = null;
77 for (Node n : nodes) {
78 if (!n.getOutEdges().isEmpty()) {
84 Preconditions.checkState(!cycle, "Cycle detected in graph around node: " + cycledNode);
88 * Interface for nodes in graph that can be sorted topologically
90 public interface Node {
91 Set<Edge> getInEdges();
93 Set<Edge> getOutEdges();
97 * Interface for edges in graph that can be sorted topologically
99 public interface Edge {
106 * Basic Node implementation.
108 public static class NodeImpl implements Node {
109 private final Set<Edge> inEdges;
110 private final Set<Edge> outEdges;
113 inEdges = Sets.newHashSet();
114 outEdges = Sets.newHashSet();
118 public Set<Edge> getInEdges() {
123 public Set<Edge> getOutEdges() {
127 public void addEdge(Node to) {
128 Edge e = new EdgeImpl(this, to);
130 to.getInEdges().add(e);
135 * Basic Edge implementation
137 public static class EdgeImpl implements Edge {
138 private final Node from;
139 private final Node to;
141 public EdgeImpl(Node from, Node to) {
147 public Node getFrom() {
152 public Node getTo() {
157 public int hashCode() {
158 final int prime = 31;
160 result = prime * result + ((from == null) ? 0 : from.hashCode());
161 result = prime * result + ((to == null) ? 0 : to.hashCode());
166 public boolean equals(Object obj) {
173 if (getClass() != obj.getClass()) {
176 EdgeImpl other = (EdgeImpl) obj;
178 if (other.from != null) {
181 } else if (!from.equals(other.from)) {
185 if (other.to != null) {
188 } else if (!to.equals(other.to)) {