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