1 11 12 package org.eclipse.osgi.internal.resolver; 13 14 import java.util.*; 15 16 25 public class ComputeNodeOrder { 26 27 30 private ComputeNodeOrder() { 31 } 33 34 43 private static class Digraph { 44 48 public static class Vertex { 49 52 public static final String WHITE = "white"; 54 58 public static final String GREY = "grey"; 60 63 public static final String BLACK = "black"; 65 70 public String color = WHITE; 71 72 76 public Vertex predecessor = null; 77 78 83 public int finishTime; 84 85 88 public Object id; 89 90 97 public List adjacent = new ArrayList(3); 98 99 104 public Vertex(Object id) { 105 this.id = id; 106 } 107 } 108 109 114 private List vertexList = new ArrayList(100); 115 116 121 private Map vertexMap = new HashMap(100); 122 123 126 private int time; 127 128 132 private boolean initialized = false; 133 134 138 private boolean cycles = false; 139 140 150 public Digraph() { 151 super(); 152 } 153 154 159 public void freeze() { 160 if (!initialized) { 161 initialized = true; 162 DFS(); 164 } 165 } 166 167 176 public void addVertex(Object id) throws IllegalArgumentException { 177 if (initialized) { 178 throw new IllegalArgumentException (); 179 } 180 Vertex vertex = new Vertex(id); 181 Object existing = vertexMap.put(id, vertex); 182 if (existing != null) { 184 throw new IllegalArgumentException (); 185 } 186 vertexList.add(vertex); 187 } 188 189 201 public void addEdge(Object fromId, Object toId) throws IllegalArgumentException { 202 if (initialized) { 203 throw new IllegalArgumentException (); 204 } 205 Vertex fromVertex = (Vertex) vertexMap.get(fromId); 206 Vertex toVertex = (Vertex) vertexMap.get(toId); 207 if (fromVertex == null || toVertex == null) 209 return; 210 fromVertex.adjacent.add(toVertex); 211 } 212 213 225 public List idsByDFSFinishTime(boolean increasing) { 226 if (!initialized) { 227 throw new IllegalArgumentException (); 228 } 229 int len = vertexList.size(); 230 Object [] r = new Object [len]; 231 for (Iterator allV = vertexList.iterator(); allV.hasNext();) { 232 Vertex vertex = (Vertex) allV.next(); 233 int f = vertex.finishTime; 234 if (increasing) { 236 r[f - 1] = vertex.id; 237 } else { 238 r[len - f] = vertex.id; 239 } 240 } 241 return Arrays.asList(r); 242 } 243 244 251 public boolean containsCycles() { 252 if (!initialized) { 253 throw new IllegalArgumentException (); 254 } 255 return cycles; 256 } 257 258 268 public List nonTrivialComponents() { 269 if (!initialized) { 270 throw new IllegalArgumentException (); 271 } 272 Map components = new HashMap(); 275 for (Iterator it = vertexList.iterator(); it.hasNext();) { 276 Vertex vertex = (Vertex) it.next(); 277 if (vertex.predecessor == null) { 278 } else { 281 Vertex root = vertex; 283 while (root.predecessor != null) { 284 root = root.predecessor; 285 } 286 List component = (List) components.get(root); 287 if (component == null) { 288 component = new ArrayList(2); 289 component.add(root.id); 290 components.put(root, component); 291 } 292 component.add(vertex.id); 293 } 294 } 295 List result = new ArrayList(components.size()); 296 for (Iterator it = components.values().iterator(); it.hasNext();) { 297 List component = (List) it.next(); 298 if (component.size() > 1) { 299 result.add(component.toArray()); 300 } 301 } 302 return result; 303 } 304 305 353 358 private void DFS() { 359 int state; 361 final int NEXT_VERTEX = 1; 362 final int START_DFS_VISIT = 2; 363 final int NEXT_ADJACENT = 3; 364 final int AFTER_NEXTED_DFS_VISIT = 4; 365 final Integer NEXT_VERTEX_OBJECT = new Integer (NEXT_VERTEX); 367 final Integer AFTER_NEXTED_DFS_VISIT_OBJECT = new Integer (AFTER_NEXTED_DFS_VISIT); 368 time = 0; 372 List stack = new ArrayList(Math.max(1, vertexList.size())); 374 Iterator allAdjacent = null; 375 Vertex vertex = null; 376 Iterator allV = vertexList.iterator(); 377 state = NEXT_VERTEX; 378 nextStateLoop: while (true) { 379 switch (state) { 380 case NEXT_VERTEX : 381 if (!allV.hasNext()) { 383 break nextStateLoop; 385 } 386 Vertex nextVertex = (Vertex) allV.next(); 387 if (nextVertex.color == Vertex.WHITE) { 388 stack.add(NEXT_VERTEX_OBJECT); 389 vertex = nextVertex; 390 state = START_DFS_VISIT; 391 continue nextStateLoop; 392 } else { 393 state = NEXT_VERTEX; 394 continue nextStateLoop; 395 } 396 case START_DFS_VISIT : 397 vertex.color = Vertex.GREY; 401 allAdjacent = vertex.adjacent.iterator(); 402 state = NEXT_ADJACENT; 403 continue nextStateLoop; 404 case NEXT_ADJACENT : 405 if (allAdjacent.hasNext()) { 408 Vertex adjVertex = (Vertex) allAdjacent.next(); 409 if (adjVertex.color == Vertex.WHITE) { 410 adjVertex.predecessor = vertex; 412 stack.add(allAdjacent); 413 stack.add(vertex); 414 stack.add(AFTER_NEXTED_DFS_VISIT_OBJECT); 415 vertex = adjVertex; 416 state = START_DFS_VISIT; 417 continue nextStateLoop; 418 } 419 if (adjVertex.color == Vertex.GREY) { 420 cycles = true; 422 } 423 state = NEXT_ADJACENT; 424 continue nextStateLoop; 425 } else { 426 vertex.color = Vertex.BLACK; 428 time++; 429 vertex.finishTime = time; 430 state = ((Integer ) stack.remove(stack.size() - 1)).intValue(); 431 continue nextStateLoop; 432 } 433 case AFTER_NEXTED_DFS_VISIT : 434 vertex = (Vertex) stack.remove(stack.size() - 1); 436 allAdjacent = (Iterator) stack.remove(stack.size() - 1); 437 state = NEXT_ADJACENT; 438 continue nextStateLoop; 439 } 440 } 441 } 442 443 } 444 445 471 public static Object [][] computeNodeOrder(Object [] objects, Object [][] references) { 472 473 final Digraph g1 = new Digraph(); 475 for (int i = 0; i < objects.length; i++) 477 g1.addVertex(objects[i]); 478 for (int i = 0; i < references.length; i++) 480 g1.addEdge(references[i][1], references[i][0]); 483 g1.freeze(); 484 485 final Digraph g2 = new Digraph(); 489 List resortedVertexes = g1.idsByDFSFinishTime(false); 491 for (Iterator it = resortedVertexes.iterator(); it.hasNext();) 492 g2.addVertex(it.next()); 493 for (int i = 0; i < references.length; i++) 495 g2.addEdge(references[i][0], references[i][1]); 496 g2.freeze(); 497 498 List sortedProjectList = g2.idsByDFSFinishTime(true); 501 Object [] orderedNodes = new Object [sortedProjectList.size()]; 502 sortedProjectList.toArray(orderedNodes); 503 Object [][] knots; 504 boolean hasCycles = g2.containsCycles(); 505 if (hasCycles) { 506 List knotList = g2.nonTrivialComponents(); 507 knots = (Object [][]) knotList.toArray(new Object [knotList.size()][]); 508 } else { 509 knots = new Object [0][]; 510 } 511 for (int i = 0; i < orderedNodes.length; i++) 512 objects[i] = orderedNodes[i]; 513 return knots; 514 } 515 } 516 | Popular Tags |