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