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