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