### Question:
PathFilter { public String[] scanClassNames(Path rootPath, Stream<Path> pathStream, Predicate<Path> isRegularFile) { return pathStream .filter(isRegularFile) .filter(path -> path.getFileName().toString().endsWith(CLASS_SUFFIX)) .map(rootPath::relativize) .map(Path::toString) .map(stringPath -> stringPath.substring(0, stringPath.length() - CLASS_SUFFIX_LENGTH)) .filter(stringPredicate) .map(slashClassName -> slashClassName.replace('/', '.')) .toArray(String[]::new); } PathFilter(List<String> includePatterns, List<String> excludePatterns); Predicate<String> asStringPredicate(); Predicate<DotName> asDotNamePredicate(); Predicate<Path> asPathPredicate(); String[] scanClassNames(Path rootPath, Stream<Path> pathStream, Predicate<Path> isRegularFile);  }### Answer:
@Test void scanClassNames() { final PathFilter filter = new PathFilter.Builder() .include("org/p1/*") .include("org/p2/**") .exclude("org/p1/ExcludedClass") .exclude("org/p2/excludedpackage/**") .build(); final Path rootPath = Paths.get("/foo"); final Stream<Path> pathStream = Stream.of( "org/p1/Class1.class", "org/p1/Class1$Inner.class", "org/p1/Class1.txt", "org/p1/ExcludedClass.class", "org/p2/excludedpackage/ExcludedClass.class", "org/p2/excludedpackage/p/ExcludedClass.class", "org/p2/whatever/Class2.class") .map(rootPath::resolve); final Predicate<Path> isRegularFile = path -> path.getFileName().toString().contains("."); final String[] classNames = filter.scanClassNames(rootPath, pathStream, isRegularFile); Assertions.assertArrayEquals(new String[] { "org.p1.Class1", "org.p1.Class1$Inner", "org.p2.whatever.Class2" }, classNames); }