001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.io.filefilter;
018
019import java.io.File;
020import java.io.Serializable;
021import java.nio.file.FileVisitResult;
022import java.nio.file.Path;
023import java.nio.file.attribute.BasicFileAttributes;
024import java.util.regex.Pattern;
025
026import org.apache.commons.io.IOCase;
027
028/**
029 * Filters files using supplied regular expression(s).
030 * <p>
031 * See java.util.regex.Pattern for regex matching rules.
032 * </p>
033 * <h2>Using Classic IO</h2>
034 * <p>
035 * e.g.
036 *
037 * <pre>
038 * File dir = new File(".");
039 * FileFilter fileFilter = new RegexFileFilter("^.*[tT]est(-\\d+)?\\.java$");
040 * File[] files = dir.listFiles(fileFilter);
041 * for (String file : files) {
042 *     System.out.println(file);
043 * }
044 * </pre>
045 *
046 * <h2>Using NIO</h2>
047 *
048 * <pre>
049 * final Path dir = Paths.get("");
050 * final AccumulatorPathVisitor visitor = AccumulatorPathVisitor.withLongCounters(new RegexFileFilter("^.*[tT]est(-\\d+)?\\.java$"));
051 * //
052 * // Walk one dir
053 * Files.<b>walkFileTree</b>(dir, Collections.emptySet(), 1, visitor);
054 * System.out.println(visitor.getPathCounters());
055 * System.out.println(visitor.getFileList());
056 * //
057 * visitor.getPathCounters().reset();
058 * //
059 * // Walk dir tree
060 * Files.<b>walkFileTree</b>(dir, visitor);
061 * System.out.println(visitor.getPathCounters());
062 * System.out.println(visitor.getDirList());
063 * System.out.println(visitor.getFileList());
064 * </pre>
065 *
066 * @since 1.4
067 */
068public class RegexFileFilter extends AbstractFileFilter implements Serializable {
069
070    private static final long serialVersionUID = 4269646126155225062L;
071    /** The regular expression pattern that will be used to match file names */
072    private final Pattern pattern;
073
074    /**
075     * Construct a new regular expression filter for a compiled regular expression
076     *
077     * @param pattern regular expression to match
078     * @throws IllegalArgumentException if the pattern is null
079     */
080    public RegexFileFilter(final Pattern pattern) {
081        if (pattern == null) {
082            throw new IllegalArgumentException("Pattern is missing");
083        }
084
085        this.pattern = pattern;
086    }
087
088    /**
089     * Construct a new regular expression filter.
090     *
091     * @param pattern regular string expression to match
092     * @throws IllegalArgumentException if the pattern is null
093     */
094    public RegexFileFilter(final String pattern) {
095        if (pattern == null) {
096            throw new IllegalArgumentException("Pattern is missing");
097        }
098
099        this.pattern = Pattern.compile(pattern);
100    }
101
102    /**
103     * Construct a new regular expression filter with the specified flags.
104     *
105     * @param pattern regular string expression to match
106     * @param flags pattern flags - e.g. {@link Pattern#CASE_INSENSITIVE}
107     * @throws IllegalArgumentException if the pattern is null
108     */
109    public RegexFileFilter(final String pattern, final int flags) {
110        if (pattern == null) {
111            throw new IllegalArgumentException("Pattern is missing");
112        }
113        this.pattern = Pattern.compile(pattern, flags);
114    }
115
116    /**
117     * Construct a new regular expression filter with the specified flags case sensitivity.
118     *
119     * @param pattern regular string expression to match
120     * @param caseSensitivity how to handle case sensitivity, null means case-sensitive
121     * @throws IllegalArgumentException if the pattern is null
122     */
123    public RegexFileFilter(final String pattern, final IOCase caseSensitivity) {
124        if (pattern == null) {
125            throw new IllegalArgumentException("Pattern is missing");
126        }
127        int flags = 0;
128        if (caseSensitivity != null && !caseSensitivity.isCaseSensitive()) {
129            flags = Pattern.CASE_INSENSITIVE;
130        }
131        this.pattern = Pattern.compile(pattern, flags);
132    }
133
134    /**
135     * Checks to see if the file name matches one of the regular expressions.
136     *
137     * @param dir the file directory (ignored)
138     * @param name the file name
139     * @return true if the file name matches one of the regular expressions
140     */
141    @Override
142    public boolean accept(final File dir, final String name) {
143        return pattern.matcher(name).matches();
144    }
145
146    /**
147     * Checks to see if the file name matches one of the regular expressions.
148     *
149     * @param path the path
150     * @param attributes the path attributes
151     * @return true if the file name matches one of the regular expressions
152     */
153    @Override
154    public FileVisitResult accept(final Path path, final BasicFileAttributes attributes) {
155        return toFileVisitResult(pattern.matcher(path.toString()).matches(), path);
156    }
157
158}