content: /*
   * Licensed to the Apache Software Foundation (ASF) under one or more
   * contributor license agreements.  See the NOTICE file distributed with
   * this work for additional information regarding copyright ownership.
   * The ASF licenses this file to You under the Apache License, Version 2.0
   * (the "License"); you may not use this file except in compliance with
   * the License.  You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.apache.camel.quarkus.core.deployment.util;
  
  import java.io.File;
  import java.nio.file.Path;
  import java.nio.file.Paths;
  import java.util.Arrays;
  import java.util.List;
  import java.util.Set;
  import java.util.TreeSet;
  import java.util.function.Predicate;
  import java.util.stream.Stream;
  
  import org.apache.camel.util.FileUtil;
  import org.jboss.jandex.DotName;
  import org.junit.jupiter.api.Assertions;
  import org.junit.jupiter.api.Test;
  
  import static org.junit.jupiter.api.Assertions.assertFalse;
  import static org.junit.jupiter.api.Assertions.assertTrue;
  
  public class PathFilterTest {
  
      @Test
      public void stringFilter() {
          assertFalse(isPathIncluded(
                  "org/acme/MyClass",
                  Arrays.asList("org/**"),
                  Arrays.asList()));
          assertFalse(isPathIncluded(
                  "org/acme/MyClass",
                  Arrays.asList("org/**"),
                  Arrays.asList("org/**", "org/acme/MyClass")));
          assertFalse(isPathIncluded(
                  "org/acme/MyClass",
                  Arrays.asList("org/acme/M*"),
                  Arrays.asList("org/acme/MyClass")));
          assertFalse(isPathIncluded(
                  "org/acme/MyClass",
                  Arrays.asList(),
                  Arrays.asList("org/acme/A*")));
  
          assertTrue(isPathIncluded(
                  "org/acme/MyClass",
                  Arrays.asList(),
                  Arrays.asList()));
          assertTrue(isPathIncluded(
                  "org/acme/MyClass",
                  Arrays.asList(),
                  Arrays.asList("org/**")));
          assertTrue(isPathIncluded(
                  "org/acme/MyClass",
                  Arrays.asList("org/acme/A*"),
                  Arrays.asList("org/acme/MyClass")));
      }
  
      @Test
      public void pathFilter() {
          PathFilter.Builder builder = new PathFilter.Builder();
          Stream.of("/foo/bar/*", "moo/mar/*")
                  .forEach(path -> {
                      if (FileUtil.isWindows()) {
                          path = path.replace("/", File.pathSeparator);
                      }
                      builder.include(path);
                  });
  
          Stream.of("/foo/baz/*", "moo/maz/*")
                  .forEach(path -> {
                      if (FileUtil.isWindows()) {
                          path = path.replace("/", File.pathSeparator);
                      }
                      builder.exclude(path);
                  });
  
          Predicate<Path> predicate = builder
                  .include("/foo/bar/*")
                  .include("moo/mar/*")
                  .exclude("/foo/baz/*")
                  .exclude("moo/maz/*")
                  .build().asPathPredicate();
          assertTrue(predicate.test(Paths.get("/foo/bar/file")));
          assertTrue(predicate.test(Paths.get("foo/bar/file")));
          assertFalse(predicate.test(Paths.get("/foo/baz/file")));
          assertFalse(predicate.test(Paths.get("foo/baz/file")));
  
          assertTrue(predicate.test(Paths.get("/moo/mar/file")));
          assertTrue(predicate.test(Paths.get("moo/mar/file")));
          assertFalse(predicate.test(Paths.get("/moo/marz/file")));
          assertFalse(predicate.test(Paths.get("moo/maz/file")));
      }
  
      @Test
      public void dotNameFilter() {
          Predicate<DotName> predicate = new PathFilter.Builder()
                  .include("foo/bar/*")
                  .exclude("foo/baz/*")
                  .build().asDotNamePredicate();
          assertTrue(predicate.test(DotName.createSimple("foo.bar.Class")));
          assertFalse(predicate.test(DotName.createSimple("foo.baz.Class")));
      }
  
      static boolean isPathIncluded(String path, List<String> excludePatterns, List<String> includePatterns) {
          return new PathFilter(includePatterns, excludePatterns).asStringPredicate().test(path);
      }
  
      @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 Set<String> classNames = new TreeSet<>();
          filter.scanClassNames(rootPath, pathStream, isRegularFile, classNames::add);
  
          Assertions.assertEquals(new TreeSet<>(Arrays.asList(
                  "org.p1.Class1",
                  "org.p1.Class1$Inner",
                  "org.p2.whatever.Class2")),
                  classNames);
  
      }
  
      @Test
      void addNonPatternPaths() {
          final PathFilter pathFilter = new PathFilter.Builder()
                  .include("org/p1/*")
                  .include("org/p2/**")
                  .include("org/p3/NonPatternClass")
                  .exclude("org/p1/ExcludedClass")
                  .exclude("org/p2/excludedpackage/**")
                  .build();
          Set<String> selectedPaths = new TreeSet<>();
          pathFilter.addNonPatternPaths(selectedPaths);
          Assertions.assertEquals(new TreeSet<>(Arrays.asList("org.p3.NonPatternClass")), selectedPaths);
      }
  
  }
  