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.Serializable;
021import java.util.ArrayList;
022import java.util.Collections;
023import java.util.List;
024
025/**
026 * A {@link java.io.FileFilter} providing conditional AND logic across a list of
027 * file filters. This filter returns {@code true} if all filters in the
028 * list return {@code true}. Otherwise, it returns {@code false}.
029 * Checking of the file filter list stops when the first filter returns
030 * {@code false}.
031 *
032 * @since 1.0
033 * @version $Id: AndFileFilter.java 1642757 2014-12-01 21:09:30Z sebb $
034 *
035 * @see FileFilterUtils#and(IOFileFilter...)
036 */
037public class AndFileFilter
038        extends AbstractFileFilter
039        implements ConditionalFileFilter, Serializable {
040
041    private static final long serialVersionUID = 7215974688563965257L;
042
043    /** The list of file filters. */
044    private final List<IOFileFilter> fileFilters;
045
046    /**
047     * Constructs a new instance of <code>AndFileFilter</code>.
048     *
049     * @since 1.1
050     */
051    public AndFileFilter() {
052        this.fileFilters = new ArrayList<IOFileFilter>();
053    }
054
055    /**
056     * Constructs a new instance of <code>AndFileFilter</code>
057     * with the specified list of filters.
058     *
059     * @param fileFilters  a List of IOFileFilter instances, copied, null ignored
060     * @since 1.1
061     */
062    public AndFileFilter(final List<IOFileFilter> fileFilters) {
063        if (fileFilters == null) {
064            this.fileFilters = new ArrayList<IOFileFilter>();
065        } else {
066            this.fileFilters = new ArrayList<IOFileFilter>(fileFilters);
067        }
068    }
069
070    /**
071     * Constructs a new file filter that ANDs the result of two other filters.
072     *
073     * @param filter1  the first filter, must not be null
074     * @param filter2  the second filter, must not be null
075     * @throws IllegalArgumentException if either filter is null
076     */
077    public AndFileFilter(final IOFileFilter filter1, final IOFileFilter filter2) {
078        if (filter1 == null || filter2 == null) {
079            throw new IllegalArgumentException("The filters must not be null");
080        }
081        this.fileFilters = new ArrayList<IOFileFilter>(2);
082        addFileFilter(filter1);
083        addFileFilter(filter2);
084    }
085
086    /**
087     * {@inheritDoc}
088     */
089    public void addFileFilter(final IOFileFilter ioFileFilter) {
090        this.fileFilters.add(ioFileFilter);
091    }
092
093    /**
094     * {@inheritDoc}
095     */
096    public List<IOFileFilter> getFileFilters() {
097        return Collections.unmodifiableList(this.fileFilters);
098    }
099
100    /**
101     * {@inheritDoc}
102     */
103    public boolean removeFileFilter(final IOFileFilter ioFileFilter) {
104        return this.fileFilters.remove(ioFileFilter);
105    }
106
107    /**
108     * {@inheritDoc}
109     */
110    public void setFileFilters(final List<IOFileFilter> fileFilters) {
111        this.fileFilters.clear();
112        this.fileFilters.addAll(fileFilters);
113    }
114
115    /**
116     * {@inheritDoc}
117     */
118    @Override
119    public boolean accept(final File file) {
120        if (this.fileFilters.isEmpty()) {
121            return false;
122        }
123        for (final IOFileFilter fileFilter : fileFilters) {
124            if (!fileFilter.accept(file)) {
125                return false;
126            }
127        }
128        return true;
129    }
130
131    /**
132     * {@inheritDoc}
133     */
134    @Override
135    public boolean accept(final File file, final String name) {
136        if (this.fileFilters.isEmpty()) {
137            return false;
138        }
139        for (final IOFileFilter fileFilter : fileFilters) {
140            if (!fileFilter.accept(file, name)) {
141                return false;
142            }
143        }
144        return true;
145    }
146
147    /**
148     * Provide a String representaion of this file filter.
149     *
150     * @return a String representaion
151     */
152    @Override
153    public String toString() {
154        final StringBuilder buffer = new StringBuilder();
155        buffer.append(super.toString());
156        buffer.append("(");
157        if (fileFilters != null) {
158            for (int i = 0; i < fileFilters.size(); i++) {
159                if (i > 0) {
160                    buffer.append(",");
161                }
162                final Object filter = fileFilters.get(i);
163                buffer.append(filter == null ? "null" : filter.toString());
164            }
165        }
166        buffer.append(")");
167        return buffer.toString();
168    }
169
170}