2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com
.intellij
.cyclicDependencies
;
19 import com
.intellij
.util
.graph
.Graph
;
20 import com
.intellij
.util
.ui
.tree
.TreeUtil
;
22 import javax
.swing
.tree
.DefaultMutableTreeNode
;
23 import javax
.swing
.tree
.DefaultTreeModel
;
24 import javax
.swing
.tree
.TreeModel
;
25 import javax
.swing
.tree
.TreeNode
;
33 public class ShortestPathUtil
<Node
> {
34 private final HashSet
<Node
> myVisited
;
35 private final Set
<ProcessingNode
> myProcessingNodes
;
37 private DefaultTreeModel myShortestPathTree
;
39 private final Graph
<Node
> myGraph
;
41 public ShortestPathUtil(Graph
<Node
> graph
) {
42 myVisited
= new HashSet
<Node
>();
43 myProcessingNodes
= new HashSet
<ProcessingNode
>();
47 public List
<Node
> getShortestPath(Node from
, Node to
) {
48 ArrayList
<Node
> result
= new ArrayList
<Node
>();
49 if (myShortestPathTree
== null || ((DefaultMutableTreeNode
)myShortestPathTree
.getRoot()).getUserObject() != from
) {
52 final boolean flag
= traverse(to
, result
);
53 return flag ? result
: null;
56 private boolean traverse(Node to
, List
<Node
> path
){
57 DefaultMutableTreeNode treeNode
= findNodeByUserObject(to
);
58 if (treeNode
== null){
61 while (treeNode
!= null){
62 path
.add((Node
)treeNode
.getUserObject());
63 treeNode
= (DefaultMutableTreeNode
)treeNode
.getParent();
69 private TreeModel
shortestPath(Node from
) {
70 myShortestPathTree
= new DefaultTreeModel(new DefaultMutableTreeNode(from
));
72 myProcessingNodes
.add(new ProcessingNode(null, from
, 0));
74 while (!myProcessingNodes
.isEmpty()) {
79 myProcessingNodes
.clear();
81 return myShortestPathTree
;
84 private DefaultMutableTreeNode
findNodeByUserObject(final Node nodeToFind
){
85 final ArrayList
<DefaultMutableTreeNode
> parent
= new ArrayList
<DefaultMutableTreeNode
>();
86 TreeUtil
.traverseDepth((TreeNode
)myShortestPathTree
.getRoot(), new TreeUtil
.Traverse() {
87 public boolean accept(Object node
) {
88 final DefaultMutableTreeNode treeNode
= ((DefaultMutableTreeNode
)node
);
89 if (treeNode
.getUserObject() != null && treeNode
.getUserObject().equals(nodeToFind
)) {
96 return parent
.size() > 0 ? parent
.get(0) : null;
99 private void moveToVisited() {
100 ProcessingNode priorityNode
= null;
101 for (Iterator
<ProcessingNode
> iterator
= myProcessingNodes
.iterator(); iterator
.hasNext();) {
102 ProcessingNode processingNode
= iterator
.next();
103 if (priorityNode
!= null) {
104 if (priorityNode
.getPriority() > processingNode
.getPriority()) {
105 priorityNode
= processingNode
;
109 priorityNode
= processingNode
;
112 myProcessingNodes
.remove(priorityNode
);
113 myVisited
.add(priorityNode
.myToNode
);
114 if (priorityNode
.myFromNode
!= null) {
115 final DefaultMutableTreeNode parentNode
= findNodeByUserObject(priorityNode
.myFromNode
);
116 if (parentNode
!= null){
117 myShortestPathTree
.insertNodeInto(new DefaultMutableTreeNode(priorityNode
.myToNode
), parentNode
, 0);
120 moveAdjacentVerticesToProcessing(priorityNode
);
123 private void moveAdjacentVerticesToProcessing(ProcessingNode priorityNode
) {
124 Node fromNode
= priorityNode
.getToNode();
125 int priority
= priorityNode
.getPriority();
126 Iterator
<Node
> iterator
= myGraph
.getIn(fromNode
);
128 while (iterator
.hasNext()) {
129 toNode
= iterator
.next();
130 if (myVisited
.contains(toNode
)){
133 final ProcessingNode processingNode
= getProcessingNodeByFromNode(toNode
);
134 if (processingNode
== null) {
135 myProcessingNodes
.add(new ProcessingNode(fromNode
, toNode
, priority
+ 1));
138 if (processingNode
.getPriority() > priority
+ 1) {
139 processingNode
.setPriority(priority
+ 1);
140 processingNode
.setFromNode(fromNode
);
146 private ProcessingNode
getProcessingNodeByFromNode(Node fromNode
) {
147 for (Iterator
<ProcessingNode
> iterator
= myProcessingNodes
.iterator(); iterator
.hasNext();) {
148 ProcessingNode processingNode
= iterator
.next();
149 if (processingNode
.getFromNode() == fromNode
) {
150 return processingNode
;
158 private class ProcessingNode
{
159 private Node myFromNode
;
160 private Node myToNode
;
161 private int myPriority
;
163 public ProcessingNode(final Node fromNode
, final Node toNode
, final int priority
) {
164 myFromNode
= fromNode
;
166 myPriority
= priority
;
169 public Node
getFromNode() {
173 public Node
getToNode() {
177 public int getPriority() {
181 public void setPriority(final int priority
) {
182 myPriority
= priority
;
185 public void setFromNode(final Node fromNode
) {
186 myFromNode
= fromNode
;
189 public void setToNode(final Node toNode
) {