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