blob: fa8695c5c8bf1e73e15335be25129bb1c67620d8 [file] [log] [blame]
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.util.graph.impl;
import com.intellij.util.graph.Graph;
import org.jetbrains.annotations.NotNull;
import java.util.*;
/**
* User: anna
* Date: Feb 13, 2005
*/
public class CycleFinder<Node> {
private final Graph<Node> myGraph;
public CycleFinder(Graph<Node> graph) {
myGraph = graph;
}
@NotNull
public Set<List<Node>> getNodeCycles(final Node node){
final Set<List<Node>> result = new HashSet<List<Node>>();
final Graph<Node> graphWithoutNode = new Graph<Node>() {
public Collection<Node> getNodes() {
final Collection<Node> nodes = myGraph.getNodes();
nodes.remove(node);
return nodes;
}
public Iterator<Node> getIn(final Node n) {
final HashSet<Node> nodes = new HashSet<Node>();
final Iterator<Node> in = myGraph.getIn(n);
while (in.hasNext()) {
nodes.add(in.next());
}
nodes.remove(node);
return nodes.iterator();
}
public Iterator<Node> getOut(final Node n) {
final HashSet<Node> nodes = new HashSet<Node>();
final Iterator<Node> out = myGraph.getOut(n);
while (out.hasNext()) {
nodes.add(out.next());
}
nodes.remove(node);
return nodes.iterator();
}
};
final HashSet<Node> inNodes = new HashSet<Node>();
final Iterator<Node> in = myGraph.getIn(node);
while (in.hasNext()) {
inNodes.add(in.next());
}
final HashSet<Node> outNodes = new HashSet<Node>();
final Iterator<Node> out = myGraph.getOut(node);
while (out.hasNext()) {
outNodes.add(out.next());
}
final HashSet<Node> retainNodes = new HashSet<Node>(inNodes);
retainNodes.retainAll(outNodes);
for (Node node1 : retainNodes) {
ArrayList<Node> oneNodeCycle = new ArrayList<Node>();
oneNodeCycle.add(node1);
oneNodeCycle.add(node);
result.add(oneNodeCycle);
}
inNodes.removeAll(retainNodes);
outNodes.removeAll(retainNodes);
ShortestPathFinder<Node> finder = new ShortestPathFinder<Node>(graphWithoutNode);
for (Node fromNode : outNodes) {
for (Node toNode : inNodes) {
final List<Node> shortestPath = finder.findPath(fromNode, toNode);
if (shortestPath != null) {
ArrayList<Node> path = new ArrayList<Node>();
path.addAll(shortestPath);
path.add(node);
result.add(path);
}
}
}
return result;
}
}