1 11 12 package org.eclipse.core.internal.resources; 13 14 import java.util.*; 15 import org.eclipse.core.resources.IProject; 16 import org.eclipse.core.resources.IWorkspace; 17 18 24 class ComputeProjectOrder { 25 26 29 private ComputeProjectOrder() { 30 } 32 33 42 private static class Digraph { 43 47 public static class Vertex { 48 51 public static final String WHITE = "white"; 53 57 public static final String GREY = "grey"; 59 62 public static final String BLACK = "black"; 64 69 public String color = WHITE; 70 71 75 public Vertex predecessor = null; 76 77 82 public int finishTime; 83 84 87 public Object id; 88 89 96 public List adjacent = new ArrayList(3); 97 98 103 public Vertex(Object id) { 104 this.id = id; 105 } 106 } 107 108 113 private List vertexList = new ArrayList(100); 114 115 120 private Map vertexMap = new HashMap(100); 121 122 125 private int time; 126 127 131 private boolean initialized = false; 132 133 137 private boolean cycles = false; 138 139 149 public Digraph() { 150 super(); 151 } 152 153 158 public void freeze() { 159 if (!initialized) { 160 initialized = true; 161 DFS(); 163 } 164 } 165 166 175 public void addVertex(Object id) throws IllegalArgumentException { 176 if (initialized) { 177 throw new IllegalArgumentException (); 178 } 179 Vertex vertex = new Vertex(id); 180 Object existing = vertexMap.put(id, vertex); 181 if (existing != null) { 183 throw new IllegalArgumentException (); 184 } 185 vertexList.add(vertex); 186 } 187 188 200 public void addEdge(Object fromId, Object toId) throws IllegalArgumentException { 201 if (initialized) { 202 throw new IllegalArgumentException (); 203 } 204 Vertex fromVertex = (Vertex) vertexMap.get(fromId); 205 Vertex toVertex = (Vertex) vertexMap.get(toId); 206 if (fromVertex == null) { 208 throw new IllegalArgumentException (); 209 } 210 if (toVertex == null) { 211 throw new IllegalArgumentException (); 212 } 213 fromVertex.adjacent.add(toVertex); 214 } 215 216 228 public List idsByDFSFinishTime(boolean increasing) { 229 if (!initialized) { 230 throw new IllegalArgumentException (); 231 } 232 int len = vertexList.size(); 233 Object [] r = new Object [len]; 234 for (Iterator allV = vertexList.iterator(); allV.hasNext();) { 235 Vertex vertex = (Vertex) allV.next(); 236 int f = vertex.finishTime; 237 if (increasing) { 239 r[f - 1] = vertex.id; 240 } else { 241 r[len - f] = vertex.id; 242 } 243 } 244 return Arrays.asList(r); 245 } 246 247 254 public boolean containsCycles() { 255 if (!initialized) { 256 throw new IllegalArgumentException (); 257 } 258 return cycles; 259 } 260 261 271 public List nonTrivialComponents() { 272 if (!initialized) { 273 throw new IllegalArgumentException (); 274 } 275 Map components = new HashMap(); 278 for (Iterator it = vertexList.iterator(); it.hasNext();) { 279 Vertex vertex = (Vertex) it.next(); 280 if (vertex.predecessor == null) { 281 } else { 284 Vertex root = vertex; 286 while (root.predecessor != null) { 287 root = root.predecessor; 288 } 289 List component = (List) components.get(root); 290 if (component == null) { 291 component = new ArrayList(2); 292 component.add(root.id); 293 components.put(root, component); 294 } 295 component.add(vertex.id); 296 } 297 } 298 List result = new ArrayList(components.size()); 299 for (Iterator it = components.values().iterator(); it.hasNext();) { 300 List component = (List) it.next(); 301 if (component.size() > 1) { 302 result.add(component.toArray()); 303 } 304 } 305 return result; 306 } 307 308 356 361 private void DFS() { 362 int state; 364 final int NEXT_VERTEX = 1; 365 final int START_DFS_VISIT = 2; 366 final int NEXT_ADJACENT = 3; 367 final int AFTER_NEXTED_DFS_VISIT = 4; 368 final Integer NEXT_VERTEX_OBJECT = new Integer (NEXT_VERTEX); 370 final Integer AFTER_NEXTED_DFS_VISIT_OBJECT = new Integer (AFTER_NEXTED_DFS_VISIT); 371 time = 0; 375 List stack = new ArrayList(Math.max(1, vertexList.size())); 377 Iterator allAdjacent = null; 378 Vertex vertex = null; 379 Iterator allV = vertexList.iterator(); 380 state = NEXT_VERTEX; 381 nextStateLoop: while (true) { 382 switch (state) { 383 case NEXT_VERTEX : 384 if (!allV.hasNext()) { 386 break nextStateLoop; 388 } 389 Vertex nextVertex = (Vertex) allV.next(); 390 if (nextVertex.color == Vertex.WHITE) { 391 stack.add(NEXT_VERTEX_OBJECT); 392 vertex = nextVertex; 393 state = START_DFS_VISIT; 394 continue nextStateLoop; 395 } 396 state = NEXT_VERTEX; 398 continue nextStateLoop; 399 case START_DFS_VISIT : 400 vertex.color = Vertex.GREY; 404 allAdjacent = vertex.adjacent.iterator(); 405 state = NEXT_ADJACENT; 406 continue nextStateLoop; 407 case NEXT_ADJACENT : 408 if (allAdjacent.hasNext()) { 411 Vertex adjVertex = (Vertex) allAdjacent.next(); 412 if (adjVertex.color == Vertex.WHITE) { 413 adjVertex.predecessor = vertex; 415 stack.add(allAdjacent); 416 stack.add(vertex); 417 stack.add(AFTER_NEXTED_DFS_VISIT_OBJECT); 418 vertex = adjVertex; 419 state = START_DFS_VISIT; 420 continue nextStateLoop; 421 } 422 if (adjVertex.color == Vertex.GREY) { 423 cycles = true; 425 } 426 state = NEXT_ADJACENT; 427 continue nextStateLoop; 428 } 429 vertex.color = Vertex.BLACK; 431 time++; 432 vertex.finishTime = time; 433 state = ((Integer ) stack.remove(stack.size() - 1)).intValue(); 434 continue nextStateLoop; 435 case AFTER_NEXTED_DFS_VISIT : 436 vertex = (Vertex) stack.remove(stack.size() - 1); 438 allAdjacent = (Iterator) stack.remove(stack.size() - 1); 439 state = NEXT_ADJACENT; 440 continue nextStateLoop; 441 } 442 } 443 } 444 445 } 446 447 473 static IWorkspace.ProjectOrder computeProjectOrder(SortedSet projects, List references) { 474 475 final Digraph g1 = new Digraph(); 477 for (Iterator it = projects.iterator(); it.hasNext();) { 479 IProject project = (IProject) it.next(); 480 g1.addVertex(project); 481 } 482 for (Iterator it = references.iterator(); it.hasNext();) { 484 IProject[] ref = (IProject[]) it.next(); 485 IProject p = ref[0]; 486 IProject q = ref[1]; 487 g1.addEdge(q, p); 491 } 492 g1.freeze(); 493 494 final Digraph g2 = new Digraph(); 498 List resortedVertexes = g1.idsByDFSFinishTime(false); 500 for (Iterator it = resortedVertexes.iterator(); it.hasNext();) { 501 final IProject project = (IProject) it.next(); 502 g2.addVertex(project); 503 } 504 for (Iterator it = references.iterator(); it.hasNext();) { 506 IProject[] ref = (IProject[]) it.next(); 507 IProject p = ref[0]; 508 IProject q = ref[1]; 509 g2.addEdge(p, q); 513 } 514 g2.freeze(); 515 516 List sortedProjectList = g2.idsByDFSFinishTime(true); 519 IProject[] orderedProjects = new IProject[sortedProjectList.size()]; 520 sortedProjectList.toArray(orderedProjects); 521 IProject[][] knots; 522 boolean hasCycles = g2.containsCycles(); 523 if (hasCycles) { 524 List knotList = g2.nonTrivialComponents(); 525 knots = new IProject[knotList.size()][]; 526 int k = 0; 529 for (Iterator it = knotList.iterator(); it.hasNext();) { 530 Object [] knot = (Object []) it.next(); 531 IProject[] knotCopy = new IProject[knot.length]; 532 for (int i = 0; i < knot.length; i++) { 533 knotCopy[i] = (IProject) knot[i]; 534 } 535 knots[k] = knotCopy; 536 k++; 537 } 538 } else { 539 knots = new IProject[][] {}; 540 } 541 return new IWorkspace.ProjectOrder(orderedProjects, hasCycles, knots); 542 } 543 } 544 | Popular Tags |