1 | /* |
2 | * $Id: Traversers.java 594 2010-11-19 20:41:04Z PSpeed $ |
3 | * |
4 | * The Filament BSD license. |
5 | * |
6 | * Copyright (c) 2009-2010, the original author or authors |
7 | * |
8 | * Redistribution and use in source and binary forms, with or without |
9 | * modification, are permitted provided that the following conditions |
10 | * are met: |
11 | * |
12 | * 1) Redistributions of source code must retain the above copyright notice, |
13 | * this list of conditions and the following disclaimer. |
14 | * 2) Redistributions in binary form must reproduce the above copyright |
15 | * notice, this list of conditions and the following disclaimer in the |
16 | * documentation and/or other materials provided with the distribution. |
17 | * 3) Neither the names "Filament", "fgraph.org", "filamentgraph.org", nor the |
18 | * names of its contributors may be used to endorse or promote products |
19 | * derived from this software without specific prior written permission. |
20 | * |
21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
25 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
31 | * POSSIBILITY OF SUCH DAMAGE. |
32 | */ |
33 | |
34 | package org.fgraph.steps; |
35 | |
36 | import java.util.*; |
37 | |
38 | import com.google.common.base.Function; |
39 | import com.google.common.base.Predicate; |
40 | import com.google.common.collect.Iterables; |
41 | import com.google.common.collect.Iterators; |
42 | |
43 | |
44 | /** |
45 | * Factory methods for creating traverser Iterables. |
46 | * |
47 | * @version $Revision: 594 $ |
48 | * @author Paul Speed |
49 | */ |
50 | public class Traversers |
51 | { |
52 | /** |
53 | * Creates an Iterable that performs a pre-order depth-first |
54 | * traversal starting at a specified node and using the specified |
55 | * adjacency function for traversal. |
56 | * |
57 | * <p>If an optional visitMarker function is provided then the |
58 | * traversal is acyclic based on the 'marker' returned from that |
59 | * function. For example, a Functions.identity() visit marker |
60 | * will make sure a node is only visited once based on its own |
61 | * .equals() implementation. A null indicates that no cycle |
62 | * detection should be performed.</p> |
63 | */ |
64 | public static <T> Iterable<T> preOrder( T start, Function<T,? extends Iterable<T>> fstep, |
65 | Function<? super T,? extends Object> visitMarker ) |
66 | { |
67 | Iterable<DepthFirstStep<T>> pre = preOrderSteps( start, fstep, visitMarker ); |
68 | return Iterables.transform( pre, StepFunctions.<T>unwrapStep() ); |
69 | } |
70 | |
71 | /** |
72 | * Creates a function that performs a pre-order depth-first |
73 | * traversal starting at a specified node and using the specified |
74 | * adjacency function for traversal, also providing additional |
75 | * control over and information about the ongoing traversal. |
76 | * |
77 | * <p>This is similar to the non-step based version except that |
78 | * the traversed values are returned wrapped in DepthFirstStep |
79 | * objects that provide additional information about the state |
80 | * of the traversal such as depth. These steps also allow themselves |
81 | * to be 'pruned', resulting in any potential descendants being ignored |
82 | * during the subsequent traverses.</p> |
83 | * |
84 | * <p>If an optional visitMarker function is provided then the |
85 | * traversal is acyclic based on the 'marker' returned from that |
86 | * function. For example, a Functions.identity() visit marker |
87 | * will make sure a node is only visited once based on its own |
88 | * .equals() implementation. A null indicates that no cycle |
89 | * detection should be performed.</p> |
90 | */ |
91 | public static <T> Iterable<DepthFirstStep<T>> preOrderSteps( T start, |
92 | Function<T,? extends Iterable<T>> fstep, |
93 | Function<? super T,? extends Object> visitMarker ) |
94 | { |
95 | Iterable<DepthFirstStep<T>> depth = depthFirstSteps(start, fstep, visitMarker); |
96 | return Iterables.filter( depth, StepPredicates.<T>descending() ); |
97 | } |
98 | |
99 | /** |
100 | * Creates a function that performs a post-order depth-first |
101 | * traversal starting at a specified node and using the specified |
102 | * adjacency function for traversal. |
103 | * |
104 | * <p>If an optional visitMarker function is provided then the |
105 | * traversal is acyclic based on the 'marker' returned from that |
106 | * function. For example, a Functions.identity() visit marker |
107 | * will make sure a node is only visited once based on its own |
108 | * .equals() implementation. A null indicates that no cycle |
109 | * detection should be performed.</p> |
110 | */ |
111 | public static <T> Iterable<T> postOrder( T start, Function<T,? extends Iterable<T>> fstep, |
112 | Function<? super T,? extends Object> visitMarker ) |
113 | { |
114 | Iterable<DepthFirstStep<T>> post = postOrderSteps( start, fstep, visitMarker ); |
115 | return Iterables.transform( post, StepFunctions.<T>unwrapStep() ); |
116 | } |
117 | |
118 | /** |
119 | * Creates a function that performs a post-order depth-first |
120 | * traversal starting at a specified node and using the specified |
121 | * adjacency function for traversal, also providing additional |
122 | * control over and information about the ongoing traversal. |
123 | * |
124 | * <p>This is similar to the non-step based version except that |
125 | * the traversed values are returned wrapped in DepthFirstStep |
126 | * objects that provide additional information about the state |
127 | * of the traversal such as depth. These steps also allow themselves |
128 | * to be 'pruned', resulting in any potential descendants being ignored |
129 | * during the subsequent traverses.</p> |
130 | * |
131 | * <p>If an optional visitMarker function is provided then the |
132 | * traversal is acyclic based on the 'marker' returned from that |
133 | * function. For example, a Functions.identity() visit marker |
134 | * will make sure a node is only visited once based on its own |
135 | * .equals() implementation. A null indicates that no cycle |
136 | * detection should be performed.</p> |
137 | */ |
138 | public static <T> Iterable<DepthFirstStep<T>> postOrderSteps( T start, |
139 | Function<T,? extends Iterable<T>> fstep, |
140 | Function<? super T,? extends Object> visitMarker ) |
141 | { |
142 | Iterable<DepthFirstStep<T>> depth = depthFirstSteps( start, fstep, visitMarker ); |
143 | return Iterables.filter( depth, StepPredicates.<T>ascending() ); |
144 | } |
145 | |
146 | /** |
147 | * Creates a function that performs a full depth-first |
148 | * traversal (both pre- and post-) starting at a specified node |
149 | * and using the specified adjacency function for traversal. |
150 | * Every 'node' will therefore be visited twice, once descending |
151 | * and once ascending. Use the step-based depthFirstSteps() |
152 | * method to distinguish descending from ascending. |
153 | * |
154 | * <p>If an optional visitMarker function is provided then the |
155 | * traversal is acyclic based on the 'marker' returned from that |
156 | * function. For example, a Functions.identity() visit marker |
157 | * will make sure a node is only visited once based on its own |
158 | * .equals() implementation. A null indicates that no cycle |
159 | * detection should be performed.</p> |
160 | */ |
161 | public static <T> Iterable<T> depthFirst( T start, Function<T,? extends Iterable<T>> fstep, |
162 | Function<? super T,? extends Object> visitMarker ) |
163 | { |
164 | Iterable<DepthFirstStep<T>> depth = depthFirstSteps( start, fstep, visitMarker ); |
165 | return Iterables.transform( depth, StepFunctions.<T>unwrapStep() ); |
166 | } |
167 | |
168 | /** |
169 | * Creates a function that performs a full depth-first |
170 | * traversal (both pre- and post-) starting at a specified node |
171 | * and using the specified adjacency function for traversal, |
172 | * also providing additional control over and information about |
173 | * the ongoing traversal. |
174 | * |
175 | * <p>This is similar to the non-step based version except that |
176 | * the traversed values are returned wrapped in DepthFirstStep |
177 | * objects that provide additional information about the state |
178 | * of the traversal such as depth, descending/ascending, etc. |
179 | * These steps also allow themselves to be 'pruned', resulting |
180 | * in any potential descendants being ignored during the subsequent |
181 | * traverses.</p> |
182 | * |
183 | * <p>If an optional visitMarker function is provided then the |
184 | * traversal is acyclic based on the 'marker' returned from that |
185 | * function. For example, a Functions.identity() visit marker |
186 | * will make sure a node is only visited once based on its own |
187 | * .equals() implementation. A null indicates that no cycle |
188 | * detection should be performed.</p> |
189 | */ |
190 | public static <T> Iterable<DepthFirstStep<T>> depthFirstSteps( T start, |
191 | Function<T,? extends Iterable<T>> fstep, |
192 | Function<? super T,? extends Object> visitMarker ) |
193 | { |
194 | return new DepthFirstIterable<T>( start, fstep, visitMarker ); |
195 | } |
196 | |
197 | /** |
198 | * Creates a function that performs a breadth-first |
199 | * traversal starting at a specified node and using the specified |
200 | * adjacency function for traversal. |
201 | * |
202 | * <p>If an optional visitMarker function is provided then the |
203 | * traversal is acyclic based on the 'marker' returned from that |
204 | * function. For example, a Functions.identity() visit marker |
205 | * will make sure a node is only visited once based on its own |
206 | * .equals() implementation. A null indicates that no cycle |
207 | * detection should be performed.</p> |
208 | */ |
209 | public static <T> Iterable<T> breadthFirst( T start, Function<T,? extends Iterable<T>> fstep, |
210 | Function<? super T,? extends Object> visitMarker ) |
211 | { |
212 | Iterable<PrunableStep<T>> breadth = breadthFirstSteps(start, fstep, visitMarker); |
213 | return Iterables.transform( breadth, StepFunctions.<T>unwrapStep() ); |
214 | } |
215 | |
216 | /** |
217 | * Creates a function that performs a breadth-first |
218 | * traversal starting at a specified node and using the specified |
219 | * adjacency function for traversal, also providing additional |
220 | * control over and information about the ongoing traversal. |
221 | * |
222 | * <p>This is similar to the non-step based version except that |
223 | * the traversed values are returned wrapped in PrunableStep |
224 | * objects that provide additional information about the state |
225 | * of the traversal such as depth. These steps also allow themselves |
226 | * to be 'pruned', resulting in any potential descendants being ignored |
227 | * during the subsequent traverses.</p> |
228 | * |
229 | * <p>If an optional visitMarker function is provided then the |
230 | * traversal is acyclic based on the 'marker' returned from that |
231 | * function. For example, a Functions.identity() visit marker |
232 | * will make sure a node is only visited once based on its own |
233 | * .equals() implementation. A null indicates that no cycle |
234 | * detection should be performed.</p> |
235 | */ |
236 | public static <T> Iterable<PrunableStep<T>> breadthFirstSteps( T start, |
237 | Function<T,? extends Iterable<T>> fstep, |
238 | Function<? super T,? extends Object> visitMarker ) |
239 | { |
240 | return new BreadthFirstIterable<T>( start, fstep, visitMarker ); |
241 | } |
242 | |
243 | /** |
244 | * Creates a function that performs a priority-ordered |
245 | * traversal starting at a specified node and using the specified |
246 | * adjacency function for traversal. |
247 | * |
248 | * <p>The priority comparator is used to select the next step/path |
249 | * from the current pending set of descendants. For example, a |
250 | * comparator could be based to select the smallest/shortest route |
251 | * based on the sum of the accumulated weights/distances up to that step.</p> |
252 | * |
253 | * <p>If an optional visitMarker function is provided then the |
254 | * traversal is acyclic based on the 'marker' returned from that |
255 | * function. For example, a Functions.identity() visit marker |
256 | * will make sure a node is only visited once based on its own |
257 | * .equals() implementation. A null indicates that no cycle |
258 | * detection should be performed.</p> |
259 | */ |
260 | public static <T> Iterable<T> priority( T start, Function<T,? extends Iterable<T>> fstep, |
261 | Comparator<? super T> priority, |
262 | Function<? super T,? extends Object> visitMarker ) |
263 | { |
264 | Iterable<PrunableStep<T>> pri = prioritySteps( start, fstep, priority, visitMarker ); |
265 | return Iterables.transform( pri, StepFunctions.<T>unwrapStep() ); |
266 | } |
267 | |
268 | /** |
269 | * Creates a function that performs a priority-ordered |
270 | * traversal starting at a specified node and using the specified |
271 | * adjacency function for traversal, also providing additional |
272 | * control over and information about the ongoing traversal. |
273 | * |
274 | * <p>The priority comparator is used to select the next step/path |
275 | * from the current pending set of descendants. For example, a |
276 | * comparator could be based to select the smallest/shortest route |
277 | * based on the sum of the accumulated weights/distances up to that step.</p> |
278 | * |
279 | * <p>This is similar to the non-step based version except that |
280 | * the traversed values are returned wrapped in PrunableStep |
281 | * objects that provide additional information about the state |
282 | * of the traversal such as depth. These steps also allow themselves |
283 | * to be 'pruned', resulting in any potential descendants being ignored |
284 | * during the subsequent traverses. Note: for traversals that branch |
285 | * quickly, pruning a step may be a non-trivial amount of work since |
286 | * it must exhaustively search the current sorted pending steps to |
287 | * remove any queued descendants.</p> |
288 | * |
289 | * <p>If an optional visitMarker function is provided then the |
290 | * traversal is acyclic based on the 'marker' returned from that |
291 | * function. For example, a Functions.identity() visit marker |
292 | * will make sure a node is only visited once based on its own |
293 | * .equals() implementation. A null indicates that no cycle |
294 | * detection should be performed.</p> |
295 | */ |
296 | public static <T> Iterable<PrunableStep<T>> prioritySteps( T start, |
297 | Function<T,? extends Iterable<T>> fstep, |
298 | Comparator<? super T> priority, |
299 | Function<? super T,? extends Object> visitMarker ) |
300 | { |
301 | return new PriorityTraverseIterable<T>( start, fstep, priority, visitMarker ); |
302 | } |
303 | |
304 | /** |
305 | * Method used internally to wrap an adjacency function in a |
306 | * stateful function that tracks visits using the specified |
307 | * visit marker function. |
308 | */ |
309 | protected static <T> StepFunction<T,T> distinct( Function<T,? extends Iterable<T>> fstep, |
310 | Function<? super T,? extends Object> visitMarker ) |
311 | { |
312 | return new DistinctStepFunction<T>( visitMarker, fstep ); |
313 | } |
314 | |
315 | /** |
316 | * Internal implementation of Iterable that delegates |
317 | * to the abstract stepIterator() method. |
318 | */ |
319 | protected static abstract class StepIterable<S,T> implements Iterable<T> |
320 | { |
321 | private S start; |
322 | |
323 | /** |
324 | * Constructs an iterable that simply delegates |
325 | * to the stepIterator() method. |
326 | */ |
327 | public StepIterable( S start ) |
328 | { |
329 | this.start = start; |
330 | } |
331 | |
332 | protected S getStart() |
333 | { |
334 | return start; |
335 | } |
336 | |
337 | protected abstract Iterator<T> stepIterator( S start ); |
338 | |
339 | /** |
340 | * {@inheritDoc} |
341 | */ |
342 | public Iterator<T> iterator() |
343 | { |
344 | return stepIterator(start); |
345 | } |
346 | } |
347 | |
348 | private static class DepthFirstIterable<T> extends StepIterable<T,DepthFirstStep<T>> |
349 | { |
350 | private Function<T,? extends Iterable<T>> fstep; |
351 | private Function<? super T,? extends Object> visitMarker; |
352 | |
353 | public DepthFirstIterable( T start, Function<T,? extends Iterable<T>> fstep, |
354 | Function<? super T,? extends Object> visitMarker ) |
355 | { |
356 | super( start ); |
357 | this.fstep = fstep; |
358 | this.visitMarker = visitMarker; |
359 | } |
360 | |
361 | protected Iterator<DepthFirstStep<T>> stepIterator( T start ) |
362 | { |
363 | if( visitMarker != null ) |
364 | return new DepthFirstTraverser<T>( start, distinct( fstep, visitMarker ) ); |
365 | return new DepthFirstTraverser<T>( start, fstep ); |
366 | } |
367 | |
368 | public String toString() |
369 | { |
370 | return "DepthFirstIterable[start=" + getStart() |
371 | + ", delegate=" + fstep |
372 | + ", visitMarker=" + visitMarker + "]"; |
373 | } |
374 | } |
375 | |
376 | /** |
377 | * Function implementation that creates breadth first iterators on demand. |
378 | */ |
379 | private static class BreadthFirstIterable<T> extends StepIterable<T,PrunableStep<T>> |
380 | { |
381 | private Function<T,? extends Iterable<T>> fstep; |
382 | private Function<? super T,? extends Object> visitMarker; |
383 | |
384 | public BreadthFirstIterable( T start, Function<T,? extends Iterable<T>> fstep, |
385 | Function<? super T,? extends Object> visitMarker ) |
386 | { |
387 | super( start ); |
388 | this.fstep = fstep; |
389 | this.visitMarker = visitMarker; |
390 | } |
391 | |
392 | protected Iterator<PrunableStep<T>> stepIterator( T start ) |
393 | { |
394 | if( visitMarker != null ) |
395 | return new BreadthFirstTraverser<T>( start, distinct( fstep, visitMarker ) ); |
396 | return new BreadthFirstTraverser<T>( start, fstep ); |
397 | } |
398 | |
399 | public String toString() |
400 | { |
401 | return "BreadthFirstIterable[start=" + getStart() |
402 | + ", delegate=" + fstep |
403 | + ", visitMarker=" + visitMarker + "]"; |
404 | } |
405 | } |
406 | |
407 | /** |
408 | * Function implementation that creates priority first iterators on demand. |
409 | */ |
410 | private static class PriorityTraverseIterable<T> extends StepIterable<T,PrunableStep<T>> |
411 | { |
412 | private Function<T,? extends Iterable<T>> fstep; |
413 | private Comparator<? super T> priority; |
414 | private Function<? super T,? extends Object> visitMarker; |
415 | |
416 | public PriorityTraverseIterable( T start, Function<T,? extends Iterable<T>> fstep, |
417 | Comparator<? super T> priority, |
418 | Function<? super T,? extends Object> visitMarker ) |
419 | { |
420 | super( start ); |
421 | this.fstep = fstep; |
422 | this.priority = priority; |
423 | this.visitMarker = visitMarker; |
424 | } |
425 | |
426 | protected Iterator<PrunableStep<T>> stepIterator( T start ) |
427 | { |
428 | if( visitMarker != null ) |
429 | return new PriorityTraverser<T>( start, distinct( fstep, visitMarker ), priority ); |
430 | return new PriorityTraverser<T>( start, fstep, priority ); |
431 | } |
432 | |
433 | public String toString() |
434 | { |
435 | return "PriorityTraverseIterable[start=" + getStart() |
436 | + ", delegate=" + fstep |
437 | + ", priority=" + priority |
438 | + ", visitMarker=" + visitMarker + "]"; |
439 | } |
440 | } |
441 | |
442 | /** |
443 | * Stateful predicate returns true for newly encountered |
444 | * items and adds them to an internal set. A marker function |
445 | * is used to translate raw values into visit-tracking |
446 | * markers. |
447 | */ |
448 | private static class IsNewObject<T> implements Predicate<T> |
449 | { |
450 | private Set<Object> visited = new HashSet<Object>(); |
451 | private Function<? super T,? extends Object> visitMarker; |
452 | |
453 | public IsNewObject( Function<? super T,? extends Object> visitMarker ) |
454 | { |
455 | this.visitMarker = visitMarker; |
456 | } |
457 | |
458 | public boolean apply( T value ) |
459 | { |
460 | Object marker = visitMarker.apply(value); |
461 | return visited.add(marker); |
462 | } |
463 | } |
464 | |
465 | /** |
466 | * Stateful function for returning only distinct |
467 | * values. |
468 | */ |
469 | private static class DistinctStepFunction<T> implements StepFunction<T,T> |
470 | { |
471 | private IsNewObject<T> newObject; |
472 | private Function<T, ? extends Iterable<T>> delegate; |
473 | |
474 | public DistinctStepFunction( Function<? super T,? extends Object> visitMarker, |
475 | Function<T, ? extends Iterable<T>> delegate ) |
476 | { |
477 | this.newObject = new IsNewObject<T>(visitMarker); |
478 | this.delegate = delegate; |
479 | } |
480 | |
481 | public Iterable<T> apply( T value ) |
482 | { |
483 | newObject.apply( value ); |
484 | return Iterables.filter( delegate.apply( value ), newObject ); |
485 | } |
486 | } |
487 | |
488 | /** |
489 | * PrunableStep implementation that has reference back to its creating |
490 | * Traverser for pruning. Internally this keeps track of some data |
491 | * structures useful to the traverser implementations. |
492 | */ |
493 | private static class TraversalStep<T> implements PrunableStep<T> |
494 | { |
495 | private Traverser traverser; |
496 | private Step parent; |
497 | private int depth; |
498 | private T node; |
499 | |
500 | public TraversalStep( Traverser traverser, Step parent, T node ) |
501 | { |
502 | this.traverser = traverser; |
503 | this.parent = parent; |
504 | this.node = node; |
505 | if( parent == null ) |
506 | depth = 0; |
507 | else |
508 | depth = parent.getDepth() + 1; |
509 | } |
510 | |
511 | public T getValue() |
512 | { |
513 | return node; |
514 | } |
515 | |
516 | public int getDepth() |
517 | { |
518 | return depth; |
519 | } |
520 | |
521 | public Step getParent() |
522 | { |
523 | return parent; |
524 | } |
525 | |
526 | public void prune() |
527 | { |
528 | traverser.prune(this); |
529 | } |
530 | |
531 | public String toString() |
532 | { |
533 | return getClass().getSimpleName() + "[" + node + ", " + depth + "]"; |
534 | } |
535 | } |
536 | |
537 | /** |
538 | * Depth first specific step implementation. |
539 | */ |
540 | private static class DfsStep<T> extends TraversalStep<T> |
541 | implements DepthFirstStep<T> |
542 | { |
543 | private Iterator<T> it; |
544 | private int descending = -1; |
545 | |
546 | public DfsStep( Traverser traverser, DfsStep<T> parent, T node ) |
547 | { |
548 | super( traverser, parent, node ); |
549 | } |
550 | |
551 | protected Iterator<T> iterator() |
552 | { |
553 | return it; |
554 | } |
555 | |
556 | protected void setIterator( Iterator<T> it ) |
557 | { |
558 | this.it = it; |
559 | } |
560 | |
561 | protected int descending() |
562 | { |
563 | return descending; |
564 | } |
565 | |
566 | protected void setDescending( int descending ) |
567 | { |
568 | this.descending = descending; |
569 | } |
570 | |
571 | public boolean isDescending() |
572 | { |
573 | return descending <= 0; |
574 | } |
575 | |
576 | public String toString() |
577 | { |
578 | return getClass().getSimpleName() + "[" + getValue() + ", " + getDepth() |
579 | + ", " + isDescending() + "]"; |
580 | } |
581 | } |
582 | |
583 | /** |
584 | * Base class for the various traverser iterator implementations. |
585 | * Exposes an abstract prune() that the specific implementations |
586 | * must implement. |
587 | */ |
588 | protected abstract static class Traverser<T> implements Iterator<T> |
589 | { |
590 | /** |
591 | * Implemented by the specific traversers to provide |
592 | * implementation specific pruning. |
593 | */ |
594 | protected abstract void prune( PrunableStep step ); |
595 | } |
596 | |
597 | /** |
598 | * The depth-first stateful traversal implementation. |
599 | */ |
600 | private static class DepthFirstTraverser<T> extends Traverser<DepthFirstStep<T>> |
601 | { |
602 | private T start; |
603 | private Function<T,? extends Iterable<T>> fstep; |
604 | private LinkedList<DfsStep<T>> stack = new LinkedList<DfsStep<T>>(); |
605 | |
606 | public DepthFirstTraverser( T start, Function<T,? extends Iterable<T>> fstep ) |
607 | { |
608 | this.start = start; |
609 | this.fstep = fstep; |
610 | stack.addFirst( new DfsStep<T>(this, null, start) ); |
611 | } |
612 | |
613 | protected void prune( PrunableStep step ) |
614 | { |
615 | // For now, we'll only support pruning the current level... |
616 | // though there's not a strong reason not to support multi-level |
617 | // pruning it just seems a little dangerous. |
618 | if( stack.getFirst() != step ) |
619 | throw new IllegalStateException( "Pruned step is not current." ); |
620 | |
621 | // Otherwise, just remove it |
622 | stack.removeFirst(); |
623 | } |
624 | |
625 | public boolean hasNext() |
626 | { |
627 | // Since we remove the last item when we're done |
628 | // then this is enough of a check... since |
629 | // even an item with no children is returned on |
630 | // exit (and then removed). |
631 | return !stack.isEmpty(); |
632 | } |
633 | |
634 | public DepthFirstStep<T> next() |
635 | { |
636 | while( true ) |
637 | { |
638 | // See what the state of the top item is |
639 | DfsStep<T> top = stack.getFirst(); |
640 | |
641 | if( top.iterator() == null && top.descending() < 0 ) |
642 | { |
643 | // Mark it as leveling off and we'll create |
644 | // the iterator the next time through |
645 | top.setDescending(0); |
646 | return top; // descending |
647 | } |
648 | else if( top.iterator() == null ) |
649 | { |
650 | top.setIterator( fstep.apply( top.getValue() ).iterator() ); |
651 | } |
652 | |
653 | if( !top.it.hasNext() ) |
654 | { |
655 | // Then we're done with this level |
656 | stack.removeFirst(); |
657 | top.setDescending(1); |
658 | return top; // ascending |
659 | } |
660 | |
661 | // Otherwise, just return the next element in |
662 | // the steps iterator |
663 | T result = top.iterator().next(); |
664 | stack.addFirst( new DfsStep<T>(this, top, result) ); |
665 | } |
666 | } |
667 | |
668 | public void remove() |
669 | { |
670 | throw new UnsupportedOperationException(); |
671 | } |
672 | } |
673 | |
674 | /** |
675 | * The breadth-first stateful traversal implementation. |
676 | */ |
677 | private static class BreadthFirstTraverser<T> extends Traverser<PrunableStep<T>> |
678 | { |
679 | private T start; |
680 | private Function<T,? extends Iterable<T>> fstep; |
681 | private LinkedList<TraversalStep<T>> queue = new LinkedList<TraversalStep<T>>(); |
682 | private TraversalStep<T> parent; |
683 | private Iterator<T> current; |
684 | |
685 | public BreadthFirstTraverser( T start, Function<T,? extends Iterable<T>> fstep ) |
686 | { |
687 | this.start = start; |
688 | this.fstep = fstep; |
689 | parent = null; |
690 | current = Iterators.singletonIterator(start); |
691 | } |
692 | |
693 | protected void prune( PrunableStep step ) |
694 | { |
695 | // In this implementation of breadth-first traveral, |
696 | // when the current value has been returned, the |
697 | // step is added to the end of the queue and it's |
698 | // from there that we should remove it. |
699 | if( queue.getLast() != step ) |
700 | throw new IllegalStateException( "Pruned step is not current." ); |
701 | queue.removeLast(); |
702 | } |
703 | |
704 | public boolean hasNext() |
705 | { |
706 | if( current.hasNext() ) |
707 | return true; |
708 | |
709 | while( !queue.isEmpty() ) |
710 | { |
711 | parent = queue.removeFirst(); |
712 | current = fstep.apply( parent.node ).iterator(); |
713 | if( current.hasNext() ) |
714 | return true; |
715 | } |
716 | |
717 | return false; |
718 | } |
719 | |
720 | public PrunableStep<T> next() |
721 | { |
722 | if( !hasNext() ) |
723 | throw new NoSuchElementException(); |
724 | |
725 | // At this point we are guaranteed to have a current |
726 | // iterator with stuff still in it. |
727 | T next = current.next(); |
728 | TraversalStep<T> result = new TraversalStep<T>(this, parent, next); |
729 | queue.addLast( result ); |
730 | |
731 | return result; |
732 | } |
733 | |
734 | public void remove() |
735 | { |
736 | throw new UnsupportedOperationException(); |
737 | } |
738 | } |
739 | |
740 | /** |
741 | * Comparator that can unwrap steps for comparison by a delegate |
742 | * comparator. This is used by the PriorityTraverser to priority |
743 | * sort the pending steps. |
744 | */ |
745 | private static class StepComparator<T> implements Comparator<Step<T>> |
746 | { |
747 | private Comparator<? super T> delegate; |
748 | |
749 | public StepComparator( Comparator<? super T> delegate ) |
750 | { |
751 | this.delegate = delegate; |
752 | } |
753 | |
754 | public int compare( Step<T> s1, Step<T> s2 ) |
755 | { |
756 | return delegate.compare( s1.getValue(), s2.getValue() ); |
757 | } |
758 | } |
759 | |
760 | /** |
761 | * The priority-ordered stateful traversal implementation. |
762 | */ |
763 | private static class PriorityTraverser<T> extends Traverser<PrunableStep<T>> |
764 | { |
765 | private static final int INITIAL_CAPACITY = 11; // the same as PriorityQueue's default |
766 | |
767 | private T start; |
768 | private Function<T,? extends Iterable<T>> fstep; |
769 | private Comparator<? super T> priority; |
770 | |
771 | private PriorityQueue<PrunableStep<T>> pending; |
772 | private PrunableStep<T> last; |
773 | |
774 | public PriorityTraverser( T start, Function<T,? extends Iterable<T>> fstep, |
775 | Comparator<? super T> priority ) |
776 | { |
777 | this.start = start; |
778 | this.fstep = fstep; |
779 | this.priority = priority; |
780 | |
781 | this.pending = new PriorityQueue<PrunableStep<T>>( INITIAL_CAPACITY, |
782 | new StepComparator<T>(priority) ); |
783 | pending.add( new TraversalStep<T>( this, null, start ) ); |
784 | } |
785 | |
786 | protected void addChildren( PrunableStep<T> parent ) |
787 | { |
788 | for( T child : fstep.apply( parent.getValue() ) ) |
789 | { |
790 | pending.add( new TraversalStep<T>( this, parent, child ) ); |
791 | } |
792 | } |
793 | |
794 | protected void prune( PrunableStep step ) |
795 | { |
796 | // If the step isn't the last one returned then |
797 | // we don't allow it. In this case, it really is |
798 | // tricky to implement that. |
799 | if( step != last ) |
800 | throw new IllegalStateException( "Pruned step is not current." ); |
801 | |
802 | // Remove any steps that have the specified step |
803 | // as parent. There is no cheap way to do this |
804 | for( Iterator<PrunableStep<T>> i = pending.iterator(); i.hasNext(); ) |
805 | { |
806 | PrunableStep s = i.next(); |
807 | if( s.getParent() == step ) |
808 | i.remove(); |
809 | } |
810 | } |
811 | |
812 | public boolean hasNext() |
813 | { |
814 | return !pending.isEmpty(); |
815 | } |
816 | |
817 | public PrunableStep<T> next() |
818 | { |
819 | if( !hasNext() ) |
820 | throw new NoSuchElementException(); |
821 | |
822 | // Grab the top of the queue |
823 | last = pending.remove(); |
824 | |
825 | // Fetch any next level steps before returning |
826 | addChildren( last ); |
827 | |
828 | return last; |
829 | } |
830 | |
831 | public void remove() |
832 | { |
833 | throw new UnsupportedOperationException(); |
834 | } |
835 | } |
836 | } |
837 | |