Mohit Kanwar
Mohit Kanwar

Reputation: 3050

Dynamic filter chaining Java 8

I have a code like

private void processFiles() {
        try {
            Files.walk(Paths.get(Configurations.SOURCE_PATH))
                    .filter(new NoDestinationPathFilter()) //<--This one
                    .filter(new NoMetaFilesOrDirectories()) //<--and this too
                    .forEach(
                            path -> {
                                new FileProcessorFactory().getFileProcessor(
                                        path).process(path);
                            });
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
    }

As of now I have various other methods, which are same as the above one, with only difference in the filters. Some methods have additional filters, some have different or none.

Is it possible, that I create a collection of filters required for a condition and pass in dynamically. And all the filters in the collection are applied on the stream. I do not want to hard-code the list of filters being applied. I want to make it configuration based. How do I achieve that?

Upvotes: 1

Views: 509

Answers (2)

Mohit Kanwar
Mohit Kanwar

Reputation: 3050

How about this?

private void processFiles(List<Predicate<Path>> filterList) {
    Predicate<Path> compositeFilter=filterList.stream().reduce(w -> true, Predicate::and);
    try {
        Files.walk(Paths.get(Configurations.SOURCE_PATH))
             .filter(compositeFilter)
             .forEach(path -> {
                        new FileProcessorFactory().getFileProcessor(
                                path).process(path);
                    });

    } catch (IOException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }
}

Upvotes: 1

fge
fge

Reputation: 121702

You can just use Files.find():

private void processFiles(final Path baseDir, final Consumer<? super Path> consumer,
    final Collection<BiPredicate<Path, BasicFileAttributes>> filters)
    throws IOException
{
    final BiPredicate<Path, BasicFileAttributes> filter = filters.stream()
        .reduce((t, u) -> true, BiPredicate::and);

    try (
        final Stream<Path> stream = Files.find(baseDir, Integer.MAX_VALUE, filter);
    ) {
        stream.forEach(consumer);
    }
}

Yes, this will mean converting your filters...

See also the javadoc of BiPredicate and BasicFileAttributes; in particular, BiPredicate has a .and() method which you will find useful in your situation.

Upvotes: 5

Related Questions