RegexFileFilter.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.apache.commons.io.filefilter;

  18. import java.io.File;
  19. import java.io.Serializable;
  20. import java.nio.file.FileVisitResult;
  21. import java.nio.file.Path;
  22. import java.nio.file.attribute.BasicFileAttributes;
  23. import java.util.Objects;
  24. import java.util.function.Function;
  25. import java.util.regex.Pattern;

  26. import org.apache.commons.io.IOCase;
  27. import org.apache.commons.io.file.PathUtils;

  28. /**
  29.  * Filters files using supplied regular expression(s).
  30.  * <p>
  31.  * See java.util.regex.Pattern for regex matching rules.
  32.  * </p>
  33.  * <h2>Using Classic IO</h2>
  34.  * <p>
  35.  * e.g.
  36.  *
  37.  * <pre>
  38.  * File dir = FileUtils.current();
  39.  * FileFilter fileFilter = new RegexFileFilter("^.*[tT]est(-\\d+)?\\.java$");
  40.  * File[] files = dir.listFiles(fileFilter);
  41.  * for (String file : files) {
  42.  *     System.out.println(file);
  43.  * }
  44.  * </pre>
  45.  *
  46.  * <h2>Using NIO</h2>
  47.  *
  48.  * <pre>
  49.  * final Path dir = PathUtils.current();
  50.  * final AccumulatorPathVisitor visitor = AccumulatorPathVisitor.withLongCounters(new RegexFileFilter("^.*[tT]est(-\\d+)?\\.java$"));
  51.  * //
  52.  * // Walk one directory
  53.  * Files.<strong>walkFileTree</strong>(dir, Collections.emptySet(), 1, visitor);
  54.  * System.out.println(visitor.getPathCounters());
  55.  * System.out.println(visitor.getFileList());
  56.  * //
  57.  * visitor.getPathCounters().reset();
  58.  * //
  59.  * // Walk directory tree
  60.  * Files.<strong>walkFileTree</strong>(dir, visitor);
  61.  * System.out.println(visitor.getPathCounters());
  62.  * System.out.println(visitor.getDirList());
  63.  * System.out.println(visitor.getFileList());
  64.  * </pre>
  65.  * <h2>Deprecating Serialization</h2>
  66.  * <p>
  67.  * <em>Serialization is deprecated and will be removed in 3.0.</em>
  68.  * </p>
  69.  *
  70.  * @since 1.4
  71.  */
  72. public class RegexFileFilter extends AbstractFileFilter implements Serializable {

  73.     private static final long serialVersionUID = 4269646126155225062L;

  74.     /**
  75.      * Compiles the given pattern source.
  76.      *
  77.      * @param pattern the source pattern.
  78.      * @param flags the compilation flags.
  79.      * @return a new Pattern.
  80.      */
  81.     private static Pattern compile(final String pattern, final int flags) {
  82.         Objects.requireNonNull(pattern, "pattern");
  83.         return Pattern.compile(pattern, flags);
  84.     }

  85.     /**
  86.      * Converts IOCase to Pattern compilation flags.
  87.      *
  88.      * @param ioCase case-sensitivity.
  89.      * @return Pattern compilation flags.
  90.      */
  91.     private static int toFlags(final IOCase ioCase) {
  92.         return IOCase.isCaseSensitive(ioCase) ? 0 : Pattern.CASE_INSENSITIVE;
  93.     }

  94.     /** The regular expression pattern that will be used to match file names. */
  95.     private final Pattern pattern;

  96.     /** How convert a path to a string. */
  97.     private final transient Function<Path, String> pathToString;

  98.     /**
  99.      * Constructs a new regular expression filter for a compiled regular expression
  100.      *
  101.      * @param pattern regular expression to match.
  102.      * @throws NullPointerException if the pattern is null.
  103.      */
  104.     @SuppressWarnings("unchecked")
  105.     public RegexFileFilter(final Pattern pattern) {
  106.         this(pattern, (Function<Path, String> & Serializable) PathUtils::getFileNameString);
  107.     }

  108.     /**
  109.      * Constructs a new regular expression filter for a compiled regular expression
  110.      *
  111.      * @param pattern regular expression to match.
  112.      * @param pathToString How convert a path to a string.
  113.      * @throws NullPointerException if the pattern is null.
  114.      * @since 2.10.0
  115.      */
  116.     public RegexFileFilter(final Pattern pattern, final Function<Path, String> pathToString) {
  117.         Objects.requireNonNull(pattern, "pattern");
  118.         this.pattern = pattern;
  119.         this.pathToString = pathToString != null ? pathToString : Objects::toString;
  120.     }

  121.     /**
  122.      * Constructs a new regular expression filter.
  123.      *
  124.      * @param pattern regular string expression to match
  125.      * @throws NullPointerException if the pattern is null
  126.      */
  127.     public RegexFileFilter(final String pattern) {
  128.         this(pattern, 0);
  129.     }

  130.     /**
  131.      * Constructs a new regular expression filter with the specified flags.
  132.      *
  133.      * @param pattern regular string expression to match
  134.      * @param flags pattern flags - e.g. {@link Pattern#CASE_INSENSITIVE}
  135.      * @throws IllegalArgumentException if the pattern is null
  136.      */
  137.     public RegexFileFilter(final String pattern, final int flags) {
  138.         this(compile(pattern, flags));
  139.     }

  140.     /**
  141.      * Constructs a new regular expression filter with the specified flags case sensitivity.
  142.      *
  143.      * @param pattern regular string expression to match
  144.      * @param ioCase how to handle case sensitivity, null means case-sensitive
  145.      * @throws IllegalArgumentException if the pattern is null
  146.      */
  147.     public RegexFileFilter(final String pattern, final IOCase ioCase) {
  148.         this(compile(pattern, toFlags(ioCase)));
  149.     }

  150.     /**
  151.      * Checks to see if the file name matches one of the regular expressions.
  152.      *
  153.      * @param dir the file directory (ignored)
  154.      * @param name the file name
  155.      * @return true if the file name matches one of the regular expressions
  156.      */
  157.     @Override
  158.     public boolean accept(final File dir, final String name) {
  159.         return pattern.matcher(name).matches();
  160.     }

  161.     /**
  162.      * Checks to see if the file name matches one of the regular expressions.
  163.      *
  164.      * @param path the path
  165.      * @param attributes the path's basic attributes (may be null).
  166.      * @return true if the file name matches one of the regular expressions
  167.      */
  168.     @Override
  169.     public FileVisitResult accept(final Path path, final BasicFileAttributes attributes) {
  170.         final String result = pathToString.apply(path);
  171.         return toFileVisitResult(result != null && pattern.matcher(result).matches());
  172.     }

  173.     /**
  174.      * Returns a debug string.
  175.      *
  176.      * @since 2.10.0
  177.      */
  178.     @Override
  179.     public String toString() {
  180.         return "RegexFileFilter [pattern=" + pattern + "]";
  181.     }

  182. }