// Path: src/main/java/com/poolik/classfinder/io/DirUtils.java
// public class DirUtils {
// 
//   private DirUtils() {}
// 
//   public static void deleteIfExists(Path path) throws IOException {
//     if (Files.exists(path)) {
//       validate(path);
//       Files.walkFileTree(path, new DeleteDirVisitor());
//     }
//   }
// 
//   public static void copy(Path from, Path to, Predicate<Path> copyPredicate) throws IOException {
//     validate(from);
//     Files.walkFileTree(from, EnumSet.of(FileVisitOption.FOLLOW_LINKS),Integer.MAX_VALUE,new CopyDirVisitor(from, to, copyPredicate));
//   }
// 
//   public static Collection<File> findWithSuffix(Path from, String suffix) throws IOException {
//     validate(from);
//     SuffixFileVisitor visitor = new SuffixFileVisitor(suffix);
//     Files.walkFileTree(from, visitor);
//     return visitor.getFiles();
//   }
// 
//   private static void validate(Path... paths) {
//     for (Path path : paths) {
//       Objects.requireNonNull(path);
//       if (!Files.isDirectory(path)) {
//         throw new IllegalArgumentException(String.format("%s is not a directory", path.toString()));
//       }
//     }
//   }
// }
// 
// Path: src/main/java/com/poolik/classfinder/io/Predicate.java
// public interface Predicate<T> {
//   boolean apply(T t);
// }
// 
// Path: src/main/java/com/poolik/classfinder/io/Predicates.java
// public class Predicates {
//   private Predicates() {}
// 
//   public static <T> Predicate<T> alwaysTrue() {
//     return new Predicate<T>() {
//       @Override
//       public boolean apply(Object o) {
//         return true;
//       }
//     };
//   }
// }


import com.poolik.classfinder.io.DirUtils;
import com.poolik.classfinder.io.Predicate;
import com.poolik.classfinder.io.Predicates;
import org.junit.Before;
import org.junit.Rule;
import org.junit.rules.TemporaryFolder;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Path;
import java.nio.file.Paths;
package com.poolik.classfinder;



public abstract class TestWithTestClasses {

  protected Path classesFolder;
  protected Path otherClassesFolder;

  @Rule
  public TemporaryFolder testFolder = new TemporaryFolder();

  @Before
  public void createClasses() throws IOException, URISyntaxException {
    testFolder.create();
    classesFolder = Paths.get(getTestFolder(), "classes");
    otherClassesFolder = Paths.get(getTestFolder(), "otherClasses");
    copyClasses("/com/poolik/classfinder/testClasses", classesFolder);
    copyClasses("/com/poolik/classfinder/otherTestClasses", otherClassesFolder);
  }

  protected void copyClasses(String from, Path to) throws IOException, URISyntaxException {
    copyClasses(from, to, Predicates.<Path>alwaysTrue());
  }

  protected void copyClasses(String from, Path to, Predicate<Path> predicate) throws IOException, URISyntaxException {
// Path: src/main/java/com/poolik/classfinder/io/DirUtils.java
// public class DirUtils {
// 
//   private DirUtils() {}
// 
//   public static void deleteIfExists(Path path) throws IOException {
//     if (Files.exists(path)) {
//       validate(path);
//       Files.walkFileTree(path, new DeleteDirVisitor());
//     }
//   }
// 
//   public static void copy(Path from, Path to, Predicate<Path> copyPredicate) throws IOException {
//     validate(from);
//     Files.walkFileTree(from, EnumSet.of(FileVisitOption.FOLLOW_LINKS),Integer.MAX_VALUE,new CopyDirVisitor(from, to, copyPredicate));
//   }
// 
//   public static Collection<File> findWithSuffix(Path from, String suffix) throws IOException {
//     validate(from);
//     SuffixFileVisitor visitor = new SuffixFileVisitor(suffix);
//     Files.walkFileTree(from, visitor);
//     return visitor.getFiles();
//   }
// 
//   private static void validate(Path... paths) {
//     for (Path path : paths) {
//       Objects.requireNonNull(path);
//       if (!Files.isDirectory(path)) {
//         throw new IllegalArgumentException(String.format("%s is not a directory", path.toString()));
//       }
//     }
//   }
// }
// 
// Path: src/main/java/com/poolik/classfinder/io/Predicate.java
// public interface Predicate<T> {
//   boolean apply(T t);
// }
// 
// Path: src/main/java/com/poolik/classfinder/io/Predicates.java
// public class Predicates {
//   private Predicates() {}
// 
//   public static <T> Predicate<T> alwaysTrue() {
//     return new Predicate<T>() {
//       @Override
//       public boolean apply(Object o) {
//         return true;
//       }
//     };
//   }
// }


// Path: src/test/java/com/poolik/classfinder/TestWithTestClasses.java
import com.poolik.classfinder.io.DirUtils;
import com.poolik.classfinder.io.Predicate;
import com.poolik.classfinder.io.Predicates;
import org.junit.Before;
import org.junit.Rule;
import org.junit.rules.TemporaryFolder;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Path;
import java.nio.file.Paths;

package com.poolik.classfinder;



public abstract class TestWithTestClasses {

  protected Path classesFolder;
  protected Path otherClassesFolder;

  @Rule
  public TemporaryFolder testFolder = new TemporaryFolder();

  @Before
  public void createClasses() throws IOException, URISyntaxException {
    testFolder.create();
    classesFolder = Paths.get(getTestFolder(), "classes");
    otherClassesFolder = Paths.get(getTestFolder(), "otherClasses");
    copyClasses("/com/poolik/classfinder/testClasses", classesFolder);
    copyClasses("/com/poolik/classfinder/otherTestClasses", otherClassesFolder);
  }

  protected void copyClasses(String from, Path to) throws IOException, URISyntaxException {
    copyClasses(from, to, Predicates.<Path>alwaysTrue());
  }

  protected void copyClasses(String from, Path to, Predicate<Path> predicate) throws IOException, URISyntaxException {
    DirUtils.deleteIfExists(to);