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    *      https://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.List;
25  import java.util.Objects;
26  import java.util.stream.Stream;
27  
28  import org.apache.commons.io.IOCase;
29  import org.apache.commons.io.file.PathUtils;
30  
31  /**
32   * Filters file names for a certain prefix.
33   * <p>
34   * For example, to print all files and directories in the
35   * current directory whose name starts with {@code Test}:
36   * </p>
37   * <h2>Using Classic IO</h2>
38   * <pre>
39   * File dir = FileUtils.current();
40   * String[] files = dir.list(new PrefixFileFilter("Test"));
41   * for (String file : files) {
42   *     System.out.println(file);
43   * }
44   * </pre>
45   *
46   * <h2>Using NIO</h2>
47   * <pre>
48   * final Path dir = PathUtils.current();
49   * final AccumulatorPathVisitor visitor = AccumulatorPathVisitor.withLongCounters(new PrefixFileFilter("Test"));
50   * //
51   * // Walk one directory
52   * Files.<strong>walkFileTree</strong>(dir, Collections.emptySet(), 1, visitor);
53   * System.out.println(visitor.getPathCounters());
54   * System.out.println(visitor.getFileList());
55   * //
56   * visitor.getPathCounters().reset();
57   * //
58   * // Walk directory tree
59   * Files.<strong>walkFileTree</strong>(dir, visitor);
60   * System.out.println(visitor.getPathCounters());
61   * System.out.println(visitor.getDirList());
62   * System.out.println(visitor.getFileList());
63   * </pre>
64   * <h2>Deprecating Serialization</h2>
65   * <p>
66   * <em>Serialization is deprecated and will be removed in 3.0.</em>
67   * </p>
68   *
69   * @since 1.0
70   * @see FileFilterUtils#prefixFileFilter(String)
71   * @see FileFilterUtils#prefixFileFilter(String, IOCase)
72   */
73  public class PrefixFileFilter extends AbstractFileFilter implements Serializable {
74  
75      private static final long serialVersionUID = 8533897440809599867L;
76  
77      /** The file name prefixes to search for */
78      private final String[] prefixes;
79  
80      /** Whether the comparison is case-sensitive. */
81      private final IOCase isCase;
82  
83      /**
84       * Constructs a new Prefix file filter for a list of prefixes.
85       *
86       * @param prefixes  the prefixes to allow, must not be null.
87       * @throws NullPointerException if the prefix list is null.
88       * @throws ClassCastException if the list does not contain Strings.
89       */
90      public PrefixFileFilter(final List<String> prefixes) {
91          this(prefixes, IOCase.SENSITIVE);
92      }
93  
94      /**
95       * Constructs a new Prefix file filter for a list of prefixes
96       * specifying case-sensitivity.
97       *
98       * @param prefixes  the prefixes to allow, must not be null.
99       * @param ioCase  how to handle case sensitivity, null means case-sensitive.
100      * @throws NullPointerException if the prefix list is null.
101      * @throws ClassCastException if the list does not contain Strings.
102      * @since 1.4
103      */
104     public PrefixFileFilter(final List<String> prefixes, final IOCase ioCase) {
105         Objects.requireNonNull(prefixes, "prefixes");
106         this.prefixes = prefixes.toArray(EMPTY_STRING_ARRAY);
107         this.isCase = IOCase.value(ioCase, IOCase.SENSITIVE);
108     }
109 
110     /**
111      * Constructs a new Prefix file filter for a single prefix.
112      *
113      * @param prefix  the prefix to allow, must not be null.
114      * @throws IllegalArgumentException if the prefix is null.
115      */
116     public PrefixFileFilter(final String prefix) {
117         this(prefix, IOCase.SENSITIVE);
118     }
119 
120     /**
121      * Constructs a new Prefix file filter for any of an array of prefixes.
122      * <p>
123      * The array is not cloned, so could be changed after constructing the
124      * instance. This would be inadvisable however.
125      * </p>
126      *
127      * @param prefixes  the prefixes to allow, must not be null.
128      * @throws IllegalArgumentException if the prefix array is null.
129      */
130     public PrefixFileFilter(final String... prefixes) {
131         this(prefixes, IOCase.SENSITIVE);
132     }
133 
134     /**
135      * Constructs a new Prefix file filter for a single prefix
136      * specifying case-sensitivity.
137      *
138      * @param prefix  the prefix to allow, must not be null.
139      * @param ioCase  how to handle case sensitivity, null means case-sensitive.
140      * @throws IllegalArgumentException if the prefix is null.
141      * @since 1.4
142      */
143     public PrefixFileFilter(final String prefix, final IOCase ioCase) {
144         Objects.requireNonNull(prefix, "prefix");
145         this.prefixes = new String[] {prefix};
146         this.isCase = IOCase.value(ioCase, IOCase.SENSITIVE);
147     }
148 
149     /**
150      * Constructs a new Prefix file filter for any of an array of prefixes
151      * specifying case-sensitivity.
152      *
153      * @param prefixes  the prefixes to allow, must not be null.
154      * @param ioCase  how to handle case sensitivity, null means case-sensitive.
155      * @throws IllegalArgumentException if the prefix is null.
156      * @since 1.4
157      */
158     public PrefixFileFilter(final String[] prefixes, final IOCase ioCase) {
159         Objects.requireNonNull(prefixes, "prefixes");
160         this.prefixes = prefixes.clone();
161         this.isCase = IOCase.value(ioCase, IOCase.SENSITIVE);
162     }
163 
164     /**
165      * Tests to see if the file name starts with the prefix.
166      *
167      * @param file  the File to check.
168      * @return true if the file name starts with one of our prefixes.
169      */
170     @Override
171     public boolean accept(final File file) {
172         return accept(file == null ? null : file.getName());
173     }
174 
175     /**
176      * Tests to see if the file name starts with the prefix.
177      *
178      * @param file  the File directory.
179      * @param name  the file name.
180      * @return true if the file name starts with one of our prefixes.
181      */
182     @Override
183     public boolean accept(final File file, final String name) {
184         return accept(name);
185     }
186 
187     /**
188      * Tests to see if the file name starts with the prefix.
189      *
190      * @param file  the File to check.
191      * @param attributes the path's basic attributes (may be null).
192      * @return true if the file name starts with one of our prefixes.
193      * @since 2.9.0
194      */
195     @Override
196     public FileVisitResult accept(final Path file, final BasicFileAttributes attributes) {
197         return toFileVisitResult(accept(PathUtils.getFileName(file, Path::toFile)));
198     }
199 
200     private boolean accept(final String name) {
201         return Stream.of(prefixes).anyMatch(prefix -> isCase.checkStartsWith(name, prefix));
202     }
203 
204     /**
205      * Provides a String representation of this file filter.
206      *
207      * @return a String representation.
208      */
209     @Override
210     public String toString() {
211         final StringBuilder buffer = new StringBuilder();
212         buffer.append(super.toString());
213         buffer.append("(");
214         append(prefixes, buffer);
215         buffer.append(")");
216         return buffer.toString();
217     }
218 
219 }