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.FileFilter;
021import java.io.FilenameFilter;
022import java.util.Arrays;
023import java.util.Collections;
024import java.util.Date;
025import java.util.HashSet;
026import java.util.List;
027import java.util.Objects;
028import java.util.Set;
029import java.util.stream.Collector;
030import java.util.stream.Collectors;
031import java.util.stream.Stream;
032import java.util.stream.StreamSupport;
033
034import org.apache.commons.io.FileUtils;
035import org.apache.commons.io.IOCase;
036
037/**
038 * Useful utilities for working with file filters. It provides access to most
039 * file filter implementations in this package so you don't have to import
040 * every class you use.
041 *
042 * @since 1.0
043 */
044public class FileFilterUtils {
045
046    /* Constructed on demand and then cached */
047    private static final IOFileFilter CVS_FILTER = notFileFilter(
048            and(directoryFileFilter(), nameFileFilter("CVS")));
049
050    /* Constructed on demand and then cached */
051    private static final IOFileFilter SVN_FILTER = notFileFilter(
052            and(directoryFileFilter(), nameFileFilter(".svn")));
053
054    /**
055     * Returns a filter that returns true if the file was last modified before
056     * or at the specified cutoff date.
057     *
058     * @param cutoffDate  the time threshold
059     * @return an appropriately configured age file filter
060     * @see AgeFileFilter
061     * @since 1.2
062     */
063    public static IOFileFilter ageFileFilter(final Date cutoffDate) {
064        return new AgeFileFilter(cutoffDate);
065    }
066
067    /**
068     * Returns a filter that filters files based on a cutoff date.
069     *
070     * @param cutoffDate  the time threshold
071     * @param acceptOlder  if true, older files get accepted, if false, newer
072     * @return an appropriately configured age file filter
073     * @see AgeFileFilter
074     * @since 1.2
075     */
076    public static IOFileFilter ageFileFilter(final Date cutoffDate, final boolean acceptOlder) {
077        return new AgeFileFilter(cutoffDate, acceptOlder);
078    }
079
080    /**
081     * Returns a filter that returns true if the file was last modified before
082     * or at the same time as the specified reference file.
083     *
084     * @param cutoffReference  the file whose last modification
085     *        time is used as the threshold age of the files
086     * @return an appropriately configured age file filter
087     * @see AgeFileFilter
088     * @since 1.2
089     */
090    public static IOFileFilter ageFileFilter(final File cutoffReference) {
091        return new AgeFileFilter(cutoffReference);
092    }
093
094    /**
095     * Returns a filter that filters files based on a cutoff reference file.
096     *
097     * @param cutoffReference  the file whose last modification
098     *        time is used as the threshold age of the files
099     * @param acceptOlder  if true, older files get accepted, if false, newer
100     * @return an appropriately configured age file filter
101     * @see AgeFileFilter
102     * @since 1.2
103     */
104    public static IOFileFilter ageFileFilter(final File cutoffReference, final boolean acceptOlder) {
105        return new AgeFileFilter(cutoffReference, acceptOlder);
106    }
107
108    /**
109     * Returns a filter that returns true if the file was last modified before
110     * or at the specified cutoff time.
111     *
112     * @param cutoffMillis  the time threshold
113     * @return an appropriately configured age file filter
114     * @see AgeFileFilter
115     * @since 1.2
116     */
117    public static IOFileFilter ageFileFilter(final long cutoffMillis) {
118        return new AgeFileFilter(cutoffMillis);
119    }
120
121    /**
122     * Returns a filter that filters files based on a cutoff time.
123     *
124     * @param cutoffMillis  the time threshold
125     * @param acceptOlder  if true, older files get accepted, if false, newer
126     * @return an appropriately configured age file filter
127     * @see AgeFileFilter
128     * @since 1.2
129     */
130    public static IOFileFilter ageFileFilter(final long cutoffMillis, final boolean acceptOlder) {
131        return new AgeFileFilter(cutoffMillis, acceptOlder);
132    }
133
134    /**
135     * Returns a filter that ANDs the specified filters.
136     *
137     * @param filters the IOFileFilters that will be ANDed together.
138     * @return a filter that ANDs the specified filters
139     * @throws IllegalArgumentException if the filters are null or contain a
140     *         null value.
141     * @see AndFileFilter
142     * @since 2.0
143     */
144    public static IOFileFilter and(final IOFileFilter... filters) {
145        return new AndFileFilter(toList(filters));
146    }
147
148    /**
149     * Returns a filter that ANDs the two specified filters.
150     *
151     * @param filter1  the first filter
152     * @param filter2  the second filter
153     * @return a filter that ANDs the two specified filters
154     * @see #and(IOFileFilter...)
155     * @see AndFileFilter
156     * @deprecated use {@link #and(IOFileFilter...)}
157     */
158    @Deprecated
159    public static IOFileFilter andFileFilter(final IOFileFilter filter1, final IOFileFilter filter2) {
160        return new AndFileFilter(filter1, filter2);
161    }
162
163    /**
164     * Returns an {@link IOFileFilter} that wraps the
165     * {@link FileFilter} instance.
166     *
167     * @param filter  the filter to be wrapped
168     * @return a new filter that implements IOFileFilter
169     * @see DelegateFileFilter
170     */
171    public static IOFileFilter asFileFilter(final FileFilter filter) {
172        return new DelegateFileFilter(filter);
173    }
174
175    /**
176     * Returns an {@link IOFileFilter} that wraps the
177     * {@link FilenameFilter} instance.
178     *
179     * @param filter  the filter to be wrapped
180     * @return a new filter that implements IOFileFilter
181     * @see DelegateFileFilter
182     */
183    public static IOFileFilter asFileFilter(final FilenameFilter filter) {
184        return new DelegateFileFilter(filter);
185    }
186
187    /**
188     * Returns a filter that checks if the file is a directory.
189     *
190     * @return file filter that accepts only directories and not files
191     * @see DirectoryFileFilter#DIRECTORY
192     */
193    public static IOFileFilter directoryFileFilter() {
194        return DirectoryFileFilter.DIRECTORY;
195    }
196
197    /**
198     * Returns a filter that always returns false.
199     *
200     * @return a false filter
201     * @see FalseFileFilter#FALSE
202     */
203    public static IOFileFilter falseFileFilter() {
204        return FalseFileFilter.FALSE;
205    }
206
207    /**
208     * Returns a filter that checks if the file is a file (and not a directory).
209     *
210     * @return file filter that accepts only files and not directories
211     * @see FileFileFilter#INSTANCE
212     */
213    public static IOFileFilter fileFileFilter() {
214        return FileFileFilter.INSTANCE;
215    }
216
217    /**
218     * <p>
219     * Applies an {@link IOFileFilter} to the provided {@link File}
220     * objects. The resulting array is a subset of the original file list that
221     * matches the provided filter.
222     * </p>
223     *
224     * <pre>
225     * Set&lt;File&gt; allFiles = ...
226     * Set&lt;File&gt; javaFiles = FileFilterUtils.filterSet(allFiles,
227     *     FileFilterUtils.suffixFileFilter(".java"));
228     * </pre>
229     * @param filter the filter to apply to the set of files.
230     * @param files the array of files to apply the filter to.
231     * @return a subset of {@code files} that is accepted by the
232     *         file filter.
233     * @throws NullPointerException if the filter is {@code null}
234     *         or {@code files} contains a {@code null} value.
235     *
236     * @since 2.0
237     */
238    public static File[] filter(final IOFileFilter filter, final File... files) {
239        Objects.requireNonNull(filter, "filter");
240        if (files == null) {
241            return FileUtils.EMPTY_FILE_ARRAY;
242        }
243        return filterFiles(filter, Stream.of(files), Collectors.toList()).toArray(FileUtils.EMPTY_FILE_ARRAY);
244    }
245
246    /**
247     * <p>
248     * Applies an {@link IOFileFilter} to the provided {@link File}
249     * objects. The resulting array is a subset of the original file list that
250     * matches the provided filter.
251     * </p>
252     *
253     * <p>
254     * The {@link Set} returned by this method is not guaranteed to be thread safe.
255     * </p>
256     *
257     * <pre>
258     * Set&lt;File&gt; allFiles = ...
259     * Set&lt;File&gt; javaFiles = FileFilterUtils.filterSet(allFiles,
260     *     FileFilterUtils.suffixFileFilter(".java"));
261     * </pre>
262     * @param filter the filter to apply to the set of files.
263     * @param files the array of files to apply the filter to.
264     * @return a subset of {@code files} that is accepted by the
265     *         file filter.
266     * @throws IllegalArgumentException if the filter is {@code null}
267     *         or {@code files} contains a {@code null} value.
268     *
269     * @since 2.0
270     */
271    public static File[] filter(final IOFileFilter filter, final Iterable<File> files) {
272        return filterList(filter, files).toArray(FileUtils.EMPTY_FILE_ARRAY);
273    }
274
275    /**
276     * <p>
277     * Applies an {@link IOFileFilter} to the provided {@link File} stream and collects the accepted files.
278     * </p>
279     *
280     * @param filter the filter to apply to the stream of files.
281     * @param stream the stream of files on which to apply the filter.
282     * @param collector how to collect the end result.
283     * @param <R> the return type.
284     * @param <A> the mutable accumulation type of the reduction operation (often hidden as an implementation detail)
285     * @return a subset of files from the stream that is accepted by the filter.
286     * @throws NullPointerException if the filter is {@code null}.
287     */
288    private static <R, A> R filterFiles(final IOFileFilter filter, final Stream<File> stream,
289        final Collector<? super File, A, R> collector) {
290        Objects.requireNonNull(filter, "filter");
291        Objects.requireNonNull(collector, "collector");
292        if (stream == null) {
293            return Stream.<File>empty().collect(collector);
294        }
295        return stream.filter(filter::accept).collect(collector);
296    }
297
298    /**
299     * <p>
300     * Applies an {@link IOFileFilter} to the provided {@link File}
301     * objects. The resulting list is a subset of the original files that
302     * matches the provided filter.
303     * </p>
304     *
305     * <p>
306     * The {@link List} returned by this method is not guaranteed to be thread safe.
307     * </p>
308     *
309     * <pre>
310     * List&lt;File&gt; filesAndDirectories = ...
311     * List&lt;File&gt; directories = FileFilterUtils.filterList(filesAndDirectories,
312     *     FileFilterUtils.directoryFileFilter());
313     * </pre>
314     * @param filter the filter to apply to each files in the list.
315     * @param files the collection of files to apply the filter to.
316     * @return a subset of {@code files} that is accepted by the
317     *         file filter.
318     * @throws IllegalArgumentException if the filter is {@code null}
319     *         or {@code files} contains a {@code null} value.
320     * @since 2.0
321     */
322    public static List<File> filterList(final IOFileFilter filter, final File... files) {
323        return Arrays.asList(filter(filter, files));
324    }
325
326    /**
327     * <p>
328     * Applies an {@link IOFileFilter} to the provided {@link File}
329     * objects. The resulting list is a subset of the original files that
330     * matches the provided filter.
331     * </p>
332     *
333     * <p>
334     * The {@link List} returned by this method is not guaranteed to be thread safe.
335     * </p>
336     *
337     * <pre>
338     * List&lt;File&gt; filesAndDirectories = ...
339     * List&lt;File&gt; directories = FileFilterUtils.filterList(filesAndDirectories,
340     *     FileFilterUtils.directoryFileFilter());
341     * </pre>
342     * @param filter the filter to apply to each files in the list.
343     * @param files the collection of files to apply the filter to.
344     * @return a subset of {@code files} that is accepted by the
345     *         file filter.
346     * @throws IllegalArgumentException if the filter is {@code null}
347     * @since 2.0
348     */
349    public static List<File> filterList(final IOFileFilter filter, final Iterable<File> files) {
350        if (files == null) {
351            return Collections.emptyList();
352        }
353        return filterFiles(filter, StreamSupport.stream(files.spliterator(), false), Collectors.toList());
354    }
355
356    /**
357     * <p>
358     * Applies an {@link IOFileFilter} to the provided {@link File}
359     * objects. The resulting set is a subset of the original file list that
360     * matches the provided filter.
361     * </p>
362     *
363     * <p>
364     * The {@link Set} returned by this method is not guaranteed to be thread safe.
365     * </p>
366     *
367     * <pre>
368     * Set&lt;File&gt; allFiles = ...
369     * Set&lt;File&gt; javaFiles = FileFilterUtils.filterSet(allFiles,
370     *     FileFilterUtils.suffixFileFilter(".java"));
371     * </pre>
372     * @param filter the filter to apply to the set of files.
373     * @param files the collection of files to apply the filter to.
374     * @return a subset of {@code files} that is accepted by the
375     *         file filter.
376     * @throws IllegalArgumentException if the filter is {@code null}
377     *         or {@code files} contains a {@code null} value.
378     *
379     * @since 2.0
380     */
381    public static Set<File> filterSet(final IOFileFilter filter, final File... files) {
382        return new HashSet<>(Arrays.asList(filter(filter, files)));
383    }
384
385    /**
386     * <p>
387     * Applies an {@link IOFileFilter} to the provided {@link File}
388     * objects. The resulting set is a subset of the original file list that
389     * matches the provided filter.
390     * </p>
391     *
392     * <p>
393     * The {@link Set} returned by this method is not guaranteed to be thread safe.
394     * </p>
395     *
396     * <pre>
397     * Set&lt;File&gt; allFiles = ...
398     * Set&lt;File&gt; javaFiles = FileFilterUtils.filterSet(allFiles,
399     *     FileFilterUtils.suffixFileFilter(".java"));
400     * </pre>
401     * @param filter the filter to apply to the set of files.
402     * @param files the collection of files to apply the filter to.
403     * @return a subset of {@code files} that is accepted by the
404     *         file filter.
405     * @throws IllegalArgumentException if the filter is {@code null}
406     * @since 2.0
407     */
408    public static Set<File> filterSet(final IOFileFilter filter, final Iterable<File> files) {
409        if (files == null) {
410            return Collections.emptySet();
411        }
412        return filterFiles(filter, StreamSupport.stream(files.spliterator(), false), Collectors.toSet());
413    }
414
415    /**
416     * Returns a filter that accepts files that begin with the provided magic
417     * number.
418     *
419     * @param magicNumber the magic number (byte sequence) to match at the
420     *        beginning of each file.
421     *
422     * @return an IOFileFilter that accepts files beginning with the provided
423     *         magic number.
424     *
425     * @throws IllegalArgumentException if {@code magicNumber} is
426     *         {@code null} or is of length zero.
427     * @see MagicNumberFileFilter
428     * @since 2.0
429     */
430    public static IOFileFilter magicNumberFileFilter(final byte[] magicNumber) {
431        return new MagicNumberFileFilter(magicNumber);
432    }
433
434    /**
435     * Returns a filter that accepts files that contains the provided magic
436     * number at a specified offset within the file.
437     *
438     * @param magicNumber the magic number (byte sequence) to match at the
439     *        provided offset in each file.
440     * @param offset the offset within the files to look for the magic number.
441     * @return an IOFileFilter that accepts files containing the magic number
442     *         at the specified offset.
443     *
444     * @throws IllegalArgumentException if {@code magicNumber} is
445     *         {@code null}, or contains no bytes, or {@code offset}
446     *         is a negative number.
447     * @see MagicNumberFileFilter
448     * @since 2.0
449     */
450    public static IOFileFilter magicNumberFileFilter(final byte[] magicNumber, final long offset) {
451        return new MagicNumberFileFilter(magicNumber, offset);
452    }
453
454    /**
455     * Returns a filter that accepts files that begin with the provided magic
456     * number.
457     *
458     * @param magicNumber the magic number (byte sequence) to match at the
459     *        beginning of each file.
460     *
461     * @return an IOFileFilter that accepts files beginning with the provided
462     *         magic number.
463     *
464     * @throws IllegalArgumentException if {@code magicNumber} is
465     *         {@code null} or the empty String.
466     * @see MagicNumberFileFilter
467     * @since 2.0
468     */
469    public static IOFileFilter magicNumberFileFilter(final String magicNumber) {
470        return new MagicNumberFileFilter(magicNumber);
471    }
472
473    /**
474     * Returns a filter that accepts files that contains the provided magic
475     * number at a specified offset within the file.
476     *
477     * @param magicNumber the magic number (byte sequence) to match at the
478     *        provided offset in each file.
479     * @param offset the offset within the files to look for the magic number.
480     * @return an IOFileFilter that accepts files containing the magic number
481     *         at the specified offset.
482     *
483     * @throws IllegalArgumentException if {@code magicNumber} is
484     *         {@code null} or the empty String, or if offset is a
485     *         negative number.
486     * @see MagicNumberFileFilter
487     * @since 2.0
488     */
489    public static IOFileFilter magicNumberFileFilter(final String magicNumber, final long offset) {
490        return new MagicNumberFileFilter(magicNumber, offset);
491    }
492
493    /**
494     * Decorates a filter to make it ignore CVS directories.
495     * Passing in {@code null} will return a filter that accepts everything
496     * except CVS directories.
497     *
498     * @param filter  the filter to decorate, null means an unrestricted filter
499     * @return the decorated filter, never null
500     * @since 1.1 (method existed but had a bug in 1.0)
501     */
502    public static IOFileFilter makeCVSAware(final IOFileFilter filter) {
503        return filter == null ? CVS_FILTER : and(filter, CVS_FILTER);
504    }
505
506    /**
507     * Decorates a filter so that it only applies to directories and not to files.
508     *
509     * @param filter  the filter to decorate, null means an unrestricted filter
510     * @return the decorated filter, never null
511     * @see DirectoryFileFilter#DIRECTORY
512     * @since 1.3
513     */
514    public static IOFileFilter makeDirectoryOnly(final IOFileFilter filter) {
515        if (filter == null) {
516            return DirectoryFileFilter.DIRECTORY;
517        }
518        return DirectoryFileFilter.DIRECTORY.and(filter);
519    }
520
521    /**
522     * Decorates a filter so that it only applies to files and not to directories.
523     *
524     * @param filter  the filter to decorate, null means an unrestricted filter
525     * @return the decorated filter, never null
526     * @see FileFileFilter#INSTANCE
527     * @since 1.3
528     */
529    public static IOFileFilter makeFileOnly(final IOFileFilter filter) {
530        if (filter == null) {
531            return FileFileFilter.INSTANCE;
532        }
533        return FileFileFilter.INSTANCE.and(filter);
534    }
535
536    /**
537     * Decorates a filter to make it ignore SVN directories.
538     * Passing in {@code null} will return a filter that accepts everything
539     * except SVN directories.
540     *
541     * @param filter  the filter to decorate, null means an unrestricted filter
542     * @return the decorated filter, never null
543     * @since 1.1
544     */
545    public static IOFileFilter makeSVNAware(final IOFileFilter filter) {
546        return filter == null ? SVN_FILTER : and(filter, SVN_FILTER);
547    }
548
549    /**
550     * Returns a filter that returns true if the file name matches the specified text.
551     *
552     * @param name  the file name
553     * @return a name checking filter
554     * @see NameFileFilter
555     */
556    public static IOFileFilter nameFileFilter(final String name) {
557        return new NameFileFilter(name);
558    }
559
560    /**
561     * Returns a filter that returns true if the file name matches the specified text.
562     *
563     * @param name  the file name
564     * @param ioCase  how to handle case sensitivity, null means case-sensitive
565     * @return a name checking filter
566     * @see NameFileFilter
567     * @since 2.0
568     */
569    public static IOFileFilter nameFileFilter(final String name, final IOCase ioCase) {
570        return new NameFileFilter(name, ioCase);
571    }
572
573    /**
574     * Returns a filter that NOTs the specified filter.
575     *
576     * @param filter  the filter to invert
577     * @return a filter that NOTs the specified filter
578     * @see NotFileFilter
579     */
580    public static IOFileFilter notFileFilter(final IOFileFilter filter) {
581        return filter.negate();
582    }
583
584    /**
585     * Returns a filter that ORs the specified filters.
586     *
587     * @param filters the IOFileFilters that will be ORed together.
588     * @return a filter that ORs the specified filters
589     * @throws IllegalArgumentException if the filters are null or contain a
590     *         null value.
591     * @see OrFileFilter
592     * @since 2.0
593     */
594    public static IOFileFilter or(final IOFileFilter... filters) {
595        return new OrFileFilter(toList(filters));
596    }
597
598    /**
599     * Returns a filter that ORs the two specified filters.
600     *
601     * @param filter1  the first filter
602     * @param filter2  the second filter
603     * @return a filter that ORs the two specified filters
604     * @see #or(IOFileFilter...)
605     * @see OrFileFilter
606     * @deprecated use {@link #or(IOFileFilter...)}
607     */
608    @Deprecated
609    public static IOFileFilter orFileFilter(final IOFileFilter filter1, final IOFileFilter filter2) {
610        return new OrFileFilter(filter1, filter2);
611    }
612
613    /**
614     * Returns a filter that returns true if the file name starts with the specified text.
615     *
616     * @param prefix  the file name prefix
617     * @return a prefix checking filter
618     * @see PrefixFileFilter
619     */
620    public static IOFileFilter prefixFileFilter(final String prefix) {
621        return new PrefixFileFilter(prefix);
622    }
623
624    /**
625     * Returns a filter that returns true if the file name starts with the specified text.
626     *
627     * @param prefix  the file name prefix
628     * @param ioCase  how to handle case sensitivity, null means case-sensitive
629     * @return a prefix checking filter
630     * @see PrefixFileFilter
631     * @since 2.0
632     */
633    public static IOFileFilter prefixFileFilter(final String prefix, final IOCase ioCase) {
634        return new PrefixFileFilter(prefix, ioCase);
635    }
636
637    /**
638     * Returns a filter that returns true if the file is bigger than a certain size.
639     *
640     * @param threshold  the file size threshold
641     * @return an appropriately configured SizeFileFilter
642     * @see SizeFileFilter
643     * @since 1.2
644     */
645    public static IOFileFilter sizeFileFilter(final long threshold) {
646        return new SizeFileFilter(threshold);
647    }
648
649    /**
650     * Returns a filter that filters based on file size.
651     *
652     * @param threshold  the file size threshold
653     * @param acceptLarger  if true, larger files get accepted, if false, smaller
654     * @return an appropriately configured SizeFileFilter
655     * @see SizeFileFilter
656     * @since 1.2
657     */
658    public static IOFileFilter sizeFileFilter(final long threshold, final boolean acceptLarger) {
659        return new SizeFileFilter(threshold, acceptLarger);
660    }
661
662    /**
663     * Returns a filter that accepts files whose size is &gt;= minimum size
664     * and &lt;= maximum size.
665     *
666     * @param minSizeInclusive the minimum file size (inclusive)
667     * @param maxSizeInclusive the maximum file size (inclusive)
668     * @return an appropriately configured IOFileFilter
669     * @see SizeFileFilter
670     * @since 1.3
671     */
672    public static IOFileFilter sizeRangeFileFilter(final long minSizeInclusive, final long maxSizeInclusive) {
673        final IOFileFilter minimumFilter = new SizeFileFilter(minSizeInclusive, true);
674        final IOFileFilter maximumFilter = new SizeFileFilter(maxSizeInclusive + 1L, false);
675        return minimumFilter.and(maximumFilter);
676    }
677
678    /**
679     * Returns a filter that returns true if the file name ends with the specified text.
680     *
681     * @param suffix  the file name suffix
682     * @return a suffix checking filter
683     * @see SuffixFileFilter
684     */
685    public static IOFileFilter suffixFileFilter(final String suffix) {
686        return new SuffixFileFilter(suffix);
687    }
688
689    /**
690     * Returns a filter that returns true if the file name ends with the specified text.
691     *
692     * @param suffix  the file name suffix
693     * @param ioCase  how to handle case sensitivity, null means case-sensitive
694     * @return a suffix checking filter
695     * @see SuffixFileFilter
696     * @since 2.0
697     */
698    public static IOFileFilter suffixFileFilter(final String suffix, final IOCase ioCase) {
699        return new SuffixFileFilter(suffix, ioCase);
700    }
701
702    /**
703     * Create a List of file filters.
704     *
705     * @param filters The file filters
706     * @return The list of file filters
707     * @throws NullPointerException if the filters are null or contain a
708     *         null value.
709     * @since 2.0
710     */
711    public static List<IOFileFilter> toList(final IOFileFilter... filters) {
712        return Stream.of(Objects.requireNonNull(filters, "filters")).map(Objects::requireNonNull).collect(Collectors.toList());
713    }
714
715    /**
716     * Returns a filter that always returns true.
717     *
718     * @return a true filter
719     * @see TrueFileFilter#TRUE
720     */
721    public static IOFileFilter trueFileFilter() {
722        return TrueFileFilter.TRUE;
723    }
724
725    /**
726     * FileFilterUtils is not normally instantiated.
727     */
728    public FileFilterUtils() {
729    }
730
731}