/*
 * Copyright 2008 Google Inc.
 * 
 * Licensed 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 com.google.gwt.dev.resource.impl;

import com.google.gwt.dev.resource.impl.DefaultFilters.FilterFileType;

import junit.framework.TestCase;

import org.apache.tools.ant.types.ZipScanner;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * An implementation for DefaultExcludesFilterTest.
 * 
 * Tests:
 * 
 * 1. The filter conversion from ant to Java regex. Which cases can we handle,
 * and confirm that we perform correctly in all cases.
 * 
 * 2. checking the 4 defaultFilters, one for each combination of defaultExcludes
 * and isJava.
 * 
 * 3. Checking whether customFilter work correctly, both in presence and absence
 * of Ant.
 * 
 * TODO (amitmanjhi): clean up this test code.
 */
public class DefaultFiltersTest extends TestCase {

  static class AdvancedPaths {
    String baseIncluded[] = {
        "Baz", "test/foo/Foo", "test/bar/Bar", "test/baz/Foo"};

    String baseExcludedTesting[] = {"foo/testing/Baz"};
    String baseExcludedExact[] = {"Foo", "Bar",};
    String baseExcludedDoubleStar[] = {"fooz/Baz", "barz/hello/Baz"};
    String baseExcluded[] = mergeArrays(baseExcludedTesting, baseExcludedExact,
        baseExcludedDoubleStar);

    void testAdvancedPath(ResourceFilterString expected,
        ResourceFilterString actual, String suffix) {
      for (String path : mergeArrays(baseIncluded, baseExcluded, getMiscPaths(
          "testing", false).toArray(EMPTY_ARRAY),
          getMiscPaths("a/bc/de", false).toArray(EMPTY_ARRAY))) {
        assertEquals(path + suffix, expected, actual);
      }      
    }

    void testAdvancedPathAnt(ResourceFilterString expected,
        ResourceFilterString actual, String suffix) {
      for (String path : mergeArrays(baseIncluded, baseExcluded, getMiscPaths(
          "testing", true).toArray(EMPTY_ARRAY),
          getMiscPaths("a/bc/de", true).toArray(EMPTY_ARRAY))) {
        assertEquals(EXCLUDED_CHARS + path + EXCLUDED_CHARS + suffix,
            expected, actual);
        assertEquals(path + EXCLUDED_CHARS + suffix, expected, actual);
        assertEquals(path + suffix, expected, actual);
      }
      testAdvancedPath(expected, actual, suffix);
      new BasicPaths().testBasicPath(expected, actual, suffix);
    }
    
    void testAdvancedClassFilesPathAnt(ResourceFilterString expected,
        ResourceFilterString actual) {
      testAdvancedPathAnt(expected, actual, CLASS_FILE_SUFFIX);
    }

    void testAdvancedJavaPathAnt(ResourceFilterString expected,
        ResourceFilterString actual) {
      testAdvancedPathAnt(expected, actual, JAVA_FILE_SUFFIX);      
    }
    
    void testAdvancedPath(ResourceFilterString expected,
        ResourceFilterString actual) {
      for (String path : mergeArrays(baseIncluded, baseExcluded, getMiscPaths(
          "testing", false).toArray(EMPTY_ARRAY),
          getMiscPaths("a/bc/de", false).toArray(EMPTY_ARRAY))) {
        assertEquals(path, expected, actual);
      }
    }

    void testAdvancedPathAnt(ResourceFilterString expected,
        ResourceFilterString actual) {
      for (String path : mergeArrays(baseIncluded, baseExcluded, getMiscPaths(
          "testing", true).toArray(EMPTY_ARRAY),
          getMiscPaths("a/bc/de", true).toArray(EMPTY_ARRAY))) {
        assertEquals(path, expected, actual);
        assertEquals(path + EXCLUDED_CHARS, expected, actual);
        assertEquals(EXCLUDED_CHARS + path + EXCLUDED_CHARS, expected, actual);
      }
      testAdvancedPath(expected, actual);
      new BasicPaths().testBasicPath(expected, actual);
    }
  }

  static class BasicPaths {
    String baseIncluded[] = {
        "foo", "/foo", "foo/bar", "/foo/bar", "/foo/bar", "/foo$/$", "/foo-_", "123FOO123", "cvs",
        "cvs/cvs/svn", ".foo_bar$", "foo/asvn"};
    String baseExcluded[] = {"foo/CVS/bar", "CVS/bar", "foo/.svn/bar", ".svn/bar", "foo/SCCS/bar",};
    String baseSuffixExcluded[] = {
        "foo/.cvsignore", "foo/CVS", "foo/.svn", "foo/SCCS",
        "foo/bar/vssver.scc", "/foo/bar/.DS_Store"};

    void testBasicPath(ResourceFilterString expected,
        ResourceFilterString actual, String suffix) {
      for (String str : mergeArrays(baseIncluded, baseExcluded,
          baseSuffixExcluded,
          getMiscPaths("testing", true).toArray(EMPTY_ARRAY), getMiscPaths(
              "a/bc/de", true).toArray(EMPTY_ARRAY))) {
        assertEquals(str, expected, actual);
        assertEquals(str + suffix, expected, actual);
        assertEquals(EXCLUDED_CHARS + str, expected, actual);
        assertEquals(EXCLUDED_CHARS + str + EXCLUDED_CHARS, expected, actual);
        assertEquals(EXCLUDED_CHARS + str + suffix, expected, actual);
        assertEquals(EXCLUDED_CHARS + str + EXCLUDED_CHARS + suffix,
            expected, actual);
      }      
    }

    void testBasicPath(ResourceFilterString expected,
        ResourceFilterString actual) {
      for (String str : mergeArrays(baseIncluded, baseExcluded,
          baseSuffixExcluded,
          getMiscPaths("testing", true).toArray(EMPTY_ARRAY), getMiscPaths(
              "a/bc/de", true).toArray(EMPTY_ARRAY))) {
        assertEquals(str, expected, actual);
        assertEquals(EXCLUDED_CHARS + str, expected, actual);
        assertEquals(EXCLUDED_CHARS + str + EXCLUDED_CHARS, expected, actual);
      }
    }
  }

  /*
   * Sole purpose of this class is to get a useful debug message.
   */
  private static class ResourceFilterString {
    final ResourceFilter filter;
    final String stringRepresentation;

    ResourceFilterString(ResourceFilter filter, String stringRepresentation) {
      this.filter = filter;
      this.stringRepresentation = stringRepresentation;
    }
  }

  private static final String EMPTY_ARRAY[] = new String[0];
  private static final boolean DEFAULT_EXCLUDES = true;
  private static final boolean DEFAULT_INCLUDES = false;
  private static final String JAVA_FILE_SUFFIX = ".java";
  private static final String CLASS_FILE_SUFFIX = ".class";
  
  private static final String MERGED_PATTERNS[] = {
      "**/testing/**", "Foo", "Bar", "fooz/**", "barz/hello/**"};

  // careful that the pattern is still permitted by ant.
  private static final String EXCLUDED_CHARS = "#~%*";

  private static void assertEquals(String path, ResourceFilterString expected,
      ResourceFilterString actual) {
    boolean scanResult = expected.filter.allows(path);
    assertEquals("String to be matched = " + path + ", actual filter = "
        + actual.stringRepresentation + " should yield " + scanResult
        + ", expected Filter = " + expected.stringRepresentation, scanResult,
        actual.filter.allows(path));
  }

  private static List<String> getMiscPaths(String middleString,
      boolean endInSlash) {
    List<String> testPaths = new ArrayList<String>();
    testPaths.addAll(Arrays.asList(new String[] {
        "Foo", "Bar", "foo/xyz", "afoo/xyz-_$", "b/foo/x",
        "foo/BarTestabc.java", "foo/xyz/BarTestabc.java", "a/b/testing/c/d",
        "a/testing/b/c/FooBazBarTest.java", "a/testing/b/Foo/BazBar.java",
        "a/testing/b/Foo$-_$Bar.class", "a/testing/b/Foo$/$.class"}));

    String pathPrefixes[] = {"", "/", "foo/", "/foo/", "bar/foo/", "/bar/foo/"};
    List<String> pathSuffixes = new ArrayList<String>();
    if (endInSlash) {
      // special handling because currently we don't handle paths that end in /
      pathSuffixes.addAll(Arrays.asList(new String[] {
          "", "/", "/foo", "/foo/", "/foo/bar", "/foo/bar/"}));
    } else {
      pathSuffixes.addAll(Arrays.asList(new String[] {"", "/foo", "/foo/bar",}));
    }
    for (String pathPrefix : pathPrefixes) {
      for (String pathSuffix : pathSuffixes) {
        testPaths.add(pathPrefix + middleString + pathSuffix);
      }
    }
    return testPaths;
  }

  private static String[] mergeArrays(String[]... baseArrays) {
    int count = 0;
    for (String arrayElement[] : baseArrays) {
      count += arrayElement.length;
    }
    String retArray[] = new String[count];
    count = 0;
    for (String arrayElement[] : baseArrays) {
      for (String element : arrayElement) {
        retArray[count++] = element;
      }
    }
    return retArray;
  }

  public void testEmptyFilters() {
    BasicPaths basicPaths = new BasicPaths();
    FilterFileType fileType;
    
    // first arg: ant filter, second arg: our custom filter
    fileType= FilterFileType.RESOURCE_FILES;
    basicPaths.testBasicPath(getAntFilter(EMPTY_ARRAY, EMPTY_ARRAY,
        EMPTY_ARRAY, DEFAULT_EXCLUDES, fileType, "antDefaultFilter"),
        new ResourceFilterString(fileType.getDefaultFilter(),
            "defaultFilter"));
    basicPaths.testBasicPath(getAntFilter(EMPTY_ARRAY, EMPTY_ARRAY,
        EMPTY_ARRAY, DEFAULT_INCLUDES, fileType, "antDefaultIncludesFilter"),
        new ResourceFilterString(fileType.getFileTypeFilter(),
            "defaultIncludesFilter"));

    fileType = FilterFileType.JAVA_FILES;
    basicPaths.testBasicPath(getAntFilter(EMPTY_ARRAY, EMPTY_ARRAY,
        EMPTY_ARRAY, DEFAULT_EXCLUDES, fileType, "antDefaultJavaFilter"),
        new ResourceFilterString(fileType.getDefaultFilter(),
            "defaultJavaFilter"), fileType.getSuffix());
    basicPaths.testBasicPath(getAntFilter(EMPTY_ARRAY, EMPTY_ARRAY,
        EMPTY_ARRAY, DEFAULT_INCLUDES, fileType, "antJustJavaFilter"),
        new ResourceFilterString(fileType.getFileTypeFilter(),
            "justJavaFilter"), fileType.getSuffix());
    
    fileType = FilterFileType.CLASS_FILES;
    basicPaths.testBasicPath(getAntFilter(EMPTY_ARRAY, EMPTY_ARRAY,
        EMPTY_ARRAY, DEFAULT_EXCLUDES, FilterFileType.CLASS_FILES, "antDefaultClassFilesFilter"),
        new ResourceFilterString(fileType.getDefaultFilter(),
            "defaultClassFilesFilter"), fileType.getSuffix());
    basicPaths.testBasicPath(getAntFilter(EMPTY_ARRAY, EMPTY_ARRAY,
        EMPTY_ARRAY, DEFAULT_INCLUDES, FilterFileType.CLASS_FILES, "antJustClassFilesFilter"),
        new ResourceFilterString(fileType.getFileTypeFilter(),
            "justClassFilesFilter"), fileType.getSuffix());    
  }

  /**
   * (a) test that filters are correctly converted to non-null and null
   * patterns. (b) test that filters match the same String.
   */
  public void testFilterConversion() {
    List<String> nullFilters = Arrays.asList(new String[] {
        "***/testing/**", "**/{/**", "**/}/**", "**/+/**",});
    List<String> okayFilters = new ArrayList<String>();
    okayFilters.addAll(Arrays.asList(new String[] {
        "**/#/**", "**/~/**", "Foo", "Bar", "foo/**", "foo/*Test*java",
        "**/testing/**", "**/testing/**/Foo*Bar*.java",
        "**/testing/**/Foo$*r.class",}));
    String doubleStarPrefixes[] = {"", "/", "**/", "/**/", "foo**/", "/foo**/"};
    String doubleStarSuffixes[] = {"", "/", "/**", "/**/", "/**foo", "/**foo/"};
    String middleString = "testing";
    for (String doubleStarPrefix : doubleStarPrefixes) {
      for (String doubleStarSuffix : doubleStarSuffixes) {
        okayFilters.add(doubleStarPrefix + middleString + doubleStarSuffix);
      }
    }

    List<String> testPaths = getMiscPaths("testing", false);
    DefaultFilters filters = new DefaultFilters();
    for (String filter : nullFilters) {
      assertNull(filter + " conversion should be null",
          filters.getPatternFromAntPattern(filter));
    }

    for (String filter : okayFilters) {
      String pattern = filters.getPatternFromAntPattern(filter);
      assertNotNull(filter + " conversion should be non-null", pattern);

      ResourceFilterString antFilterString = getAntFilter(
          new String[] {filter}, EMPTY_ARRAY, EMPTY_ARRAY, DEFAULT_EXCLUDES,
          FilterFileType.RESOURCE_FILES, "ant_" + filter);
      ResourceFilterString customFilterString = new ResourceFilterString(
          filters.customFilterWithCatchAll(new String[] {filter}, EMPTY_ARRAY,
              EMPTY_ARRAY, true, null, FilterFileType.RESOURCE_FILES), "custom_" + pattern);
      for (String path : testPaths) {
        assertEquals(path, antFilterString, customFilterString);
      }
    }
  }

  public void testFilterParts() {
    AdvancedPaths advancedPaths = new AdvancedPaths();
    ResourceFilter filter = null;

    // everything except those starting with '/' should be included
    filter = new DefaultFilters().getIncludesFilterPart(EMPTY_ARRAY);
    advancedPaths.testAdvancedPath(getAntFilter(EMPTY_ARRAY, EMPTY_ARRAY,
        EMPTY_ARRAY, DEFAULT_INCLUDES, FilterFileType.RESOURCE_FILES, "antDefaultFilter"),
        new ResourceFilterString(filter, "defaultFilter"));

    // everything should be excluded
    filter = new DefaultFilters().getExcludesFilterPart(EMPTY_ARRAY);
    advancedPaths.testAdvancedPath(getAntFilter(new String[] {"a/1/2/3"},
        new String[] {"**", "/**"}, EMPTY_ARRAY, DEFAULT_INCLUDES, FilterFileType.RESOURCE_FILES,
        "antDefaultFilter"), new ResourceFilterString(filter, "defaultFilter"));

    filter = new DefaultFilters().getIncludesFilterPart(MERGED_PATTERNS);
    advancedPaths.testAdvancedPath(getAntFilter(MERGED_PATTERNS, EMPTY_ARRAY,
        EMPTY_ARRAY, DEFAULT_INCLUDES, FilterFileType.RESOURCE_FILES, "antMergedPatterns"),
        new ResourceFilterString(filter, "customMergedPatterns"));
  }

  // no ant, catchAll filter is null
  public void testNonEmptyFilters() {
    AdvancedPaths advancedPaths = new AdvancedPaths();

    ResourceFilter filter = null;
    // pass empty includeArray. Matches everything that is not excluded.
    filter = getFilterWithoutCatchAll(EMPTY_ARRAY, MERGED_PATTERNS, EMPTY_ARRAY,
        FilterFileType.RESOURCE_FILES);
    advancedPaths.testAdvancedPath(getAntFilter(EMPTY_ARRAY, MERGED_PATTERNS,
        EMPTY_ARRAY, DEFAULT_EXCLUDES, FilterFileType.RESOURCE_FILES, "ant_emptyArray_mergedPatterns"),
        new ResourceFilterString(filter, "custom_emptyArray_mergedPatterns"));

    // pass empty excludeArray. Matches everything that is included.
    filter = getFilterWithoutCatchAll(MERGED_PATTERNS, EMPTY_ARRAY, EMPTY_ARRAY,
        FilterFileType.RESOURCE_FILES);
    advancedPaths.testAdvancedPath(getAntFilter(MERGED_PATTERNS, EMPTY_ARRAY,
        EMPTY_ARRAY, DEFAULT_EXCLUDES, FilterFileType.RESOURCE_FILES, "ant_mergedPatterns_emptyArray"),
        new ResourceFilterString(filter, "custom_mergedPatterns_emptyArray"));

    // pass non-empty include and exclude array. Matches nothing
    filter = getFilterWithoutCatchAll(MERGED_PATTERNS, MERGED_PATTERNS,
        EMPTY_ARRAY, FilterFileType.RESOURCE_FILES);
    advancedPaths.testAdvancedPath(
        getAntFilter(MERGED_PATTERNS, MERGED_PATTERNS, EMPTY_ARRAY,
            DEFAULT_EXCLUDES, FilterFileType.RESOURCE_FILES, "ant_mergedPatterns_mergedPatterns"),
        new ResourceFilterString(filter, "custom_mergedPatterns_mergedPatterns"));
  }

  // finish, catchAll filter is not-null
  public void testNonEmptyFiltersAnt() {
    AdvancedPaths advancedPaths = new AdvancedPaths();

    ResourceFilter filter = null;
    // pass empty includeArray. Matches everything that is not excluded.
    filter = getFilterWithCatchAll(EMPTY_ARRAY, MERGED_PATTERNS, EMPTY_ARRAY,
        FilterFileType.RESOURCE_FILES);
    advancedPaths.testAdvancedPathAnt(getAntFilter(EMPTY_ARRAY, MERGED_PATTERNS,
        EMPTY_ARRAY, DEFAULT_EXCLUDES, FilterFileType.RESOURCE_FILES,
        "ant_emptyIncludeArray_mergedPatterns"),
        new ResourceFilterString(filter, "custom_emptyArray_mergedPatterns"));

    // pass empty excludeArray. Matches everything that is included.
    filter = getFilterWithCatchAll(MERGED_PATTERNS, EMPTY_ARRAY, EMPTY_ARRAY,
        FilterFileType.RESOURCE_FILES);
    advancedPaths.testAdvancedPathAnt(getAntFilter(MERGED_PATTERNS, EMPTY_ARRAY,
        EMPTY_ARRAY, DEFAULT_EXCLUDES, FilterFileType.RESOURCE_FILES,
        "ant_emptyExcludeArray_mergedPatterns"),
        new ResourceFilterString(filter, "custom_emptyArray_mergedPatterns"));

    // pass non-empty include and exclude array. Matches nothing
    filter = getFilterWithCatchAll(MERGED_PATTERNS, MERGED_PATTERNS, EMPTY_ARRAY,
        FilterFileType.RESOURCE_FILES);
    advancedPaths.testAdvancedPathAnt(getAntFilter(MERGED_PATTERNS,
        MERGED_PATTERNS, EMPTY_ARRAY, DEFAULT_EXCLUDES, FilterFileType.RESOURCE_FILES,
        "ant_mergedPatterns_mergedPatterns"), new ResourceFilterString(filter,
        "custom_mergedPatterns_mergedPatterns"));
  }

  // no ant, catchAll filter is null
  public void testNonEmptyJavaFilters() {
    AdvancedPaths advancedPaths = new AdvancedPaths();
    String newMergedPatterns[] = getMergedPatterns(JAVA_FILE_SUFFIX);
    ResourceFilter filter = null;
    
    // pass empty includeArray. Means catch all
    filter = getFilterWithoutCatchAll(EMPTY_ARRAY, newMergedPatterns,
        EMPTY_ARRAY, FilterFileType.JAVA_FILES);
    advancedPaths.testAdvancedPath(getAntFilter(EMPTY_ARRAY,
        newMergedPatterns, EMPTY_ARRAY, DEFAULT_EXCLUDES, FilterFileType.JAVA_FILES,
        "ant_emptyArray_newMergedPatterns"), new ResourceFilterString(filter,
        "custom_emptyArray_newMergedPatterns"), JAVA_FILE_SUFFIX);

    // pass empty excludeArray. Means catch only the pattern
    filter = getFilterWithoutCatchAll(newMergedPatterns, EMPTY_ARRAY,
        EMPTY_ARRAY, FilterFileType.JAVA_FILES);
    advancedPaths.testAdvancedPath(getAntFilter(newMergedPatterns,
        EMPTY_ARRAY, EMPTY_ARRAY, DEFAULT_EXCLUDES, FilterFileType.JAVA_FILES,
        "ant_newMergedPatterns_emptyArray"), new ResourceFilterString(filter,
        "custom_newMergedPatterns_emptyArray"), JAVA_FILE_SUFFIX);

    // pass non-empty include and exclude array.
    filter = getFilterWithoutCatchAll(newMergedPatterns, newMergedPatterns,
        EMPTY_ARRAY, FilterFileType.JAVA_FILES);
    advancedPaths.testAdvancedPath(getAntFilter(newMergedPatterns,
        newMergedPatterns, EMPTY_ARRAY, DEFAULT_EXCLUDES, FilterFileType.JAVA_FILES,
        "ant_newMergedPatterns_newMergedPatterns"), new ResourceFilterString(
        filter, "custom_newMergedPatterns_newMergedPatterns"), JAVA_FILE_SUFFIX);
  }

  public void testNonEmptyJavaFiltersAnt() {
    AdvancedPaths advancedPaths = new AdvancedPaths();
    String newMergedPatterns[] = getMergedPatterns(JAVA_FILE_SUFFIX);
    ResourceFilter filter = null;
    
    // pass empty includeArray. Means catch all
    filter = getFilterWithCatchAll(EMPTY_ARRAY, newMergedPatterns, EMPTY_ARRAY,
        FilterFileType.JAVA_FILES);
    advancedPaths.testAdvancedPathAnt(getAntFilter(EMPTY_ARRAY,
        newMergedPatterns, EMPTY_ARRAY, DEFAULT_EXCLUDES, FilterFileType.JAVA_FILES,
        "ant_emptyArray_newMergedPatterns"), new ResourceFilterString(filter,
        "custom_emptyArray_newMergedPatterns"), JAVA_FILE_SUFFIX);

    // pass empty excludeArray. Means catch only the pattern
    filter = getFilterWithCatchAll(newMergedPatterns, EMPTY_ARRAY, EMPTY_ARRAY,
        FilterFileType.JAVA_FILES);
    advancedPaths.testAdvancedPathAnt(getAntFilter(newMergedPatterns,
        EMPTY_ARRAY, EMPTY_ARRAY, DEFAULT_EXCLUDES, FilterFileType.JAVA_FILES,
        "ant_newMergedPatterns_emptyArray"), new ResourceFilterString(filter,
        "custom_newMergedPatterns_emptyArray"), JAVA_FILE_SUFFIX);

    // pass non-empty include and exclude array.
    filter = getFilterWithCatchAll(newMergedPatterns, newMergedPatterns,
        EMPTY_ARRAY, FilterFileType.JAVA_FILES);
    advancedPaths.testAdvancedPathAnt(getAntFilter(newMergedPatterns,
        newMergedPatterns, EMPTY_ARRAY, DEFAULT_EXCLUDES, FilterFileType.JAVA_FILES,
        "ant_newMergedPatterns_newMergedPatterns"), new ResourceFilterString(
        filter, "custom_newMergedPatterns_newMergedPatterns"), JAVA_FILE_SUFFIX);
  }
  
  public void testNonEmptyJavaSkipFiltersAnt() {
    AdvancedPaths advancedPaths = new AdvancedPaths();
    String newMergedPatterns[] = getMergedPatterns(JAVA_FILE_SUFFIX);
    ResourceFilter filter = null;

    // pass empty includeArray. Means catch all, skipping newMergedPatterns
    filter = getFilterWithCatchAll(EMPTY_ARRAY, EMPTY_ARRAY, newMergedPatterns,
        FilterFileType.JAVA_FILES);
    advancedPaths.testAdvancedJavaPathAnt(getAntFilter(EMPTY_ARRAY,
        EMPTY_ARRAY, newMergedPatterns, DEFAULT_EXCLUDES, FilterFileType.JAVA_FILES,
        "ant_emptyArray_newMergedPatterns"), new ResourceFilterString(filter,
        "custom_emptyArray_newMergedPatterns"));

    // pass non-empty include and skip array.
    filter = getFilterWithCatchAll(newMergedPatterns, EMPTY_ARRAY,
        newMergedPatterns, FilterFileType.JAVA_FILES);
    advancedPaths.testAdvancedJavaPathAnt(getAntFilter(newMergedPatterns,
        EMPTY_ARRAY, newMergedPatterns, DEFAULT_EXCLUDES, FilterFileType.JAVA_FILES,
        "ant_newMergedPatterns_newMergedPatterns"), new ResourceFilterString(
        filter, "custom_newMergedPatterns_newMergedPatterns"));

    // in a single filter, skip and exclude are equivalent
    filter = getFilterWithCatchAll(newMergedPatterns, newMergedPatterns,
        EMPTY_ARRAY, FilterFileType.JAVA_FILES);
    advancedPaths.testAdvancedJavaPathAnt(getAntFilter(newMergedPatterns,
        EMPTY_ARRAY, newMergedPatterns, DEFAULT_EXCLUDES, FilterFileType.JAVA_FILES,
        "ant_newMergedPatterns_newMergedPatterns"), new ResourceFilterString(
        filter, "custom_newMergedPatterns_newMergedPatterns"));
  }
  
  // no ant, catchAll filter is null
  public void testNonEmptyClassFileFilters() {
    AdvancedPaths advancedPaths = new AdvancedPaths();

    String newMergedPatterns[] = getMergedPatterns(CLASS_FILE_SUFFIX);
    ResourceFilter filter = null;
    // pass empty includeArray. Means catch all
    filter = getFilterWithoutCatchAll(EMPTY_ARRAY, newMergedPatterns,
        EMPTY_ARRAY, FilterFileType.CLASS_FILES);
    advancedPaths.testAdvancedPath(getAntFilter(EMPTY_ARRAY,
        newMergedPatterns, EMPTY_ARRAY, DEFAULT_EXCLUDES, FilterFileType.CLASS_FILES,
        "ant_emptyArray_newMergedPatterns"), new ResourceFilterString(filter,
        "custom_emptyArray_newMergedPatterns"), CLASS_FILE_SUFFIX);

    // pass empty excludeArray. Means catch only the pattern
    filter = getFilterWithoutCatchAll(newMergedPatterns, EMPTY_ARRAY,
        EMPTY_ARRAY, FilterFileType.CLASS_FILES);
    advancedPaths.testAdvancedPath(getAntFilter(newMergedPatterns,
        EMPTY_ARRAY, EMPTY_ARRAY, DEFAULT_EXCLUDES, FilterFileType.CLASS_FILES,
        "ant_newMergedPatterns_emptyArray"), new ResourceFilterString(filter,
        "custom_newMergedPatterns_emptyArray"), CLASS_FILE_SUFFIX);

    // pass non-empty include and exclude array.
    filter = getFilterWithoutCatchAll(newMergedPatterns, newMergedPatterns,
        EMPTY_ARRAY, FilterFileType.CLASS_FILES);
    advancedPaths.testAdvancedPath(getAntFilter(newMergedPatterns,
        newMergedPatterns, EMPTY_ARRAY, DEFAULT_EXCLUDES, FilterFileType.CLASS_FILES,
        "ant_newMergedPatterns_newMergedPatterns"), new ResourceFilterString(
        filter, "custom_newMergedPatterns_newMergedPatterns"), CLASS_FILE_SUFFIX);
  }

  public void testNonEmptyClassFileFiltersAnt() {
    AdvancedPaths advancedPaths = new AdvancedPaths();
    String newMergedPatterns[] = getMergedPatterns(CLASS_FILE_SUFFIX);
    ResourceFilter filter = null;
    
    // pass empty includeArray. Means catch all
    filter = getFilterWithCatchAll(EMPTY_ARRAY, newMergedPatterns, EMPTY_ARRAY,
        FilterFileType.CLASS_FILES);
    advancedPaths.testAdvancedPathAnt(getAntFilter(EMPTY_ARRAY,
        newMergedPatterns, EMPTY_ARRAY, DEFAULT_EXCLUDES, FilterFileType.CLASS_FILES,
        "ant_emptyArray_newMergedPatterns"), new ResourceFilterString(filter,
        "custom_emptyArray_newMergedPatterns"), CLASS_FILE_SUFFIX);

    // pass empty excludeArray. Means catch only the pattern
    filter = getFilterWithCatchAll(newMergedPatterns, EMPTY_ARRAY, EMPTY_ARRAY,
        FilterFileType.CLASS_FILES);
    advancedPaths.testAdvancedPathAnt(getAntFilter(newMergedPatterns,
        EMPTY_ARRAY, EMPTY_ARRAY, DEFAULT_EXCLUDES, FilterFileType.CLASS_FILES,
        "ant_newMergedPatterns_emptyArray"), new ResourceFilterString(filter,
        "custom_newMergedPatterns_emptyArray"), CLASS_FILE_SUFFIX);

    // pass non-empty include and exclude array.
    filter = getFilterWithCatchAll(newMergedPatterns, newMergedPatterns,
        EMPTY_ARRAY, FilterFileType.CLASS_FILES);
    advancedPaths.testAdvancedPathAnt(getAntFilter(newMergedPatterns,
        newMergedPatterns, EMPTY_ARRAY, DEFAULT_EXCLUDES, FilterFileType.CLASS_FILES,
        "ant_newMergedPatterns_newMergedPatterns"), new ResourceFilterString(
        filter, "custom_newMergedPatterns_newMergedPatterns"), CLASS_FILE_SUFFIX);
  }
  
  private String[] getMergedPatterns(String suffix) {
    String newMergedPatterns[] = new String[MERGED_PATTERNS.length];
    for (int i = 0; i < MERGED_PATTERNS.length; i++) {
      if (MERGED_PATTERNS[i].endsWith("*")) {
        newMergedPatterns[i] = MERGED_PATTERNS[i];
      } else {
        newMergedPatterns[i] = MERGED_PATTERNS[i] + suffix;
      }
    }
    return newMergedPatterns;
  }
  
  public void testNonEmptyClassFileSkipFiltersAnt() {
    AdvancedPaths advancedPaths = new AdvancedPaths();
    String newMergedPatterns[] = getMergedPatterns(CLASS_FILE_SUFFIX);
    ResourceFilter filter = null;

    // pass empty includeArray. Means catch all, skipping newMergedPatterns
    filter = getFilterWithCatchAll(EMPTY_ARRAY, EMPTY_ARRAY, newMergedPatterns,
        FilterFileType.CLASS_FILES);
    advancedPaths.testAdvancedPathAnt(getAntFilter(EMPTY_ARRAY,
        EMPTY_ARRAY, newMergedPatterns, DEFAULT_EXCLUDES, FilterFileType.CLASS_FILES,
        "ant_emptyArray_newMergedPatterns"), new ResourceFilterString(filter,
        "custom_emptyArray_newMergedPatterns"), CLASS_FILE_SUFFIX);

    // pass non-empty include and skip array.
    filter = getFilterWithCatchAll(newMergedPatterns, EMPTY_ARRAY,
        newMergedPatterns, FilterFileType.CLASS_FILES);
    advancedPaths.testAdvancedPathAnt(getAntFilter(newMergedPatterns,
        EMPTY_ARRAY, newMergedPatterns, DEFAULT_EXCLUDES, FilterFileType.CLASS_FILES,
        "ant_newMergedPatterns_newMergedPatterns"), new ResourceFilterString(
        filter, "custom_newMergedPatterns_newMergedPatterns"), CLASS_FILE_SUFFIX);

    // in a single filter, skip and exclude are equivalent
    filter = getFilterWithCatchAll(newMergedPatterns, newMergedPatterns,
        EMPTY_ARRAY, FilterFileType.CLASS_FILES);
    advancedPaths.testAdvancedPathAnt(getAntFilter(newMergedPatterns,
        EMPTY_ARRAY, newMergedPatterns, DEFAULT_EXCLUDES, FilterFileType.CLASS_FILES,
        "ant_newMergedPatterns_newMergedPatterns"), new ResourceFilterString(
        filter, "custom_newMergedPatterns_newMergedPatterns"), CLASS_FILE_SUFFIX);
  }
  
  private ResourceFilterString getAntFilter(String includes[],
      String excludes[], String skips[], boolean defaultExcludes,
      final FilterFileType filterFileType, String tag) {
    final ZipScanner scanner = DefaultFilters.getScanner(includes, excludes,
        skips, defaultExcludes, true);
    return new ResourceFilterString(new ResourceFilter() {
      public boolean allows(String path) {
        return fileTypeMatches(filterFileType, path) && scanner.match(path);
      }
    }, tag != null ? tag : "includes: " + Arrays.toString(includes)
        + ", excludes: " + Arrays.toString(excludes));
  }

  private ResourceFilter getFilterWithCatchAll(String includesList[],
      String excludesList[], String skipList[], FilterFileType filterFileType) {
    switch (filterFileType) {
      case JAVA_FILES:
        return new DefaultFilters().customJavaFilter(includesList, excludesList,
            skipList, true, true);
      case CLASS_FILES:
        return new DefaultFilters().customClassFilesFilter(includesList, excludesList,
            skipList, true, true);
      case RESOURCE_FILES:
      default:
        return new DefaultFilters().customResourceFilter(includesList,
            excludesList, skipList, true, true);
    }
  }

  // caseSensitive and excludeDefaults are set
  private ResourceFilter getFilterWithoutCatchAll(String includesList[],
      String excludesList[], String skipList[],  FilterFileType filterFileType) {
    return new DefaultFilters().customFilterWithCatchAll(includesList,
        excludesList, skipList, true, null, filterFileType);
  }
  
  private boolean fileTypeMatches(FilterFileType filterFileType, String path) {
    switch (filterFileType) {
      case JAVA_FILES:
        return path.endsWith(".java");
      case CLASS_FILES:
        return path.endsWith(".class");
    }
    return true;
  }
}
