1 | /* |
2 | * $Id: StepDemo.java 562 2010-11-11 00:28:13Z 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.io.File; |
37 | import java.lang.reflect.Method; |
38 | import java.util.*; |
39 | |
40 | import com.google.common.base.Function; |
41 | import com.google.common.base.Predicate; |
42 | import com.google.common.base.Predicates; |
43 | import com.google.common.collect.Sets; |
44 | |
45 | import org.progeeks.util.Inspector; |
46 | import org.progeeks.util.NanoTimer; |
47 | import org.progeeks.util.log.Log; |
48 | |
49 | |
50 | /** |
51 | * Prototyping some step function related stuff to |
52 | * reimplement a traverser/query model. |
53 | * |
54 | * @version $Revision: 562 $ |
55 | * @author Paul Speed |
56 | */ |
57 | public class StepDemo |
58 | { |
59 | private static final int TEST_DEPTH3 = 3; |
60 | private static final int TEST_DEPTH4 = 4; |
61 | |
62 | private StepFunction<Class,Method> demoMethods; |
63 | |
64 | /** |
65 | * Constructs the test/demo for test calls. |
66 | */ |
67 | public StepDemo() |
68 | { |
69 | // Create a step function that can reflectively |
70 | // return all of the 'demo' Methods on this class. |
71 | |
72 | // Return methods that have a VOID return type |
73 | Predicate<Object> filter = Reflection.propertyEqualTo( "returnType", Void.TYPE ); |
74 | |
75 | // Return methods that have no arguments |
76 | filter = Predicates.and( filter, Reflection.hasParameterTypes() ); |
77 | |
78 | // Return methods for whom the declaring class |
79 | // is us (eliminates the Object declared methods) |
80 | filter = Predicates.and( filter, Reflection.propertyEqualTo( "declaringClass", getClass() ) ); |
81 | |
82 | demoMethods = StepFunctions.filter( Reflection.methods(), filter ); |
83 | } |
84 | |
85 | /** |
86 | * Demonstrates a single-hop child function. |
87 | */ |
88 | public void dir() |
89 | { |
90 | ChildFiles dir = new ChildFiles(); |
91 | |
92 | int count = 0; |
93 | for( File f : dir.apply( new File("." ) ) ) |
94 | { |
95 | System.out.println( "f:" + f ); |
96 | count++; |
97 | } |
98 | |
99 | System.out.println( "Total files:" + count ); |
100 | } |
101 | |
102 | /** |
103 | * Demonstrates a pre-order depth-first traversal using the child function. |
104 | */ |
105 | public void dirTree() |
106 | { |
107 | ChildFiles dir = new ChildFiles(); |
108 | StepFunction<File,File> dirTree = TraverseFunctions.preOrder( dir, null ); |
109 | |
110 | int count = 0; |
111 | for( File f : dirTree.apply( new File("." ) ) ) |
112 | { |
113 | System.out.println( "f:" + f ); |
114 | count++; |
115 | } |
116 | |
117 | System.out.println( "Total files:" + count ); |
118 | } |
119 | |
120 | /** |
121 | * Demonstrates a pre-order depth-first traversal using the child function |
122 | * and pruning and .svn directories. |
123 | */ |
124 | public void dirTreePruned() |
125 | { |
126 | ChildFiles dir = new ChildFiles(); |
127 | StepFunction<File,DepthFirstStep<File>> dirTree = TraverseFunctions.preOrderSteps( dir, null ); |
128 | |
129 | int count = 0; |
130 | for( PrunableStep<File> step : dirTree.apply( new File("." ) ) ) |
131 | { |
132 | if( ".svn".equals( step.getValue().getName() ) ) |
133 | { |
134 | step.prune(); |
135 | continue; |
136 | } |
137 | |
138 | System.out.println( "f:" + step.getValue() ); |
139 | count++; |
140 | } |
141 | |
142 | System.out.println( "Total files:" + count ); |
143 | } |
144 | |
145 | /** |
146 | * Demonstrates a pre-order depth-first traversal using the child function |
147 | * and filtering the .svn directories instead of pruning them during the |
148 | * loop. |
149 | */ |
150 | public void dirTreeFiltered() |
151 | { |
152 | StepFunction<File,File> dir = new ChildFiles(); |
153 | |
154 | Predicate<Object> isSvn = Reflection.propertyEqualTo( "name", ".svn" ); |
155 | dir = StepFunctions.prune( dir, isSvn ); |
156 | |
157 | StepFunction<File,File> dirTree = TraverseFunctions.preOrder( dir, null ); |
158 | |
159 | int count = 0; |
160 | for( File f : dirTree.apply( new File("." ) ) ) |
161 | { |
162 | System.out.println( "f:" + f ); |
163 | count++; |
164 | } |
165 | |
166 | System.out.println( "Total files:" + count ); |
167 | } |
168 | |
169 | /** |
170 | * Demonstrates a breadth-first traversal using the child function. |
171 | */ |
172 | public void breadthTree() |
173 | { |
174 | ChildFiles dir = new ChildFiles(); |
175 | StepFunction<File,File> dirTree = TraverseFunctions.breadthFirst( dir, null ); |
176 | |
177 | int count = 0; |
178 | for( File f : dirTree.apply( new File("." ) ) ) |
179 | { |
180 | System.out.println( "f:" + f ); |
181 | count++; |
182 | } |
183 | |
184 | System.out.println( "Total files:" + count ); |
185 | } |
186 | |
187 | /** |
188 | * Demonstrates a breadth-first traversal using the child function |
189 | * and pruning and .svn directories. |
190 | */ |
191 | public void breadthTreePruned() |
192 | { |
193 | ChildFiles dir = new ChildFiles(); |
194 | StepFunction<File,PrunableStep<File>> dirTree = TraverseFunctions.breadthFirstSteps( dir, null ); |
195 | |
196 | int count = 0; |
197 | for( PrunableStep<File> step : dirTree.apply( new File("." ) ) ) |
198 | { |
199 | if( ".svn".equals( step.getValue().getName() ) ) |
200 | { |
201 | step.prune(); |
202 | continue; |
203 | } |
204 | |
205 | System.out.println( "f:" + step.getValue() ); |
206 | count++; |
207 | } |
208 | |
209 | System.out.println( "Total files:" + count ); |
210 | } |
211 | |
212 | /** |
213 | * Demonstrates a breadth-first traversal using the child function |
214 | * and filtering the .svn directories instead of pruning them during the |
215 | * loop. |
216 | */ |
217 | public void breadthTreeFiltered() |
218 | { |
219 | StepFunction<File,File> dir = new ChildFiles(); |
220 | |
221 | Predicate<Object> isSvn = Reflection.propertyEqualTo( "name", ".svn" ); |
222 | dir = StepFunctions.prune( dir, isSvn ); |
223 | |
224 | StepFunction<File,File> dirTree = TraverseFunctions.breadthFirst( dir, null ); |
225 | |
226 | int count = 0; |
227 | for( File f : dirTree.apply( new File("." ) ) ) |
228 | { |
229 | System.out.println( "f:" + f ); |
230 | count++; |
231 | } |
232 | |
233 | System.out.println( "Total files:" + count ); |
234 | } |
235 | |
236 | /** |
237 | * Demonstrates a fixed-depth chained traversal, ie: all |
238 | * paths returned will have the same length. |
239 | */ |
240 | public void dirFixedPaths() |
241 | { |
242 | StepFunction<File,File> dir = new ChildFiles(); |
243 | |
244 | StepFunction<File,File> paths = StepFunctions.chain( dir, dir ); |
245 | paths = StepFunctions.chain( paths, dir ); |
246 | |
247 | System.out.println( "All files at depth 3:" ); |
248 | int count = 0; |
249 | for( File f : paths.apply( new File("." ) ) ) |
250 | { |
251 | System.out.println( "f:" + f ); |
252 | count++; |
253 | } |
254 | |
255 | System.out.println( "Total files:" + count ); |
256 | } |
257 | |
258 | /** |
259 | * Demonstrates a composed function that returns all file |
260 | * names in the tree not in .svn directories and uses this |
261 | * to construct a set of unique file names. |
262 | */ |
263 | public void uniqueFileNames() |
264 | { |
265 | StepFunction<File,File> dir = new ChildFiles(); |
266 | |
267 | Predicate<Object> isSvn = Reflection.propertyEqualTo( "name", ".svn" ); |
268 | dir = StepFunctions.prune( dir, isSvn ); |
269 | |
270 | StepFunction<File,File> dirTree = TraverseFunctions.preOrder( dir, null ); |
271 | |
272 | // Now transform into file names |
273 | StepFunction<File,String> names = StepFunctions.transform( dirTree, |
274 | Reflection.<String>property("name") ); |
275 | |
276 | // Turn all of the names into a sorted set |
277 | Set<String> unique = Sets.newTreeSet( names.apply( new File(".") ) ); |
278 | int count = 0; |
279 | for( String s : unique ) |
280 | { |
281 | System.out.println( s ); |
282 | count++; |
283 | } |
284 | System.out.println( "Total names:" + count ); |
285 | } |
286 | |
287 | /** |
288 | * Demonstrates depth-based pruning by doing a directory tree |
289 | * only a certain level deep. |
290 | */ |
291 | public void dirTreeDepthPruned() |
292 | { |
293 | // To do depth-based pruning with a filter, our |
294 | // filter will need to know depth. Therefore, we |
295 | // will use a step-based adjacency function. |
296 | |
297 | // You can use a custom step->step based function |
298 | // or just wrap an existing non-step based function. |
299 | StepFunction<Step<File>,Step<File>> dir = StepFunctions.adaptToSteps( new ChildFiles() ); |
300 | |
301 | // The rest is pretty straight forward, prune |
302 | // everything at depth four |
303 | dir = StepFunctions.prune( dir, StepPredicates.depth(TEST_DEPTH4) ); |
304 | |
305 | // Grab a regular depth first traversal using our step-based |
306 | // function. No need for DepthFirstSteps here. |
307 | StepFunction<Step<File>,Step<File>> dirTreeSteps = TraverseFunctions.preOrder( dir, null ); |
308 | |
309 | // At this point we could use the dirTree function directly |
310 | // but we'd have to pass a Step<File> into the apply() using |
311 | // something like DefaultStep.create()... and then manually |
312 | // unwrap our steps. Instead, we can wrap and unwrap as part |
313 | // of the accumulated function by 'unadapting' it. |
314 | StepFunction<File,File> dirTree = StepFunctions.adaptFromSteps( dirTreeSteps ); |
315 | |
316 | int count = 0; |
317 | for( File f : dirTree.apply( new File("." ) ) ) |
318 | { |
319 | System.out.println( "f:" + f ); |
320 | count++; |
321 | } |
322 | |
323 | System.out.println( "Total files:" + count ); |
324 | |
325 | } |
326 | |
327 | |
328 | /** |
329 | * Tests a full traversal like test2() except this one has |
330 | * a function built into the stack that will convert the raw |
331 | * root file into a root step for the traverser. |
332 | */ |
333 | /*public void test3() |
334 | { |
335 | // Full traversal test with the root adapter |
336 | // build into a chain stack. |
337 | File root = new File("."); |
338 | ChildFileSteps files = new ChildFileSteps(); |
339 | |
340 | StepFunction<File,Step<File>> f1 = StepFunctions.wrapSteps(); |
341 | |
342 | StepFunction<Step<File>,Step<File>> f2 = TraverseFunctions.depthFirst( files, null ); |
343 | |
344 | StepFunction<File,Step<File>> chain = StepFunctions.chain( f1, f2 ); |
345 | |
346 | int count = 0; |
347 | for( Step<File> s : chain.apply( root ) ) |
348 | { |
349 | System.out.println( "s:" + s ); |
350 | count++; |
351 | } |
352 | System.out.println( "Total results:" + count ); |
353 | }*/ |
354 | |
355 | /** |
356 | * Tests a full traversal like test2() and test3() except this |
357 | * one unwraps the results back into File objects instead of |
358 | * Steps. So it's a full traversal from a File that produces |
359 | * Files but intermittently uses Steps for tracking during |
360 | * traversal. |
361 | */ |
362 | /*public void test4() |
363 | { |
364 | // Full traversal test with the root adapter |
365 | // build into a chain stack and an unwrap adapter |
366 | // turning the results back into files. |
367 | File root = new File("."); |
368 | ChildFileSteps files = new ChildFileSteps(); |
369 | |
370 | StepFunction<File,Step<File>> f1 = StepFunctions.wrapSteps(); |
371 | |
372 | StepFunction<Step<File>,Step<File>> f2 = TraverseFunctions.depthFirst( files, null ); |
373 | |
374 | StepFunction<Step<File>,File> f3 = StepFunctions.unwrapSteps(); |
375 | |
376 | StepFunction<File,Step<File>> chain1 = StepFunctions.chain( f1, f2 ); |
377 | StepFunction<File,File> chain2 = StepFunctions.chain( chain1, f3 ); |
378 | |
379 | int count = 0; |
380 | for( File f : chain2.apply( root ) ) |
381 | { |
382 | System.out.println( "f:" + f ); |
383 | count++; |
384 | } |
385 | System.out.println( "Total results:" + count ); |
386 | }*/ |
387 | |
388 | /** |
389 | * Same as test4() except it uses the unwrapSteps() chaining wrapper |
390 | * utility method instead of manually building the unwrapping chain. |
391 | */ |
392 | /* |
393 | public void test5() |
394 | { |
395 | // Full traversal test with the root adapter |
396 | // build into a chain stack and an unwrap adapter |
397 | // turning the results back into files. |
398 | File root = new File("."); |
399 | ChildFileSteps files = new ChildFileSteps(); |
400 | |
401 | StepFunction<File,Step<File>> f1 = StepFunctions.wrapSteps(); |
402 | |
403 | StepFunction<Step<File>,Step<File>> f2 = TraverseFunctions.depthFirst( files, null ); |
404 | |
405 | StepFunction<File,Step<File>> chain1 = StepFunctions.chain( f1, f2 ); |
406 | |
407 | // In this example we use a more natural composition of the |
408 | // unwrap transform |
409 | StepFunction<File,File> f3 = StepFunctions.unwrapSteps( chain1 ); |
410 | |
411 | int count = 0; |
412 | for( File f : f3.apply( root ) ) |
413 | { |
414 | System.out.println( "f:" + f ); |
415 | count++; |
416 | } |
417 | System.out.println( "Total results:" + count ); |
418 | }*/ |
419 | |
420 | /** |
421 | * Tests using the chain function to return a fixed-lenth |
422 | * path of depth 3, ie: it will not 'visit' any of the |
423 | * intermediate depths. |
424 | */ |
425 | /*public void test6() |
426 | { |
427 | // Chain function test... chaining the same |
428 | // function a few times to produce only a specific |
429 | // depth of path. |
430 | File root = new File("."); |
431 | ChildFiles f1 = new ChildFiles(); |
432 | StepFunction<File,File> chain = StepFunctions.chain( f1, f1 ); |
433 | chain = StepFunctions.chain( chain, f1 ); |
434 | |
435 | int count = 0; |
436 | for( File f : chain.apply( root ) ) |
437 | { |
438 | System.out.println( "f:" + f ); |
439 | count++; |
440 | } |
441 | System.out.println( "Total results:" + count ); |
442 | }*/ |
443 | |
444 | /** |
445 | * A full traversal test with a depth 3 post-filter. Unlike test6(), |
446 | * this _will_ 'visit' all of the intermediate depths less than 3. |
447 | * In fact, the full file tree will be traversed but only those |
448 | * files with a depth less than 3 will be 'visited' by the loop. |
449 | */ |
450 | public void test7() |
451 | { |
452 | // Full traversal test with a filter on depth |
453 | File root = new File("."); |
454 | ChildFileSteps files = new ChildFileSteps(); |
455 | |
456 | StepFunction<File,Step<File>> f1 = StepFunctions.wrapSteps(); |
457 | |
458 | StepFunction<Step<File>,Step<File>> f2 = TraverseFunctions.depthFirst( files, null ); |
459 | |
460 | StepFunction<File,Step<File>> chain = StepFunctions.chain( f1, f2 ); |
461 | Predicate<Step<File>> filter = StepPredicates.depth(TEST_DEPTH3); |
462 | StepFunction<File,Step<File>> filtered = StepFunctions.filter( chain, filter ); |
463 | |
464 | int count = 0; |
465 | for( Step<File> s : filtered.apply( root ) ) |
466 | { |
467 | System.out.println( "s:" + s ); |
468 | count++; |
469 | } |
470 | System.out.println( "Total results:" + count ); |
471 | } |
472 | |
473 | /** |
474 | * A full traversal test with a depth 3 prune-filter. This |
475 | * prunes anything with a depth of 3 or more from the traversal |
476 | * such that those paths are never visited, even internally. |
477 | * This is a more efficient 'depth less than 3' traversal than |
478 | * test7() because it does only the work required. |
479 | */ |
480 | /*public void test8() |
481 | { |
482 | // Full traversal test with a filter on depth |
483 | // using the prune function... which pre-filters. |
484 | File root = new File("."); |
485 | ChildFileSteps files = new ChildFileSteps(); |
486 | |
487 | StepFunction<File,Step<File>> f1 = StepFunctions.wrapSteps(); |
488 | |
489 | // The TraverseFunction default behavior requires Steps |
490 | // because of its depth/breadth sorting behavior. |
491 | Predicate<Step<File>> filter = StepPredicates.depth(TEST_DEPTH3); |
492 | StepFunction<Step<File>,Step<File>> f2 |
493 | = TraverseFunctions.depthFirst( StepFunctions.prune(files, filter), null ); |
494 | |
495 | // So the above will only traverse if filter is _NOT_ true. It |
496 | // prunes at filter. |
497 | |
498 | StepFunction<File,Step<File>> chain = StepFunctions.chain( f1, f2 ); |
499 | |
500 | int count = 0; |
501 | for( Step<File> s : chain.apply( root ) ) |
502 | { |
503 | System.out.println( "s:" + s ); |
504 | count++; |
505 | } |
506 | System.out.println( "Total results:" + count ); |
507 | }*/ |
508 | |
509 | /** |
510 | * Tests the distinct traverser on the full file traversal |
511 | * test. As written, this will not produce anything different |
512 | * than other full traversals since the same file is never |
513 | * encountered more than once. |
514 | */ |
515 | /*public void test9() |
516 | { |
517 | // Full traversal test with distinct traversal |
518 | File root = new File("."); |
519 | ChildFileSteps files = new ChildFileSteps(); |
520 | |
521 | // The TraverseFunction default behavior requires Steps |
522 | // because of its depth/breadth sorting behavior... so |
523 | // to properly track visits we unwrap them. |
524 | Function<Step<File>,File> unwrap = StepFunctions.unwrapStep(); |
525 | |
526 | StepFunction<Step<File>,Step<File>> f1 = TraverseFunctions.depthFirst( files, |
527 | unwrap ); |
528 | |
529 | int count = 0; |
530 | for( Step<File> s : f1.apply( DefaultStep.create(null, root) ) ) |
531 | { |
532 | System.out.println( "s:" + s ); |
533 | count++; |
534 | } |
535 | System.out.println( "Total results:" + count ); |
536 | }*/ |
537 | |
538 | /** |
539 | * Tests a fixed depth iteration that adapts a non-Step-based |
540 | * function into a Step-producing function. So, starting with |
541 | * a root File and a function that can produce an Iterable<File> |
542 | * of children for any File, this will produce Step<File> |
543 | * objects whose getParent() path walks all the way back to the |
544 | * root file. |
545 | */ |
546 | /*public void test10() |
547 | { |
548 | // Fixed depth chain using the step adapter |
549 | // support to use the plain ChildFiles function |
550 | File root = new File("."); |
551 | ChildFiles files = new ChildFiles(); |
552 | |
553 | StepFunction<File,Step<File>> f1 = StepFunctions.wrapSteps(); |
554 | StepFunction<Step<File>,Step<File>> f2 = StepFunctions.adaptToSteps( files ); |
555 | |
556 | StepFunction<File,Step<File>> chain = StepFunctions.chain( f1, f2 ); |
557 | chain = StepFunctions.chain( chain, f2 ); |
558 | |
559 | int count = 0; |
560 | for( Step<File> s : chain.apply( root ) ) |
561 | { |
562 | System.out.println( "s:" + s + " ->" + getStepPath(s) ); |
563 | count++; |
564 | } |
565 | System.out.println( "Total results:" + count ); |
566 | }*/ |
567 | |
568 | /** |
569 | * Tests the concatenation function by simulating a depth-two |
570 | * breadth first search by concatenating a depth-one fixed-depth |
571 | * iteration with a depth-two fixed-depth iteration. |
572 | */ |
573 | public void test11() |
574 | { |
575 | // Fixed depth chain using the step adapter |
576 | // support to use the plain ChildFiles function |
577 | // and concatenates the multiple levels into |
578 | // one output... which sort of simulates a breadth |
579 | // first search except its doing twice the work. |
580 | File root = new File("."); |
581 | ChildFiles files = new ChildFiles(); |
582 | |
583 | StepFunction<File,Step<File>> f1 = StepFunctions.wrapSteps(); |
584 | StepFunction<Step<File>,Step<File>> f2 = StepFunctions.adaptToSteps( files ); |
585 | |
586 | StepFunction<File,Step<File>> chain1 = StepFunctions.chain( f1, f2 ); |
587 | StepFunction<File,Step<File>> chain2 = StepFunctions.chain( chain1, f2 ); |
588 | |
589 | StepFunction<File,Step<File>> concat = StepFunctions.concat( chain1, chain2 ); |
590 | |
591 | int count = 0; |
592 | for( Step<File> s : concat.apply( root ) ) |
593 | { |
594 | System.out.println( "s:" + s + " ->" + getStepPath(s) ); |
595 | count++; |
596 | } |
597 | System.out.println( "Total results:" + count ); |
598 | } |
599 | |
600 | /** |
601 | * Tests the distinct traverser on the full file traversal |
602 | * test. This is similar to test9 except that it uses a |
603 | * Reflection.property("name") function to determine if the |
604 | * file has been visited... so a file with a particular name |
605 | * will only show up once in the output. |
606 | */ |
607 | /*public void test12() |
608 | { |
609 | // Full traversal test with distinct traversal |
610 | File root = new File("."); |
611 | ChildFileSteps files = new ChildFileSteps(); |
612 | |
613 | // The TraverseFunction default behavior requires Steps |
614 | // because of its depth/breadth sorting behavior... so |
615 | // to properly track visits we unwrap them. |
616 | Function<Step<File>,File> unwrap = StepFunctions.unwrapStep(); |
617 | Function<Object,String> name = Reflection.property( "name" ); |
618 | Function<Step<File>,String> visitMarker = Functions.compose( name, unwrap ); |
619 | |
620 | StepFunction<Step<File>,Step<File>> f1 = TraverseFunctions.depthFirst( files, |
621 | visitMarker ); |
622 | |
623 | int count = 0; |
624 | for( Step<File> s : f1.apply( DefaultStep.create(null, root) ) ) |
625 | { |
626 | System.out.println( "s:" + s ); |
627 | count++; |
628 | } |
629 | System.out.println( "Total results:" + count ); |
630 | }*/ |
631 | |
632 | /** |
633 | * Tests a full traversal starting from the current directory and |
634 | * using the child file step function. This the same as test2() |
635 | * except that it doesn't take or return Step objects but just uses |
636 | * them internally to manage priority. |
637 | */ |
638 | /*public void test13() |
639 | { |
640 | // Full traversal test |
641 | File root = new File("."); |
642 | ChildFiles files = new ChildFiles(); |
643 | |
644 | StepFunction<File,File> f1 = TraverseFunctions.depthFirst( files, null ); |
645 | |
646 | int count = 0; |
647 | for( File f : f1.apply( root ) ) |
648 | { |
649 | System.out.println( "f:" + f ); |
650 | count++; |
651 | } |
652 | System.out.println( "Total results:" + count ); |
653 | }*/ |
654 | |
655 | |
656 | /** |
657 | * Returns the full path for a File Step by recursively calling its |
658 | * getParent() method. |
659 | */ |
660 | @SuppressWarnings("unchecked") |
661 | public String getStepPath( Step<File> step ) |
662 | { |
663 | if( step.getParent() == null ) |
664 | return step.getValue().getName(); |
665 | |
666 | return getStepPath( step.getParent() ) + "/" + step.getValue().getName(); |
667 | } |
668 | |
669 | /** |
670 | * Lists all available demo commands. |
671 | */ |
672 | public void list() |
673 | { |
674 | for( Method m : demoMethods.apply( getClass() ) ) |
675 | { |
676 | String name = m.getName(); |
677 | System.out.println( m.getName() ); |
678 | } |
679 | } |
680 | |
681 | /** |
682 | * Run all available demo commands... except this one and list(). |
683 | */ |
684 | public void all() |
685 | { |
686 | Function<Object,String> name = Reflection.property( "name" ); |
687 | StepFunction<Class,String> names = StepFunctions.transform( demoMethods, name ); |
688 | Set<String> all = Sets.newTreeSet( names.apply(getClass()) ); |
689 | all.remove( "all" ); |
690 | all.remove( "list" ); |
691 | |
692 | execute( all ); |
693 | } |
694 | |
695 | /** |
696 | * Runs a set of commands in order. |
697 | */ |
698 | public void execute( Iterable<String> commands ) |
699 | { |
700 | NanoTimer timer = new NanoTimer(); |
701 | timer.start(); |
702 | |
703 | Inspector ins = new Inspector(this); |
704 | int count = 0; |
705 | for( String s : commands ) |
706 | { |
707 | System.out.println( "---executing:" + s ); |
708 | ins.callMethod( s ); |
709 | count++; |
710 | } |
711 | timer.stop(); |
712 | |
713 | System.out.println( "Executed " + count + " commands." ); |
714 | System.out.println( "Total execution time:" + timer.getAccumulatedTimeMillis() + " ms" ); |
715 | } |
716 | |
717 | /** |
718 | * Runs the test names that are supplied as arguments and shows |
719 | * the resulting execution time. |
720 | * |
721 | * @throws Exception for any exception that occurs. |
722 | */ |
723 | public static void main( String... args ) throws Exception |
724 | { |
725 | Log.initialize(); |
726 | |
727 | if( args == null || args.length == 0 ) |
728 | { |
729 | System.out.println( "Usage: StepDemo <commands>" ); |
730 | System.out.println( " Use 'list' to list all available commands." ); |
731 | return; |
732 | } |
733 | |
734 | List<String> argList = new ArrayList<String>( Arrays.asList(args) ); |
735 | |
736 | StepDemo demo = new StepDemo(); |
737 | |
738 | demo.execute( Arrays.asList(args) ); |
739 | } |
740 | |
741 | /** |
742 | * A function that produces an Iterable of child Files for |
743 | * a supplied file. |
744 | */ |
745 | public static class ChildFiles implements StepFunction<File, File> |
746 | { |
747 | /** |
748 | * {@inheritDoc} |
749 | */ |
750 | public Iterable<File> apply( File start ) |
751 | { |
752 | File[] files = start.listFiles(); |
753 | if( files == null ) |
754 | return Collections.emptySet(); |
755 | return Arrays.asList(files); |
756 | } |
757 | } |
758 | |
759 | /** |
760 | * A function that produces an Iterable of child File Steps for |
761 | * a supplied File Step. This is technicaly the equivalent of |
762 | * wrapping the ChildFiles function in the function produced by |
763 | * StepFunctions.wrapSteps() but it useful on its own for testing/demoing |
764 | * certain features. |
765 | */ |
766 | public static class ChildFileSteps implements StepFunction<Step<File>, Step<File>> |
767 | { |
768 | /** |
769 | * {@inheritDoc} |
770 | */ |
771 | public Iterable<Step<File>> apply( Step<File> start ) |
772 | { |
773 | File[] files = start.getValue().listFiles(); |
774 | if( files == null ) |
775 | return Collections.emptySet(); |
776 | return StepFunctions.doWrapSteps( start, Arrays.asList(files) ); |
777 | } |
778 | } |
779 | } |
780 | |
781 | |