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; 024 025import java.util.Optional; 026import java.util.function.BiFunction; 027import java.util.function.BinaryOperator; 028import java.util.function.Function; 029import java.util.function.Supplier; 030 031/** 032 * Represents an operation upon two operands of the same type, that may throw 033 * exception, producing a result of the same type as the operands. This is a 034 * specialization of {@link BiFunctionWithException} for the case where the 035 * operands and the result are all of the same type. 036 * <p> 037 * As this interface must return the same type of the input, a lifted version 038 * which returns {@code Optional} is not possible. 039 * <h3>General contract</h3> 040 * <ul> 041 * <li><b>{@link #apply(Object, Object) T apply(T t, T u) throws 042 * E}</b> - The functional method.</li> 043 * <li><b>uncheck</b> - Return a {@code BinaryOperator<T>}</li> 044 * <li><b>lift</b> - Return a 045 * {@code BiFunction<T,T,<Optional<T>>}</li> 046 * <li><b>ignore</b> - Return a {@code BinaryOperator<T>}</li> 047 * </ul> 048 * 049 * @see BiFunctionWithException 050 * @see BinaryOperator 051 * @param <T> 052 * the type of the operands and result of the operator 053 * @param <E> 054 * the type of the potential exception of the function 055 */ 056@FunctionalInterface 057public interface BinaryOperatorWithException<T, E extends Exception> extends BiFunctionWithException<T, T, T, E> { 058 059 /** 060 * Converts this {@code BinaryOperatorWithException} to a {@code BinaryOperator} 061 * that convert exception to {@code RuntimeException}. 062 * 063 * @return the unchecked function 064 * @see #unchecked(BinaryOperatorWithException) 065 * @see #unchecked(BinaryOperatorWithException, Function) 066 */ 067 @Override 068 default BinaryOperator<T> uncheck() { 069 return (t, u) -> ObjectReturnExceptionHandlerSupport.unchecked(() -> apply(t, u), throwingHandler()); 070 } 071 072 /** 073 * Converts this {@code BinaryOperatorWithException} to a lifted 074 * {@code BinaryOperator} returning {@code null} in case of exception. 075 * 076 * @return the function that ignore error 077 * @see #ignored(BinaryOperatorWithException) 078 */ 079 @Override 080 default BinaryOperator<T> ignore() { 081 return (t, u) -> ObjectReturnExceptionHandlerSupport.unchecked(() -> apply(t, u), e -> null); 082 } 083 084 @Override 085 default BinaryOperatorWithException<T, E> documented(Supplier<String> toString) { 086 return (BinaryOperatorWithException<T, E>) BiFunctionWithException.super.documented(toString); 087 } 088 089 /** 090 * Returns a binary operator that always throw exception. 091 * 092 * @param exceptionBuilder 093 * the supplier to create the exception 094 * @param <T> 095 * the type of the operands and result of the operator 096 * @param <E> 097 * the type of the exception 098 * @return a function that always throw exception 099 */ 100 static <T, E extends Exception> BinaryOperatorWithException<T, E> failing(Supplier<E> exceptionBuilder) { 101 return (t, u) -> { 102 throw exceptionBuilder.get(); 103 }; 104 } 105 106 /** 107 * Converts a {@code BinaryOperatorWithException} to a {@code BinaryOperator} 108 * that convert exception to {@code RuntimeException}. 109 * 110 * @param function 111 * to be unchecked 112 * @param <T> 113 * the type of the operands and result of the operator 114 * @param <E> 115 * the type of the potential exception 116 * @return the unchecked exception 117 * @see #uncheck() 118 * @see #unchecked(BinaryOperatorWithException, Function) 119 * @throws NullPointerException 120 * if function is null 121 */ 122 static <T, E extends Exception> BinaryOperator<T> unchecked(BinaryOperatorWithException<T, E> function) { 123 return verifyFunction(function).uncheck(); 124 } 125 126 /** 127 * Converts a {@code BinaryOperatorWithException} to a {@code BinaryOperator} 128 * that convert exception to {@code RuntimeException} by using the provided 129 * mapping function. 130 * 131 * @param function 132 * the be unchecked 133 * @param exceptionMapper 134 * a function to convert the exception to the runtime exception. 135 * @param <T> 136 * the type of the operands and result of the operator 137 * @param <E> 138 * the type of the potential exception 139 * @return the unchecked exception 140 * @see #uncheck() 141 * @see #unchecked(BinaryOperatorWithException) 142 * @throws NullPointerException 143 * if function or exceptionMapper is null 144 */ 145 static <T, E extends Exception> BinaryOperator<T> unchecked(BinaryOperatorWithException<T, E> function, 146 Function<Exception, RuntimeException> exceptionMapper) { 147 verifyFunction(function); 148 verifyExceptionMapper(exceptionMapper); 149 return new BinaryOperatorWithException<T, E>() { 150 151 @Override 152 public T apply(T t, T u) throws E { 153 return function.apply(t, u); 154 } 155 156 @Override 157 public Function<Exception, RuntimeException> exceptionMapper() { 158 return exceptionMapper; 159 } 160 161 }.uncheck(); 162 } 163 164 /** 165 * Converts a {@code BinaryOperatorWithException} to a lifted {@code Function} 166 * returning an optional in case of exception. 167 * 168 * @param function 169 * the be unchecked 170 * @param <T> 171 * the type of the operands and result of the operator 172 * @param <E> 173 * the type of the potential exception 174 * @return the lifted function 175 * @see #ignore() 176 * @throws NullPointerException 177 * if function is null 178 */ 179 static <T, E extends Exception> BiFunction<T, T, Optional<T>> lifted(BinaryOperatorWithException<T, E> function) { 180 return verifyFunction(function).lift(); 181 } 182 183 /** 184 * Converts a {@code BinaryOperatorWithException} to a lifted 185 * {@code BinaryOperator} returning {@code null} in case of exception. 186 * 187 * @param function 188 * the be unchecked 189 * @param <T> 190 * the type of the operands and result of the operator 191 * @param <E> 192 * the type of the potential exception 193 * @return the lifted function 194 * @see #ignore() 195 * @throws NullPointerException 196 * if function is null 197 */ 198 static <T, E extends Exception> BinaryOperator<T> ignored(BinaryOperatorWithException<T, E> function) { 199 return verifyFunction(function).ignore(); 200 } 201 202}