001/** 002 * Powerunit - A JDK1.8 test framework 003 * Copyright (C) 2014 Mathieu Boretti. 004 * 005 * This file is part of Powerunit 006 * 007 * Powerunit is free software: you can redistribute it and/or modify 008 * it under the terms of the GNU General Public License as published by 009 * the Free Software Foundation, either version 3 of the License, or 010 * (at your option) any later version. 011 * 012 * Powerunit is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 015 * GNU General Public License for more details. 016 * 017 * You should have received a copy of the GNU General Public License 018 * along with Powerunit. If not, see <http://www.gnu.org/licenses/>. 019 */ 020package ch.powerunit.extensions.exceptions; 021 022import static ch.powerunit.extensions.exceptions.Constants.verifyExceptionMapper; 023import static ch.powerunit.extensions.exceptions.Constants.verifyPredicate; 024import static java.util.Objects.requireNonNull; 025 026import java.io.File; 027import java.io.FileFilter; 028import java.util.function.Function; 029import java.util.function.Supplier; 030 031/** 032 * A filter for abstract pathnames and may throw an exception. 033 * <h3>General contract</h3> 034 * <ul> 035 * <li><b>{@link #accept(File) boolean accept(File path) throws 036 * E}</b> - The functional method.</li> 037 * <li><b>uncheck</b> - Return a {@code FileFilter}</li> 038 * <li><b>lift</b> - Return a {@code FileFilter}</li> 039 * <li><b>ignore</b> - Return a {@code FileFilter}</li> 040 * </ul> 041 * 042 * @see FileFilter 043 * @param <E> 044 * the type of the potential exception of the function 045 * @since 1.1.0 046 */ 047@FunctionalInterface 048public interface FileFilterWithException<E extends Exception> 049 extends PrimitiveReturnExceptionHandlerSupport<FileFilter, FileFilterWithException<E>>, BooleanDefaultValue { 050 051 /** 052 * Tests whether or not the specified abstract pathname should be included in a 053 * pathname list. 054 * 055 * @param pathname 056 * The abstract pathname to be tested 057 * @return <code>true</code> if and only if <code>pathname</code> should be 058 * included 059 * @throws E 060 * any exception 061 * @see FileFilter#accept(File) 062 */ 063 boolean accept(File pathname) throws E; 064 065 @Override 066 default FileFilter uncheckOrIgnore(boolean uncheck) { 067 return pathname -> { 068 try { 069 return accept(pathname); 070 } catch (Exception e) { 071 PrimitiveReturnExceptionHandlerSupport.handleException(uncheck, e, exceptionMapper()); 072 return defaultValue(); 073 } 074 }; 075 } 076 077 /** 078 * Returns a composed FileFilter that represents a short-circuiting logical AND 079 * of this FileFilter and another. When evaluating the composed predicate, if 080 * this predicate is {@code false}, then the {@code other} predicate is not 081 * evaluated. 082 * 083 * <p> 084 * Any exceptions thrown during evaluation of either FileFilter are relayed to 085 * the caller; if evaluation of this predicate throws an exception, the 086 * {@code other} FileFilter will not be evaluated. 087 * 088 * @param other 089 * a FileFilter that will be logically-ANDed with this predicate 090 * @return a composed FileFilter that represents the short-circuiting logical 091 * AND of this FileFilter and the {@code other} FileFilter 092 * @throws NullPointerException 093 * if other is null 094 * @see #or(FileFilterWithException) 095 * @see #negate() 096 */ 097 default FileFilterWithException<E> and(FileFilterWithException<? extends E> other) { 098 requireNonNull(other); 099 return t -> accept(t) && other.accept(t); 100 } 101 102 /** 103 * Returns a FileFilter that represents the logical negation of this FileFilter. 104 * 105 * @return a FileFilter that represents the logical negation of this FileFilter 106 * @see #and(FileFilterWithException) 107 * @see #or(FileFilterWithException) 108 */ 109 default FileFilterWithException<E> negate() { 110 return t -> !accept(t); 111 } 112 113 /** 114 * Negate a {@code PredicateWithException}. 115 * 116 * @param predicate 117 * to be negate 118 * @param <E> 119 * the type of the potential exception 120 * @return the negated FileFilter 121 * @see #negate() 122 * @throws NullPointerException 123 * if predicate is null 124 */ 125 static <E extends Exception> FileFilterWithException<E> negate(FileFilterWithException<E> predicate) { 126 return verifyPredicate(predicate).negate(); 127 } 128 129 /** 130 * Returns a composed FileFilter that represents a short-circuiting logical OR 131 * of this FileFilter and another. When evaluating the composed FileFilter, if 132 * this FileFilter is {@code true}, then the {@code other} predicate is not 133 * evaluated. 134 * 135 * <p> 136 * Any exceptions thrown during evaluation of either FileFilter are relayed to 137 * the caller; if evaluation of this FileFilter throws an exception, the 138 * {@code other} FileFilter will not be evaluated. 139 * 140 * @param other 141 * a FileFilter that will be logically-ORed with this predicate 142 * @return a composed FileFilter that represents the short-circuiting logical OR 143 * of this predicate and the {@code other} FileFilter 144 * @throws NullPointerException 145 * if other is null 146 * @see #and(FileFilterWithException) 147 * @see #negate() 148 */ 149 default FileFilterWithException<E> or(FileFilterWithException<? extends E> other) { 150 requireNonNull(other); 151 return t -> accept(t) || other.accept(t); 152 } 153 154 /** 155 * Returns a FileFilter that always throw exception. 156 * 157 * @param exceptionBuilder 158 * the supplier to create the exception 159 * @param <E> 160 * the type of the exception 161 * @return a FileFilter that always throw exception 162 */ 163 static <E extends Exception> FileFilterWithException<E> failing(Supplier<E> exceptionBuilder) { 164 return t -> { 165 throw exceptionBuilder.get(); 166 }; 167 } 168 169 /** 170 * Converts a {@code FileFilterWithException} to a {@code FileFilter} that wraps 171 * exception to {@code RuntimeException}. 172 * 173 * @param predicate 174 * to be unchecked 175 * @param <E> 176 * the type of the potential exception 177 * @return the unchecked FileFilter 178 * @see #uncheck() 179 * @see #unchecked(FileFilterWithException, Function) 180 * @throws NullPointerException 181 * if predicate is null 182 */ 183 static <E extends Exception> FileFilter unchecked(FileFilterWithException<E> predicate) { 184 return verifyPredicate(predicate).uncheck(); 185 } 186 187 /** 188 * Converts a {@code FileFilterWithException} to a {@code FileFilter} that wraps 189 * exception to {@code RuntimeException} by using the provided mapping function. 190 * 191 * @param predicate 192 * the be unchecked 193 * @param exceptionMapper 194 * a function to convert the exception to the runtime exception. 195 * @param <E> 196 * the type of the potential exception 197 * @return the unchecked FileFilter 198 * @see #uncheck() 199 * @see #unchecked(FileFilterWithException) 200 * @throws NullPointerException 201 * if predicate or exceptionMapper is null 202 */ 203 static <E extends Exception> FileFilter unchecked(FileFilterWithException<E> predicate, 204 Function<Exception, RuntimeException> exceptionMapper) { 205 verifyPredicate(predicate); 206 verifyExceptionMapper(exceptionMapper); 207 return new FileFilterWithException<E>() { 208 209 @Override 210 public boolean accept(File pathname) throws E { 211 return predicate.accept(pathname); 212 } 213 214 @Override 215 public Function<Exception, RuntimeException> exceptionMapper() { 216 return exceptionMapper; 217 } 218 219 }.uncheck(); 220 } 221 222 /** 223 * Converts a {@code FileFilterWithException} to a lifted {@code FileFilter} 224 * returning {@code false} in case of exception. 225 * 226 * @param predicate 227 * to be lifted 228 * @param <E> 229 * the type of the potential exception 230 * @return the lifted FileFilter 231 * @see #lift() 232 * @throws NullPointerException 233 * if predicate is null 234 */ 235 static <E extends Exception> FileFilter lifted(FileFilterWithException<E> predicate) { 236 return verifyPredicate(predicate).lift(); 237 } 238 239 /** 240 * Converts a {@code FileFilterWithException} to a lifted {@code FileFilter} 241 * returning {@code false} in case of exception. 242 * 243 * @param predicate 244 * to be lifted 245 * @param <E> 246 * the type of the potential exception 247 * @return the lifted FileFilter 248 * @see #ignore() 249 * @throws NullPointerException 250 * if predicate is null 251 */ 252 static <E extends Exception> FileFilter ignored(FileFilterWithException<E> predicate) { 253 return verifyPredicate(predicate).ignore(); 254 } 255 256 /** 257 * Converts a {@code FileFilterWithException} to a lifted {@code FileFilter} 258 * returning a default value in case of exception. 259 * 260 * @param predicate 261 * to be lifted 262 * @param defaultValue 263 * value in case of exception 264 * @param <E> 265 * the type of the potential exception 266 * @return the lifted FileFilter 267 * @see #ignore() 268 * @see #ignored(FileFilterWithException) 269 * @throws NullPointerException 270 * if predicate is null 271 * @since 3.0.0 272 */ 273 static <E extends Exception> FileFilter ignored(FileFilterWithException<E> predicate, boolean defaultValue) { 274 verifyPredicate(predicate); 275 return new FileFilterWithException<E>() { 276 277 @Override 278 public boolean accept(File pathname) throws E { 279 return predicate.accept(pathname); 280 } 281 282 @Override 283 public boolean defaultValue() { 284 return defaultValue; 285 } 286 287 }.ignore(); 288 } 289 290}