View Javadoc
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  
19  import java.io.File;
20  import java.io.Serializable;
21  import java.nio.file.FileVisitResult;
22  import java.nio.file.Path;
23  import java.nio.file.attribute.BasicFileAttributes;
24  import java.util.Objects;
25  import java.util.function.Function;
26  import java.util.regex.Pattern;
27  
28  import org.apache.commons.io.IOCase;
29  import org.apache.commons.io.file.PathUtils;
30  
31  /**
32   * Filters files using supplied regular expression(s).
33   * <p>
34   * See java.util.regex.Pattern for regex matching rules.
35   * </p>
36   * <h2>Using Classic IO</h2>
37   * <p>
38   * e.g.
39   *
40   * <pre>
41   * File dir = FileUtils.current();
42   * FileFilter fileFilter = new RegexFileFilter("^.*[tT]est(-\\d+)?\\.java$");
43   * File[] files = dir.listFiles(fileFilter);
44   * for (String file : files) {
45   *     System.out.println(file);
46   * }
47   * </pre>
48   *
49   * <h2>Using NIO</h2>
50   *
51   * <pre>
52   * final Path dir = PathUtils.current();
53   * final AccumulatorPathVisitor visitor = AccumulatorPathVisitor.withLongCounters(new RegexFileFilter("^.*[tT]est(-\\d+)?\\.java$"));
54   * //
55   * // Walk one dir
56   * Files.<b>walkFileTree</b>(dir, Collections.emptySet(), 1, visitor);
57   * System.out.println(visitor.getPathCounters());
58   * System.out.println(visitor.getFileList());
59   * //
60   * visitor.getPathCounters().reset();
61   * //
62   * // Walk dir tree
63   * Files.<b>walkFileTree</b>(dir, visitor);
64   * System.out.println(visitor.getPathCounters());
65   * System.out.println(visitor.getDirList());
66   * System.out.println(visitor.getFileList());
67   * </pre>
68   * <h2>Deprecating Serialization</h2>
69   * <p>
70   * <em>Serialization is deprecated and will be removed in 3.0.</em>
71   * </p>
72   *
73   * @since 1.4
74   */
75  public class RegexFileFilter extends AbstractFileFilter implements Serializable {
76  
77      private static final long serialVersionUID = 4269646126155225062L;
78  
79      /**
80       * Compiles the given pattern source.
81       *
82       * @param pattern the source pattern.
83       * @param flags the compilation flags.
84       * @return a new Pattern.
85       */
86      private static Pattern compile(final String pattern, final int flags) {
87          Objects.requireNonNull(pattern, "pattern");
88          return Pattern.compile(pattern, flags);
89      }
90  
91      /**
92       * Converts IOCase to Pattern compilation flags.
93       *
94       * @param ioCase case-sensitivity.
95       * @return Pattern compilation flags.
96       */
97      private static int toFlags(final IOCase ioCase) {
98          return IOCase.isCaseSensitive(ioCase) ? 0 : Pattern.CASE_INSENSITIVE;
99      }
100 
101     /** The regular expression pattern that will be used to match file names. */
102     private final Pattern pattern;
103 
104     /** How convert a path to a string. */
105     private transient final Function<Path, String> pathToString;
106 
107     /**
108      * Constructs a new regular expression filter for a compiled regular expression
109      *
110      * @param pattern regular expression to match.
111      * @throws NullPointerException if the pattern is null.
112      */
113     @SuppressWarnings("unchecked")
114     public RegexFileFilter(final Pattern pattern) {
115         this(pattern, (Function<Path, String> & Serializable) PathUtils::getFileNameString);
116     }
117 
118     /**
119      * Constructs a new regular expression filter for a compiled regular expression
120      *
121      * @param pattern regular expression to match.
122      * @param pathToString How convert a path to a string.
123      * @throws NullPointerException if the pattern is null.
124      * @since 2.10.0
125      */
126     public RegexFileFilter(final Pattern pattern, final Function<Path, String> pathToString) {
127         Objects.requireNonNull(pattern, "pattern");
128         this.pattern = pattern;
129         this.pathToString = pathToString != null ? pathToString : Objects::toString;
130     }
131 
132     /**
133      * Constructs a new regular expression filter.
134      *
135      * @param pattern regular string expression to match
136      * @throws NullPointerException if the pattern is null
137      */
138     public RegexFileFilter(final String pattern) {
139         this(pattern, 0);
140     }
141 
142     /**
143      * Constructs a new regular expression filter with the specified flags.
144      *
145      * @param pattern regular string expression to match
146      * @param flags pattern flags - e.g. {@link Pattern#CASE_INSENSITIVE}
147      * @throws IllegalArgumentException if the pattern is null
148      */
149     public RegexFileFilter(final String pattern, final int flags) {
150         this(compile(pattern, flags));
151     }
152 
153     /**
154      * Constructs a new regular expression filter with the specified flags case sensitivity.
155      *
156      * @param pattern regular string expression to match
157      * @param ioCase how to handle case sensitivity, null means case-sensitive
158      * @throws IllegalArgumentException if the pattern is null
159      */
160     public RegexFileFilter(final String pattern, final IOCase ioCase) {
161         this(compile(pattern, toFlags(ioCase)));
162     }
163 
164     /**
165      * Checks to see if the file name matches one of the regular expressions.
166      *
167      * @param dir the file directory (ignored)
168      * @param name the file name
169      * @return true if the file name matches one of the regular expressions
170      */
171     @Override
172     public boolean accept(final File dir, final String name) {
173         return pattern.matcher(name).matches();
174     }
175 
176     /**
177      * Checks to see if the file name matches one of the regular expressions.
178      *
179      * @param path the path
180      * @param attributes the path attributes
181      * @return true if the file name matches one of the regular expressions
182      */
183     @Override
184     public FileVisitResult accept(final Path path, final BasicFileAttributes attributes) {
185         final String result = pathToString.apply(path);
186         return toFileVisitResult(result != null && pattern.matcher(result).matches());
187     }
188 
189     /**
190      * Returns a debug string.
191      *
192      * @since 2.10.0
193      */
194     @Override
195     public String toString() {
196         return "RegexFileFilter [pattern=" + pattern + "]";
197     }
198 
199 }