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.verifyFunction; 024import static java.util.Objects.requireNonNull; 025 026import java.util.Optional; 027import java.util.concurrent.Callable; 028import java.util.concurrent.CompletionStage; 029import java.util.function.Function; 030import java.util.function.Supplier; 031 032/** 033 * Represents a function that accepts one argument, may throw exception and 034 * produces a result. 035 * <h3>General contract</h3> 036 * <ul> 037 * <li><b>{@link #apply(Object) R apply(T t) throws E}</b> - The 038 * functional method.</li> 039 * <li><b>uncheck</b> - Return a {@code Function<T, R>}</li> 040 * <li><b>lift</b> - Return a {@code Function<T, Optional<R>>}</li> 041 * <li><b>ignore</b> - Return a {@code Function<T, R>}</li> 042 * </ul> 043 * 044 * @see Function 045 * @param <T> 046 * the type of the input to the function 047 * @param <R> 048 * the type of the result of the function 049 * @param <E> 050 * the type of the potential exception of the function 051 */ 052@FunctionalInterface 053public interface FunctionWithException<T, R, E extends Exception> extends 054 ObjectReturnExceptionHandlerSupport<Function<T, R>, Function<T, Optional<R>>, Function<T, CompletionStage<R>>, R, FunctionWithException<T, R, E>> { 055 056 /** 057 * Applies this function to the given argument. 058 * 059 * @param t 060 * the function argument 061 * @return the function result 062 * @throws E 063 * any exception 064 * @see Function#apply(Object) 065 */ 066 R apply(T t) throws E; 067 068 /** 069 * Converts this {@code FunctionWithException} to a {@code Function} that 070 * convert exception to {@code RuntimeException}. 071 * 072 * @return the unchecked function 073 * @see #unchecked(FunctionWithException) 074 * @see #unchecked(FunctionWithException, Function) 075 * @see Function 076 */ 077 @Override 078 default Function<T, R> uncheck() { 079 return t -> ObjectReturnExceptionHandlerSupport.unchecked(() -> apply(t), throwingHandler()); 080 } 081 082 /** 083 * Converts this {@code FunctionWithException} to a lifted {@code Function} 084 * using {@code Optional} as return value. 085 * 086 * @return the lifted function 087 * @see #lifted(FunctionWithException) 088 * @see Function 089 */ 090 @Override 091 default Function<T, Optional<R>> lift() { 092 return t -> ObjectReturnExceptionHandlerSupport.unchecked(() -> Optional.ofNullable(apply(t)), 093 notThrowingHandler()); 094 } 095 096 /** 097 * Converts this {@code FunctionWithException} to a lifted {@code Function} 098 * returning {@code null} (or the value redefined by the method 099 * {@link #defaultValue()}) in case of exception. 100 * 101 * @return the function that ignore error 102 * @see #ignored(FunctionWithException) 103 * @see Function 104 */ 105 @Override 106 default Function<T, R> ignore() { 107 return lift().andThen(o -> o.orElse(defaultValue())); 108 } 109 110 /** 111 * Convert this {@code FunctionWithException} to a lifted {@code Function} 112 * return {@code CompletionStage} as return value. 113 * 114 * @return the lifted function 115 * @see #staged(FunctionWithException) 116 * @see CompletionStage 117 */ 118 @Override 119 default Function<T, CompletionStage<R>> stage() { 120 return t -> ObjectReturnExceptionHandlerSupport.staged(() -> apply(t)); 121 } 122 123 /** 124 * Returns a composed function that first applies the {@code before} function to 125 * its input, and then applies this function to the result. If evaluation of 126 * either function throws an exception, it is relayed to the caller of the 127 * composed function. 128 * 129 * @param <V> 130 * the type of input to the {@code before} function, and to the 131 * composed function 132 * @param before 133 * the function to apply before this function is applied 134 * @return a composed function that first applies the {@code before} function 135 * and then applies this function 136 * @throws NullPointerException 137 * if before is null 138 * 139 * @see #andThen(FunctionWithException) 140 * @see Function#compose(Function) 141 */ 142 default <V> FunctionWithException<V, R, E> compose( 143 FunctionWithException<? super V, ? extends T, ? extends E> before) { 144 requireNonNull(before); 145 return (V v) -> apply(before.apply(v)); 146 } 147 148 /** 149 * Returns a composed function that first applies this function to its input, 150 * and then applies the {@code after} function to the result. If evaluation of 151 * either function throws an exception, it is relayed to the caller of the 152 * composed function. 153 * 154 * @param <V> 155 * the type of output of the {@code after} function, and of the 156 * composed function 157 * @param after 158 * the function to apply after this function is applied 159 * @return a composed function that first applies this function and then applies 160 * the {@code after} function 161 * @throws NullPointerException 162 * if after is null * 163 * @see #compose(FunctionWithException) 164 * @see Function#andThen(Function) 165 */ 166 default <V> FunctionWithException<T, V, E> andThen( 167 FunctionWithException<? super R, ? extends V, ? extends E> after) { 168 requireNonNull(after); 169 return (T t) -> after.apply(apply(t)); 170 } 171 172 /** 173 * Returns a function that always returns its input argument. 174 * 175 * @param <T> 176 * the type of the input and output objects to the function 177 * @param <E> 178 * the type of the potential exception 179 * @return a function that always returns its input argument 180 * @see Function#identity() 181 */ 182 static <T, E extends Exception> FunctionWithException<T, T, E> identity() { 183 return t -> t; 184 } 185 186 /** 187 * Returns a function that always throw exception. 188 * 189 * @param exceptionBuilder 190 * the supplier to create the exception 191 * @param <T> 192 * the type of the input to the function 193 * @param <R> 194 * the type of the result of the function 195 * @param <E> 196 * the type of the exception 197 * @return a function that always throw exception 198 */ 199 static <T, R, E extends Exception> FunctionWithException<T, R, E> failing(Supplier<E> exceptionBuilder) { 200 return t -> { 201 throw exceptionBuilder.get(); 202 }; 203 } 204 205 /** 206 * Converts a {@code FunctionWithException} to a {@code Function} that convert 207 * exception to {@code RuntimeException}. 208 * 209 * @param function 210 * to be unchecked 211 * @param <T> 212 * the type of the input to the function 213 * @param <R> 214 * the type of the result of the function 215 * @param <E> 216 * the type of the potential exception 217 * @return the unchecked exception 218 * @see #uncheck() 219 * @see #unchecked(FunctionWithException, Function) 220 * @throws NullPointerException 221 * if function is null 222 */ 223 static <T, R, E extends Exception> Function<T, R> unchecked(FunctionWithException<T, R, E> function) { 224 return verifyFunction(function).uncheck(); 225 } 226 227 /** 228 * Converts a {@code FunctionWithException} to a {@code Function} that wraps 229 * exception to {@code RuntimeException} by using the provided mapping function. 230 * 231 * @param function 232 * the be unchecked 233 * @param exceptionMapper 234 * a function to convert the exception to the runtime exception. 235 * @param <T> 236 * the type of the input to the function 237 * @param <R> 238 * the type of the result of the function 239 * @param <E> 240 * the type of the potential exception 241 * @return the unchecked exception 242 * @see #uncheck() 243 * @see #unchecked(FunctionWithException) 244 * @throws NullPointerException 245 * if function or exceptionMapper is null 246 */ 247 static <T, R, E extends Exception> Function<T, R> unchecked(FunctionWithException<T, R, E> function, 248 Function<Exception, RuntimeException> exceptionMapper) { 249 verifyFunction(function); 250 verifyExceptionMapper(exceptionMapper); 251 return new FunctionWithException<T, R, E>() { 252 253 @Override 254 public R apply(T t) throws E { 255 return function.apply(t); 256 } 257 258 @Override 259 public Function<Exception, RuntimeException> exceptionMapper() { 260 return exceptionMapper; 261 } 262 263 }.uncheck(); 264 } 265 266 /** 267 * Converts a {@code FunctionWithException} to a lifted {@code Function} using 268 * {@code Optional} as return value. 269 * 270 * @param function 271 * to be lifted 272 * @param <T> 273 * the type of the input to the function 274 * @param <R> 275 * the type of the result of the function 276 * @param <E> 277 * the type of the potential exception 278 * @return the lifted function 279 * @see #lift() 280 * @throws NullPointerException 281 * if function is null 282 */ 283 static <T, R, E extends Exception> Function<T, Optional<R>> lifted(FunctionWithException<T, R, E> function) { 284 return verifyFunction(function).lift(); 285 } 286 287 /** 288 * Converts a {@code FunctionWithException} to a lifted {@code Function} 289 * returning {@code null} in case of exception. 290 * 291 * @param function 292 * to be lifted 293 * @param <T> 294 * the type of the input to the function 295 * @param <R> 296 * the type of the result of the function 297 * @param <E> 298 * the type of the potential exception 299 * @return the lifted function 300 * @see #ignore() 301 * @throws NullPointerException 302 * if function is null 303 */ 304 static <T, R, E extends Exception> Function<T, R> ignored(FunctionWithException<T, R, E> function) { 305 return verifyFunction(function).ignore(); 306 } 307 308 /** 309 * Converts a {@code FunctionWithException} to a lifted {@code Function} 310 * returning a default value in case of exception. 311 * 312 * @param function 313 * to be lifted 314 * @param defaultValue 315 * the value to be returned in case of exception. 316 * @param <T> 317 * the type of the input to the function 318 * @param <R> 319 * the type of the result of the function 320 * @param <E> 321 * the type of the potential exception 322 * @return the lifted function 323 * @see #ignore() 324 * @see #ignored(FunctionWithException) 325 * @throws NullPointerException 326 * if function is null 327 * @since 3.0.0 328 */ 329 static <T, R, E extends Exception> Function<T, R> ignored(FunctionWithException<T, R, E> function, R defaultValue) { 330 verifyFunction(function); 331 return new FunctionWithException<T, R, E>() { 332 333 @Override 334 public R apply(T t) throws E { 335 return function.apply(t); 336 } 337 338 @Override 339 public R defaultValue() { 340 return defaultValue; 341 } 342 343 }.ignore(); 344 } 345 346 /** 347 * Convert this {@code FunctionWithException} to a lifted {@code Function} 348 * return {@code CompletionStage} as return value. 349 * 350 * @param function 351 * to be lifted 352 * @param <T> 353 * the type of the input to the function 354 * @param <R> 355 * the type of the result of the function 356 * @param <E> 357 * the type of the potential exception 358 * @return the lifted function 359 * @see #stage() 360 * @throws NullPointerException 361 * if function is null 362 */ 363 static <T, R, E extends Exception> Function<T, CompletionStage<R>> staged(FunctionWithException<T, R, E> function) { 364 return verifyFunction(function).stage(); 365 } 366 367 /** 368 * Converts a {@code FunctionWithException} to a {@code ConsumerWithException}. 369 * 370 * @param function 371 * to be converter 372 * @param <T> 373 * the type of the input to the function 374 * @param <R> 375 * the type of the result of the function 376 * @param <E> 377 * the type of the potential exception 378 * @return the consumer 379 * @throws NullPointerException 380 * if function is null 381 * @since 1.2.0 382 */ 383 static <T, R, E extends Exception> ConsumerWithException<T, E> asConsumer(FunctionWithException<T, R, E> function) { 384 return verifyFunction(function).asConsumer(); 385 } 386 387 /** 388 * Converts a {@code FunctionWithException} to a {@code ConsumerWithException}. 389 * 390 * @return the consumer 391 * @since 1.2.0 392 */ 393 default ConsumerWithException<T, E> asConsumer() { 394 return this::apply; 395 } 396 397 /** 398 * Converts a {@code FunctionWithException} to a 399 * {@code BiFunctionWithException}. 400 * 401 * @param function 402 * to be converter 403 * @param <T> 404 * the type of the input to the function 405 * @param <U> 406 * the type of the second input to the function 407 * @param <R> 408 * the type of the result of the function 409 * @param <E> 410 * the type of the potential exception 411 * @return the function 412 * @throws NullPointerException 413 * if function is null 414 * @since 1.2.0 415 */ 416 static <T, U, R, E extends Exception> BiFunctionWithException<T, U, R, E> asBiFunction( 417 FunctionWithException<T, R, E> function) { 418 return verifyFunction(function).asBiFunction(); 419 } 420 421 /** 422 * Converts a {@code FunctionWithException} to a 423 * {@code BiFunctionWithException}. 424 * 425 * @param <U> 426 * the type of the second input to the function 427 * 428 * @return the function 429 * @since 1.2.0 430 */ 431 default <U> BiFunctionWithException<T, U, R, E> asBiFunction() { 432 return (t, u) -> apply(t); 433 } 434 435 /** 436 * Converts a {@code FunctionWithException} to a {@code SupplierWithException}. 437 * 438 * @param function 439 * to be converter 440 * @param t 441 * The input to the function. 442 * @param <T> 443 * the type of the input to the function 444 * @param <R> 445 * the type of the result of the function 446 * @param <E> 447 * the type of the potential exception 448 * @return the supplier 449 * @throws NullPointerException 450 * if function is null 451 * @since 1.2.0 452 */ 453 static <T, R, E extends Exception> SupplierWithException<R, E> asSupplier(FunctionWithException<T, R, E> function, 454 T t) { 455 return verifyFunction(function).asSupplier(t); 456 } 457 458 /** 459 * Converts a {@code FunctionWithException} to a {@code SupplierWithException}. 460 * 461 * @param t 462 * The input to the function. 463 * 464 * @return the supplier 465 * @since 1.2.0 466 */ 467 default SupplierWithException<R, E> asSupplier(T t) { 468 return () -> apply(t); 469 } 470 471 /** 472 * Converts a {@code FunctionWithException} to a {@code Callable}. 473 * 474 * @param function 475 * to be converter 476 * @param t 477 * The input to the function. 478 * @param <T> 479 * the type of the input to the function 480 * @param <R> 481 * the type of the result of the function 482 * @param <E> 483 * the type of the potential exception 484 * @return the callable 485 * @throws NullPointerException 486 * if function is null 487 * @since 1.2.0 488 */ 489 static <T, R, E extends Exception> Callable<R> asCallable(FunctionWithException<T, R, E> function, T t) { 490 return verifyFunction(function).asCallable(t); 491 } 492 493 /** 494 * Converts a {@code FunctionWithException} to a {@code Callable}. 495 * 496 * @param t 497 * The input to the function. 498 * 499 * @return the callable 500 * @since 1.2.0 501 */ 502 default Callable<R> asCallable(T t) { 503 return () -> apply(t); 504 } 505 506 /** 507 * Converts a {@code FunctionWithException} to a {@code RunnableWithException}. 508 * 509 * @param function 510 * to be converter 511 * @param t 512 * The input to the function. 513 * @param <T> 514 * the type of the input to the function 515 * @param <R> 516 * the type of the result of the function 517 * @param <E> 518 * the type of the potential exception 519 * @return the Runnable 520 * @throws NullPointerException 521 * if function is null 522 * @since 1.2.0 523 */ 524 static <T, R, E extends Exception> RunnableWithException<E> asRunnable(FunctionWithException<T, R, E> function, 525 T t) { 526 return verifyFunction(function).asRunnable(t); 527 } 528 529 /** 530 * Converts a {@code FunctionWithException} to a {@code RunnableWithException}. 531 * 532 * @param t 533 * The input to the function. 534 * 535 * @return the Runnable 536 * @since 1.2.0 537 */ 538 default RunnableWithException<E> asRunnable(T t) { 539 return () -> apply(t); 540 } 541 542}