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