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