// Path: src/main/java/bbejeck/nio/files/visitor/FunctionVisitor.java
// public class FunctionVisitor extends SimpleFileVisitor<Path> {
//     
//     Function<Path,FileVisitResult> pathFunction;
// 
//     public FunctionVisitor(Function<Path, FileVisitResult> pathFunction) {
//         this.pathFunction = pathFunction;
//     }
// 
//     @Override
//     public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
//         return pathFunction.apply(file);
//     }
// }
// 
// Path: src/main/java/bbejeck/nio/util/FilterBuilder.java
// public class FilterBuilder {
//     
//     private FilterBuilder() {}
//     
//     public static DirectoryStream.Filter<Path> buildGlobFilter(String pattern) {
//         final PathMatcher pathMatcher = getPathMatcher("glob:"+pattern);
//         return new DirectoryStream.Filter<Path>() {
//             @Override
//             public boolean accept(Path entry) throws IOException {
//                 return pathMatcher.matches(entry);
//             }
//         };
//     }
// 
//     public static DirectoryStream.Filter<Path> buildRegexFilter(String pattern) {
//         final PathMatcher pathMatcher = getPathMatcher("regex:"+pattern);
//         return new DirectoryStream.Filter<Path>() {
//             @Override
//             public boolean accept(Path entry) throws IOException {
//                 return pathMatcher.matches(entry);
//             }
//         };
//     }
//     
//     
//     private static PathMatcher getPathMatcher(String pattern) {
//         return FileSystems.getDefault().getPathMatcher(pattern);
//     }
// 
// }


import bbejeck.nio.files.visitor.FunctionVisitor;
import bbejeck.nio.util.FilterBuilder;
import com.google.common.base.Function;
import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Iterator;
import java.util.Objects;
import java.util.concurrent.*;
            @Override
            public boolean hasNext() {
                try {
                    path = pathsBlockingQueue.poll();
                    while (!pathTask.isDone() && path == null) {
                        path = pathsBlockingQueue.poll(5, TimeUnit.MILLISECONDS);
                    }
                    return (path != null);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
                return false;
            }

            @Override
            public Path next() {
                return path;
            }

            @Override
            public void remove() {
                throw new UnsupportedOperationException("Removal not supported");
            }
        };
    }

    private void findFiles(final Path startPath, final Filter filter) {
        pathTask = new FutureTask<>(new Callable<Void>() {
            @Override
            public Void call() throws Exception {
// Path: src/main/java/bbejeck/nio/files/visitor/FunctionVisitor.java
// public class FunctionVisitor extends SimpleFileVisitor<Path> {
//     
//     Function<Path,FileVisitResult> pathFunction;
// 
//     public FunctionVisitor(Function<Path, FileVisitResult> pathFunction) {
//         this.pathFunction = pathFunction;
//     }
// 
//     @Override
//     public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
//         return pathFunction.apply(file);
//     }
// }
// 
// Path: src/main/java/bbejeck/nio/util/FilterBuilder.java
// public class FilterBuilder {
//     
//     private FilterBuilder() {}
//     
//     public static DirectoryStream.Filter<Path> buildGlobFilter(String pattern) {
//         final PathMatcher pathMatcher = getPathMatcher("glob:"+pattern);
//         return new DirectoryStream.Filter<Path>() {
//             @Override
//             public boolean accept(Path entry) throws IOException {
//                 return pathMatcher.matches(entry);
//             }
//         };
//     }
// 
//     public static DirectoryStream.Filter<Path> buildRegexFilter(String pattern) {
//         final PathMatcher pathMatcher = getPathMatcher("regex:"+pattern);
//         return new DirectoryStream.Filter<Path>() {
//             @Override
//             public boolean accept(Path entry) throws IOException {
//                 return pathMatcher.matches(entry);
//             }
//         };
//     }
//     
//     
//     private static PathMatcher getPathMatcher(String pattern) {
//         return FileSystems.getDefault().getPathMatcher(pattern);
//     }
// 
// }


// Path: src/main/java/bbejeck/nio/files/directory/AsynchronousRecursiveDirectoryStream.java
import bbejeck.nio.files.visitor.FunctionVisitor;
import bbejeck.nio.util.FilterBuilder;
import com.google.common.base.Function;
import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Iterator;
import java.util.Objects;
import java.util.concurrent.*;

            @Override
            public boolean hasNext() {
                try {
                    path = pathsBlockingQueue.poll();
                    while (!pathTask.isDone() && path == null) {
                        path = pathsBlockingQueue.poll(5, TimeUnit.MILLISECONDS);
                    }
                    return (path != null);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
                return false;
            }

            @Override
            public Path next() {
                return path;
            }

            @Override
            public void remove() {
                throw new UnsupportedOperationException("Removal not supported");
            }
        };
    }

    private void findFiles(final Path startPath, final Filter filter) {
        pathTask = new FutureTask<>(new Callable<Void>() {
            @Override
            public Void call() throws Exception {
                Files.walkFileTree(startPath, new FunctionVisitor(getFunction(filter)));