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.nio.file.FileVisitResult; 022import java.nio.file.Path; 023import java.nio.file.attribute.BasicFileAttributes; 024import java.util.ArrayList; 025import java.util.Collections; 026import java.util.List; 027import java.util.Objects; 028import java.util.stream.Stream; 029 030/** 031 * A {@link java.io.FileFilter} providing conditional AND logic across a list of 032 * file filters. This filter returns {@code true} if all filters in the 033 * list return {@code true}. Otherwise, it returns {@code false}. 034 * Checking of the file filter list stops when the first filter returns 035 * {@code false}. 036 * <h2>Deprecating Serialization</h2> 037 * <p> 038 * <em>Serialization is deprecated and will be removed in 3.0.</em> 039 * </p> 040 * 041 * @since 1.0 042 * @see FileFilterUtils#and(IOFileFilter...) 043 */ 044public class AndFileFilter 045 extends AbstractFileFilter 046 implements ConditionalFileFilter, Serializable { 047 048 private static final long serialVersionUID = 7215974688563965257L; 049 050 /** The list of file filters. */ 051 private final List<IOFileFilter> fileFilters; 052 053 /** 054 * Constructs a new empty instance. 055 * 056 * @since 1.1 057 */ 058 public AndFileFilter() { 059 this(0); 060 } 061 062 /** 063 * Constructs a new instance with the given initial list. 064 * 065 * @param initialList the initial list. 066 */ 067 private AndFileFilter(final ArrayList<IOFileFilter> initialList) { 068 this.fileFilters = Objects.requireNonNull(initialList, "initialList"); 069 } 070 071 /** 072 * Constructs a new instance with the given initial capacity. 073 * 074 * @param initialCapacity the initial capacity. 075 */ 076 private AndFileFilter(final int initialCapacity) { 077 this(new ArrayList<>(initialCapacity)); 078 } 079 080 /** 081 * Constructs a new instance for the give filters. 082 * @param fileFilters filters to OR. 083 * 084 * @since 2.9.0 085 */ 086 public AndFileFilter(final IOFileFilter... fileFilters) { 087 this(Objects.requireNonNull(fileFilters, "fileFilters").length); 088 addFileFilter(fileFilters); 089 } 090 091 /** 092 * Constructs a new file filter that ANDs the result of other filters. 093 * 094 * @param filter1 the first filter, must second be null 095 * @param filter2 the first filter, must not be null 096 * @throws IllegalArgumentException if either filter is null 097 */ 098 public AndFileFilter(final IOFileFilter filter1, final IOFileFilter filter2) { 099 this(2); 100 addFileFilter(filter1); 101 addFileFilter(filter2); 102 } 103 104 /** 105 * Constructs a new instance of {@link AndFileFilter} 106 * with the specified list of filters. 107 * 108 * @param fileFilters a List of IOFileFilter instances, copied. 109 * @since 1.1 110 */ 111 public AndFileFilter(final List<IOFileFilter> fileFilters) { 112 this(new ArrayList<>(Objects.requireNonNull(fileFilters, "fileFilters"))); 113 } 114 115 /** 116 * {@inheritDoc} 117 */ 118 @Override 119 public boolean accept(final File file) { 120 return !isEmpty() && fileFilters.stream().allMatch(fileFilter -> fileFilter.accept(file)); 121 } 122 123 /** 124 * {@inheritDoc} 125 */ 126 @Override 127 public boolean accept(final File file, final String name) { 128 return !isEmpty() && fileFilters.stream().allMatch(fileFilter -> fileFilter.accept(file, name)); 129 } 130 131 /** 132 * {@inheritDoc} 133 * @since 2.9.0 134 */ 135 @Override 136 public FileVisitResult accept(final Path file, final BasicFileAttributes attributes) { 137 return isEmpty() ? FileVisitResult.TERMINATE 138 : toDefaultFileVisitResult(fileFilters.stream().allMatch(fileFilter -> fileFilter.accept(file, attributes) == FileVisitResult.CONTINUE)); 139 } 140 141 /** 142 * {@inheritDoc} 143 */ 144 @Override 145 public void addFileFilter(final IOFileFilter fileFilter) { 146 this.fileFilters.add(Objects.requireNonNull(fileFilter, "fileFilter")); 147 } 148 149 /** 150 * Adds the given file filters. 151 * 152 * @param fileFilters the filters to add. 153 * @since 2.9.0 154 */ 155 public void addFileFilter(final IOFileFilter... fileFilters) { 156 Stream.of(Objects.requireNonNull(fileFilters, "fileFilters")).forEach(this::addFileFilter); 157 } 158 159 /** 160 * {@inheritDoc} 161 */ 162 @Override 163 public List<IOFileFilter> getFileFilters() { 164 return Collections.unmodifiableList(this.fileFilters); 165 } 166 167 private boolean isEmpty() { 168 return this.fileFilters.isEmpty(); 169 } 170 171 /** 172 * {@inheritDoc} 173 */ 174 @Override 175 public boolean removeFileFilter(final IOFileFilter ioFileFilter) { 176 return this.fileFilters.remove(ioFileFilter); 177 } 178 179 /** 180 * {@inheritDoc} 181 */ 182 @Override 183 public void setFileFilters(final List<IOFileFilter> fileFilters) { 184 this.fileFilters.clear(); 185 this.fileFilters.addAll(fileFilters); 186 } 187 188 /** 189 * Provide a String representation of this file filter. 190 * 191 * @return a String representation 192 */ 193 @Override 194 public String toString() { 195 final StringBuilder buffer = new StringBuilder(); 196 buffer.append(super.toString()); 197 buffer.append("("); 198 append(fileFilters, buffer); 199 buffer.append(")"); 200 return buffer.toString(); 201 } 202 203}