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