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.vfs2.filter;
018
019import java.io.Serializable;
020import java.util.ArrayList;
021import java.util.Arrays;
022import java.util.List;
023
024import org.apache.commons.vfs2.FileFilter;
025import org.apache.commons.vfs2.FileSelectInfo;
026
027/**
028 * Filters file names for a certain prefix.
029 * <p>
030 * For example, to print all files and directories in the current directory
031 * whose name starts with a {@code .}:
032 * </p>
033 *
034 * <pre>
035 * FileSystemManager fsManager = VFS.getManager();
036 * FileObject dir = fsManager.toFileObject(new File(&quot;.&quot;));
037 * FileObject[] files = dir.findFiles(new FileFilterSelector(new PrefixFileFilter(&quot;.&quot;)));
038 * for (int i = 0; i &lt; files.length; i++) {
039 *     System.out.println(files[i]);
040 * }
041 * </pre>
042 *
043 * @author This code was originally ported from Apache Commons IO File Filter
044 * @see "https://commons.apache.org/proper/commons-io/"
045 * @since 2.4
046 */
047public class PrefixFileFilter implements FileFilter, Serializable {
048
049    private static final long serialVersionUID = 1L;
050
051    /** Whether the comparison is case-sensitive. */
052    private final IOCase caseSensitivity;
053
054    /** The file name prefixes to search for. */
055    private final List<String> prefixes;
056
057    /**
058     * Constructs a new Prefix file filter for a list of prefixes specifying
059     * case-sensitivity.
060     *
061     * @param caseSensitivity how to handle case sensitivity, null means
062     *                        case-sensitive
063     * @param prefixes        the prefixes to allow, must not be null
064     */
065    public PrefixFileFilter(final IOCase caseSensitivity, final List<String> prefixes) {
066        if (prefixes == null) {
067            throw new IllegalArgumentException("The list of prefixes must not be null");
068        }
069        this.prefixes = new ArrayList<>(prefixes);
070        this.caseSensitivity = caseSensitivity == null ? IOCase.SENSITIVE : caseSensitivity;
071    }
072
073    /**
074     * Constructs a new Prefix file filter for any of an array of prefixes
075     * specifying case-sensitivity.
076     *
077     * @param prefixes        the prefixes to allow, must not be null
078     * @param caseSensitivity how to handle case sensitivity, null means
079     *                        case-sensitive
080     */
081    public PrefixFileFilter(final IOCase caseSensitivity, final String... prefixes) {
082        if (prefixes == null) {
083            throw new IllegalArgumentException("The array of prefixes must not be null");
084        }
085        this.prefixes = new ArrayList<>(Arrays.asList(prefixes));
086        this.caseSensitivity = caseSensitivity == null ? IOCase.SENSITIVE : caseSensitivity;
087    }
088
089    /**
090     * Constructs a new Prefix file filter for a list of prefixes.
091     *
092     * @param prefixes the prefixes to allow, must not be null
093     */
094    public PrefixFileFilter(final List<String> prefixes) {
095        this(IOCase.SENSITIVE, prefixes);
096    }
097
098    /**
099     * Constructs a new Prefix file filter for any of an array of prefixes.
100     * <p>
101     * The array is not cloned, so could be changed after constructing the instance.
102     * This would be inadvisable however.
103     *
104     * @param prefixes the prefixes to allow, must not be null
105     */
106    public PrefixFileFilter(final String... prefixes) {
107        this(IOCase.SENSITIVE, prefixes);
108    }
109
110    /**
111     * Checks to see if the file name starts with the prefix.
112     *
113     * @param fileSelectInfo the File to check
114     * @return true if the file name starts with one of our prefixes
115     */
116    @Override
117    public boolean accept(final FileSelectInfo fileSelectInfo) {
118        final String name = fileSelectInfo.getFile().getName().getBaseName();
119        return prefixes.stream().anyMatch(prefix -> caseSensitivity.checkStartsWith(name, prefix));
120    }
121
122    /**
123     * Provide a String representation of this file filter.
124     *
125     * @return a String representation
126     */
127    @Override
128    public String toString() {
129        final StringBuilder buffer = new StringBuilder();
130        buffer.append(super.toString());
131        buffer.append("(");
132        if (prefixes != null) {
133            buffer.append(String.join(",", prefixes));
134        }
135        buffer.append(")");
136        return buffer.toString();
137    }
138
139}