1 11 12 package org.eclipse.core.internal.dependencies; 13 14 import java.util.*; 15 16 23 public class ComputeNodeOrder { 24 25 34 private static class Digraph { 35 39 public static class Vertex { 40 41 44 public static final String BLACK = "black"; 46 50 public static final String GREY = "grey"; 54 public static final String WHITE = "white"; 56 63 public List adjacent = new ArrayList(3); 64 65 70 public String color = WHITE; 71 72 77 public int finishTime; 78 79 82 public Object id; 83 84 88 public Vertex predecessor = null; 89 90 95 public Vertex(Object id) { 96 this.id = id; 97 } 98 } 99 100 104 private boolean cycles = false; 105 106 110 private boolean initialized = false; 111 112 115 private int time; 116 117 122 private List vertexList = new ArrayList(100); 123 124 129 private Map vertexMap = new HashMap(100); 130 131 141 public Digraph() { 142 } 144 145 157 public void addEdge(Object fromId, Object toId) throws IllegalArgumentException { 158 if (initialized) { 159 throw new IllegalArgumentException (); 160 } 161 Vertex fromVertex = (Vertex) vertexMap.get(fromId); 162 Vertex toVertex = (Vertex) vertexMap.get(toId); 163 if (fromVertex == null) { 165 throw new IllegalArgumentException (); 166 } 167 if (toVertex == null) { 168 throw new IllegalArgumentException (); 169 } 170 fromVertex.adjacent.add(toVertex); 171 } 172 173 182 public void addVertex(Object id) throws IllegalArgumentException { 183 if (initialized) { 184 throw new IllegalArgumentException (); 185 } 186 Vertex vertex = new Vertex(id); 187 Object existing = vertexMap.put(id, vertex); 188 if (existing != null) { 190 throw new IllegalArgumentException (); 191 } 192 vertexList.add(vertex); 193 } 194 195 202 public boolean containsCycles() { 203 if (!initialized) { 204 throw new IllegalArgumentException (); 205 } 206 return cycles; 207 } 208 209 257 262 private void DFS() { 263 int state; 265 final int NEXT_VERTEX = 1; 266 final int START_DFS_VISIT = 2; 267 final int NEXT_ADJACENT = 3; 268 final int AFTER_NEXTED_DFS_VISIT = 4; 269 final Integer NEXT_VERTEX_OBJECT = new Integer (NEXT_VERTEX); 271 final Integer AFTER_NEXTED_DFS_VISIT_OBJECT = new Integer (AFTER_NEXTED_DFS_VISIT); 272 time = 0; 276 List stack = new ArrayList(Math.max(1, vertexList.size())); 278 Iterator allAdjacent = null; 279 Vertex vertex = null; 280 Iterator allV = vertexList.iterator(); 281 state = NEXT_VERTEX; 282 nextStateLoop: while (true) { 283 switch (state) { 284 case NEXT_VERTEX : 285 if (!allV.hasNext()) { 287 break nextStateLoop; 289 } 290 Vertex nextVertex = (Vertex) allV.next(); 291 if (nextVertex.color == Vertex.WHITE) { 292 stack.add(NEXT_VERTEX_OBJECT); 293 vertex = nextVertex; 294 state = START_DFS_VISIT; 295 continue nextStateLoop; 296 } else { 297 state = NEXT_VERTEX; 298 continue nextStateLoop; 299 } 300 case START_DFS_VISIT : 301 vertex.color = Vertex.GREY; 305 allAdjacent = vertex.adjacent.iterator(); 306 state = NEXT_ADJACENT; 307 continue nextStateLoop; 308 case NEXT_ADJACENT : 309 if (allAdjacent.hasNext()) { 312 Vertex adjVertex = (Vertex) allAdjacent.next(); 313 if (adjVertex.color == Vertex.WHITE) { 314 adjVertex.predecessor = vertex; 316 stack.add(allAdjacent); 317 stack.add(vertex); 318 stack.add(AFTER_NEXTED_DFS_VISIT_OBJECT); 319 vertex = adjVertex; 320 state = START_DFS_VISIT; 321 continue nextStateLoop; 322 } 323 if (adjVertex.color == Vertex.GREY) { 324 cycles = true; 326 } 327 state = NEXT_ADJACENT; 328 continue nextStateLoop; 329 } else { 330 vertex.color = Vertex.BLACK; 332 time++; 333 vertex.finishTime = time; 334 state = ((Integer ) stack.remove(stack.size() - 1)).intValue(); 335 continue nextStateLoop; 336 } 337 case AFTER_NEXTED_DFS_VISIT : 338 vertex = (Vertex) stack.remove(stack.size() - 1); 340 allAdjacent = (Iterator) stack.remove(stack.size() - 1); 341 state = NEXT_ADJACENT; 342 continue nextStateLoop; 343 } 344 } 345 } 346 347 352 public void freeze() { 353 if (!initialized) { 354 initialized = true; 355 DFS(); 357 } 358 } 359 360 372 public List idsByDFSFinishTime(boolean increasing) { 373 if (!initialized) { 374 throw new IllegalArgumentException (); 375 } 376 int len = vertexList.size(); 377 Object [] r = new Object [len]; 378 for (Iterator allV = vertexList.iterator(); allV.hasNext();) { 379 Vertex vertex = (Vertex) allV.next(); 380 int f = vertex.finishTime; 381 if (increasing) { 383 r[f - 1] = vertex.id; 384 } else { 385 r[len - f] = vertex.id; 386 } 387 } 388 return Arrays.asList(r); 389 } 390 391 401 public List nonTrivialComponents() { 402 if (!initialized) { 403 throw new IllegalArgumentException (); 404 } 405 Map components = new HashMap(); 408 for (Iterator it = vertexList.iterator(); it.hasNext();) { 409 Vertex vertex = (Vertex) it.next(); 410 if (vertex.predecessor == null) { 411 } else { 414 Vertex root = vertex; 416 while (root.predecessor != null) { 417 root = root.predecessor; 418 } 419 List component = (List) components.get(root); 420 if (component == null) { 421 component = new ArrayList(2); 422 component.add(root.id); 423 components.put(root, component); 424 } 425 component.add(vertex.id); 426 } 427 } 428 List result = new ArrayList(components.size()); 429 for (Iterator it = components.values().iterator(); it.hasNext();) { 430 List component = (List) it.next(); 431 if (component.size() > 1) { 432 result.add(component.toArray()); 433 } 434 } 435 return result; 436 } 437 438 } 439 440 466 public static Object [][] computeNodeOrder(Object [] objects, Object [][] references) { 467 468 final Digraph g1 = new Digraph(); 470 for (int i = 0; i < objects.length; i++) 472 g1.addVertex(objects[i]); 473 for (int i = 0; i < references.length; i++) 475 g1.addEdge(references[i][1], references[i][0]); 478 g1.freeze(); 479 480 final Digraph g2 = new Digraph(); 484 List resortedVertexes = g1.idsByDFSFinishTime(false); 486 for (Iterator it = resortedVertexes.iterator(); it.hasNext();) 487 g2.addVertex(it.next()); 488 for (int i = 0; i < references.length; i++) 490 g2.addEdge(references[i][0], references[i][1]); 491 g2.freeze(); 492 493 List sortedProjectList = g2.idsByDFSFinishTime(true); 496 Object [] orderedNodes = new Object [sortedProjectList.size()]; 497 sortedProjectList.toArray(orderedNodes); 498 Object [][] knots; 499 boolean hasCycles = g2.containsCycles(); 500 if (hasCycles) { 501 List knotList = g2.nonTrivialComponents(); 502 knots = (Object [][]) knotList.toArray(new Object [knotList.size()][]); 503 } else { 504 knots = new Object [0][]; 505 } 506 for (int i = 0; i < orderedNodes.length; i++) 507 objects[i] = orderedNodes[i]; 508 return knots; 509 } 510 511 private ComputeNodeOrder() { 512 } 514 } | Popular Tags |