1 25 45 package org.jgrapht.traverse; 46 47 import java.util.*; 48 49 import org.jgrapht.*; 50 import org.jgrapht.event.*; 51 52 53 64 public abstract class CrossComponentIterator<V, E, D> 65 extends AbstractGraphIterator<V, E> 66 { 67 68 70 private static final int CCS_BEFORE_COMPONENT = 1; 71 private static final int CCS_WITHIN_COMPONENT = 2; 72 private static final int CCS_AFTER_COMPONENT = 3; 73 74 76 private final ConnectedComponentTraversalEvent ccFinishedEvent = 78 new ConnectedComponentTraversalEvent( 79 this, 80 ConnectedComponentTraversalEvent.CONNECTED_COMPONENT_FINISHED); 81 private final ConnectedComponentTraversalEvent ccStartedEvent = 82 new ConnectedComponentTraversalEvent( 83 this, 84 ConnectedComponentTraversalEvent.CONNECTED_COMPONENT_STARTED); 85 86 private FlyweightEdgeEvent<V, E> reusableEdgeEvent; 89 private FlyweightVertexEvent<V> reusableVertexEvent; 90 private Iterator<V> vertexIterator = null; 91 92 96 private Map<V, D> seen = new HashMap<V, D>(); 97 private V startVertex; 98 private Specifics<V, E> specifics; 99 100 private final Graph<V, E> graph; 101 102 105 private int state = CCS_BEFORE_COMPONENT; 106 107 109 120 public CrossComponentIterator(Graph<V, E> g, V startVertex) 121 { 122 super(); 123 124 if (g == null) { 125 throw new IllegalArgumentException ("graph must not be null"); 126 } 127 graph = g; 128 129 specifics = createGraphSpecifics(g); 130 vertexIterator = g.vertexSet().iterator(); 131 setCrossComponentTraversal(startVertex == null); 132 133 reusableEdgeEvent = new FlyweightEdgeEvent<V, E>(this, null); 134 reusableVertexEvent = new FlyweightVertexEvent<V>(this, null); 135 136 if (startVertex == null) { 137 if (vertexIterator.hasNext()) { 139 this.startVertex = vertexIterator.next(); 140 } else { 141 this.startVertex = null; 142 } 143 } else if (g.containsVertex(startVertex)) { 144 this.startVertex = startVertex; 145 } else { 146 throw new IllegalArgumentException ( 147 "graph must contain the start vertex"); 148 } 149 } 150 151 153 156 public Graph<V, E> getGraph() 157 { 158 return graph; 159 } 160 161 164 public boolean hasNext() 165 { 166 if (startVertex != null) { 167 encounterStartVertex(); 168 } 169 170 if (isConnectedComponentExhausted()) { 171 if (state == CCS_WITHIN_COMPONENT) { 172 state = CCS_AFTER_COMPONENT; 173 fireConnectedComponentFinished(ccFinishedEvent); 174 } 175 176 if (isCrossComponentTraversal()) { 177 while (vertexIterator.hasNext()) { 178 V v = vertexIterator.next(); 179 180 if (!isSeenVertex(v)) { 181 encounterVertex(v, null); 182 state = CCS_BEFORE_COMPONENT; 183 184 return true; 185 } 186 } 187 188 return false; 189 } else { 190 return false; 191 } 192 } else { 193 return true; 194 } 195 } 196 197 200 public V next() 201 { 202 if (startVertex != null) { 203 encounterStartVertex(); 204 } 205 206 if (hasNext()) { 207 if (state == CCS_BEFORE_COMPONENT) { 208 state = CCS_WITHIN_COMPONENT; 209 fireConnectedComponentStarted(ccStartedEvent); 210 } 211 212 V nextVertex = provideNextVertex(); 213 fireVertexTraversed(createVertexTraversalEvent(nextVertex)); 214 215 addUnseenChildrenOf(nextVertex); 216 217 return nextVertex; 218 } else { 219 throw new NoSuchElementException(); 220 } 221 } 222 223 230 protected abstract boolean isConnectedComponentExhausted(); 231 232 239 protected abstract void encounterVertex(V vertex, E edge); 240 241 247 protected abstract V provideNextVertex(); 248 249 259 protected D getSeenData(V vertex) 260 { 261 return seen.get(vertex); 262 } 263 264 271 protected boolean isSeenVertex(Object vertex) 272 { 273 return seen.containsKey(vertex); 274 } 275 276 283 protected abstract void encounterVertexAgain(V vertex, E edge); 284 285 296 protected D putSeenData(V vertex, D data) 297 { 298 return seen.put(vertex, data); 299 } 300 301 309 static <V, E> Specifics<V, E> createGraphSpecifics(Graph<V, E> g) 310 { 311 if (g instanceof DirectedGraph) { 312 return new DirectedSpecifics<V, E>((DirectedGraph<V, E>) g); 313 } else { 314 return new UndirectedSpecifics<V, E>(g); 315 } 316 } 317 318 private void addUnseenChildrenOf(V vertex) 319 { 320 for (E edge : specifics.edgesOf(vertex)) { 321 fireEdgeTraversed(createEdgeTraversalEvent(edge)); 322 323 V oppositeV = Graphs.getOppositeVertex(graph, edge, vertex); 324 325 if (isSeenVertex(oppositeV)) { 326 encounterVertexAgain(oppositeV, edge); 327 } else { 328 encounterVertex(oppositeV, edge); 329 } 330 } 331 } 332 333 private EdgeTraversalEvent<V, E> createEdgeTraversalEvent(E edge) 334 { 335 if (isReuseEvents()) { 336 reusableEdgeEvent.setEdge(edge); 337 338 return reusableEdgeEvent; 339 } else { 340 return new EdgeTraversalEvent<V, E>(this, edge); 341 } 342 } 343 344 private VertexTraversalEvent<V> createVertexTraversalEvent(V vertex) 345 { 346 if (isReuseEvents()) { 347 reusableVertexEvent.setVertex(vertex); 348 349 return reusableVertexEvent; 350 } else { 351 return new VertexTraversalEvent<V>(this, vertex); 352 } 353 } 354 355 private void encounterStartVertex() 356 { 357 encounterVertex(startVertex, null); 358 startVertex = null; 359 } 360 361 363 static interface SimpleContainer<T> 364 { 365 370 public boolean isEmpty(); 371 372 377 public void add(T o); 378 379 384 public T remove(); 385 } 386 387 389 393 abstract static class Specifics<VV, EE> 394 { 395 406 public abstract Set<? extends EE> edgesOf(VV vertex); 407 } 408 409 415 static class FlyweightEdgeEvent<VV, localE> 416 extends EdgeTraversalEvent<VV, localE> 417 { 418 private static final long serialVersionUID = 4051327833765000755L; 419 420 423 public FlyweightEdgeEvent(Object eventSource, localE edge) 424 { 425 super(eventSource, edge); 426 } 427 428 433 protected void setEdge(localE edge) 434 { 435 this.edge = edge; 436 } 437 } 438 439 445 static class FlyweightVertexEvent<VV> 446 extends VertexTraversalEvent<VV> 447 { 448 private static final long serialVersionUID = 3834024753848399924L; 449 450 453 public FlyweightVertexEvent(Object eventSource, VV vertex) 454 { 455 super(eventSource, vertex); 456 } 457 458 463 protected void setVertex(VV vertex) 464 { 465 this.vertex = vertex; 466 } 467 } 468 469 472 private static class DirectedSpecifics<VV, EE> 473 extends Specifics<VV, EE> 474 { 475 private DirectedGraph<VV, EE> graph; 476 477 482 public DirectedSpecifics(DirectedGraph<VV, EE> g) 483 { 484 graph = g; 485 } 486 487 490 public Set<? extends EE> edgesOf(VV vertex) 491 { 492 return graph.outgoingEdgesOf(vertex); 493 } 494 } 495 496 500 private static class UndirectedSpecifics<VV, EE> 501 extends Specifics<VV, EE> 502 { 503 private Graph<VV, EE> graph; 504 505 510 public UndirectedSpecifics(Graph<VV, EE> g) 511 { 512 graph = g; 513 } 514 515 518 public Set<EE> edgesOf(VV vertex) 519 { 520 return graph.edgesOf(vertex); 521 } 522 } 523 } 524
| Popular Tags
|