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.FilenameFilter; 028import java.util.function.Function; 029import java.util.function.Supplier; 030 031/** 032 * Instances of classes that implement this interface are used to filter 033 * filenames and may throw exception. 034 * <h3>General contract</h3> 035 * <ul> 036 * <li><b>{@link #accept(File, String) boolean accept(File dir, String name) 037 * throws E}</b> - The functional method.</li> 038 * <li><b>uncheck</b> - Return a {@code FilenameFilter}</li> 039 * <li><b>lift</b> - Return a {@code FilenameFilter}</li> 040 * <li><b>ignore</b> - Return a {@code FilenameFilter}</li> 041 * </ul> 042 * 043 * 044 * @see FilenameFilter 045 * @param <E> 046 * the type of the potential exception of the function 047 */ 048@FunctionalInterface 049public interface FilenameFilterWithException<E extends Exception> extends 050 PrimitiveReturnExceptionHandlerSupport<FilenameFilter, FilenameFilterWithException<E>>, BooleanDefaultValue { 051 052 /** 053 * Tests if a specified file should be included in a file list. 054 * 055 * @param dir 056 * the directory in which the file was found. 057 * @param name 058 * the name of the file. 059 * @return <code>true</code> if and only if the name should be included in the 060 * file list; <code>false</code> otherwise. 061 * @throws E 062 * any exception 063 * @see FilenameFilter#accept(File, String) 064 */ 065 boolean accept(File dir, String name) throws E; 066 067 @Override 068 default FilenameFilter uncheckOrIgnore(boolean uncheck) { 069 return (dir, name) -> { 070 try { 071 return accept(dir, name); 072 } catch (Exception e) { 073 PrimitiveReturnExceptionHandlerSupport.handleException(uncheck, e, exceptionMapper()); 074 return defaultValue(); 075 } 076 }; 077 } 078 079 /** 080 * Returns a composed FilenameFilter that represents a short-circuiting logical 081 * AND of this FilenameFilter and another. When evaluating the composed 082 * FilenameFilter, if this FilenameFilter is {@code false}, then the 083 * {@code other} FilenameFilter is not evaluated. 084 * 085 * <p> 086 * Any exceptions thrown during evaluation of either FilenameFilter are relayed 087 * to the caller; if evaluation of this FilenameFilter throws an exception, the 088 * {@code other} FilenameFilter will not be evaluated. 089 * 090 * @param other 091 * a FilenameFilter that will be logically-ANDed with this predicate 092 * @return a composed FilenameFilter that represents the short-circuiting 093 * logical AND of this FilenameFilter and the {@code other} 094 * FilenameFilter 095 * @throws NullPointerException 096 * if other is null 097 * @see #or(FilenameFilterWithException) 098 * @see #negate() 099 */ 100 default FilenameFilterWithException<E> and(FilenameFilterWithException<? extends E> other) { 101 requireNonNull(other); 102 return (t, u) -> accept(t, u) && other.accept(t, u); 103 } 104 105 /** 106 * Returns a FilenameFilter that represents the logical negation of this 107 * FilenameFilter. 108 * 109 * @return a FilenameFilter that represents the logical negation of this 110 * FilenameFilter 111 * @see #and(FilenameFilterWithException) 112 * @see #or(FilenameFilterWithException) 113 */ 114 default FilenameFilterWithException<E> negate() { 115 return (t, u) -> !accept(t, u); 116 } 117 118 /** 119 * Negate a {@code DoublePredicateWithException}. 120 * 121 * @param predicate 122 * to be negate 123 * @param <E> 124 * the type of the potential exception 125 * @return the negated FilenameFilter 126 * @see #negate() 127 */ 128 static <E extends Exception> FilenameFilterWithException<E> negate(FilenameFilterWithException<E> predicate) { 129 return verifyPredicate(predicate).negate(); 130 } 131 132 /** 133 * Returns a composed FilenameFilter that represents a short-circuiting logical 134 * OR of this FilenameFilter and another. When evaluating the composed 135 * FilenameFilter, if this FilenameFilter is {@code true}, then the 136 * {@code other} FilenameFilter is not evaluated. 137 * 138 * <p> 139 * Any exceptions thrown during evaluation of either FilenameFilter are relayed 140 * to the caller; if evaluation of this FilenameFilter throws an exception, the 141 * {@code other} FilenameFilter will not be evaluated. 142 * 143 * @param other 144 * a FilenameFilter that will be logically-ORed with this 145 * FilenameFilter 146 * @return a composed FilenameFilter that represents the short-circuiting 147 * logical OR of this FilenameFilter and the {@code other} 148 * FilenameFilter 149 * @throws NullPointerException 150 * if other is null 151 * @see #and(FilenameFilterWithException) 152 * @see #negate() 153 */ 154 default FilenameFilterWithException<E> or(FilenameFilterWithException<? extends E> other) { 155 requireNonNull(other); 156 return (t, u) -> accept(t, u) || other.accept(t, u); 157 } 158 159 /** 160 * Returns a FilenameFilter that always throw exception. 161 * 162 * @param exceptionBuilder 163 * the supplier to create the exception 164 * @param <E> 165 * the type of the exception 166 * @return a predicate that always throw exception 167 */ 168 static <E extends Exception> FilenameFilterWithException<E> failing(Supplier<E> exceptionBuilder) { 169 return (dir, name) -> { 170 throw exceptionBuilder.get(); 171 }; 172 } 173 174 /** 175 * Converts a {@code FilenameFilterWithException} to a {@code FilenameFilter} 176 * that wraps to {@code RuntimeException}. 177 * 178 * @param predicate 179 * to be unchecked 180 * @param <E> 181 * the type of the potential exception 182 * @return the unchecked FilenameFilter 183 * @see #uncheck() 184 * @see #unchecked(FilenameFilterWithException, Function) 185 * @throws NullPointerException 186 * if predicate is null 187 */ 188 static <E extends Exception> FilenameFilter unchecked(FilenameFilterWithException<E> predicate) { 189 return verifyPredicate(predicate).uncheck(); 190 } 191 192 /** 193 * Converts a {@code FilenameFilterWithException} to a {@code FilenameFilter} 194 * that wraps to {@code RuntimeException} by using the provided mapping 195 * function. 196 * 197 * @param predicate 198 * the be unchecked 199 * @param exceptionMapper 200 * a function to convert the exception to the runtime exception. 201 * @param <E> 202 * the type of the potential exception 203 * @return the unchecked FilenameFilter 204 * @see #uncheck() 205 * @see #unchecked(FilenameFilterWithException) 206 * @throws NullPointerException 207 * if predicate or exceptionMapper is null 208 */ 209 static <E extends Exception> FilenameFilter unchecked(FilenameFilterWithException<E> predicate, 210 Function<Exception, RuntimeException> exceptionMapper) { 211 verifyPredicate(predicate); 212 verifyExceptionMapper(exceptionMapper); 213 return new FilenameFilterWithException<E>() { 214 215 @Override 216 public boolean accept(File dir, String name) throws E { 217 return predicate.accept(dir, name); 218 } 219 220 @Override 221 public Function<Exception, RuntimeException> exceptionMapper() { 222 return exceptionMapper; 223 } 224 225 }.uncheck(); 226 } 227 228 /** 229 * Converts a {@code FilenameFilterWithException} to a lifted 230 * {@code FilenameFilter} returning {@code false} in case of exception. 231 * 232 * @param predicate 233 * to be lifted 234 * @param <E> 235 * the type of the potential exception 236 * @return the lifted FilenameFilter 237 * @see #lift() 238 * @throws NullPointerException 239 * if predicate is null 240 */ 241 static <E extends Exception> FilenameFilter lifted(FilenameFilterWithException<E> predicate) { 242 return verifyPredicate(predicate).lift(); 243 } 244 245 /** 246 * Converts a {@code FilenameFilterWithException} to a lifted 247 * {@code FilenameFilter} returning {@code false} in case of exception. 248 * 249 * @param predicate 250 * to be lifted 251 * @param <E> 252 * the type of the potential exception 253 * @return the lifted FilenameFilter 254 * @see #ignore() 255 * @throws NullPointerException 256 * if predicate is null 257 */ 258 static <E extends Exception> FilenameFilter ignored(FilenameFilterWithException<E> predicate) { 259 return verifyPredicate(predicate).ignore(); 260 } 261 262 /** 263 * Converts a {@code FilenameFilterWithException} to a lifted 264 * {@code FilenameFilter} returning a default value in case of exception. 265 * 266 * @param predicate 267 * to be lifted 268 * @param defaultValue 269 * value in case of exception 270 * @param <E> 271 * the type of the potential exception 272 * @return the lifted FilenameFilter 273 * @see #ignore() 274 * @see #ignored(FilenameFilterWithException) 275 * @throws NullPointerException 276 * if predicate is null 277 * @since 3.0.0 278 */ 279 static <E extends Exception> FilenameFilter ignored(FilenameFilterWithException<E> predicate, 280 boolean defaultValue) { 281 verifyPredicate(predicate); 282 return new FilenameFilterWithException<E>() { 283 284 @Override 285 public boolean accept(File dir, String name) throws E { 286 return predicate.accept(dir, name); 287 } 288 289 @Override 290 public boolean defaultValue() { 291 return defaultValue; 292 } 293 294 }.ignore(); 295 } 296 297}