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.function.DoubleUnaryOperator; 027import java.util.function.Function; 028import java.util.function.Supplier; 029 030/** 031 * Represents an operation on a single {@code double}-valued operand that may 032 * thrown exception and produces a {@code double}-valued result. This is the 033 * primitive type specialization of {@link UnaryOperatorWithException} for 034 * {@code double}. 035 * <h3>General contract</h3> 036 * <ul> 037 * <li><b>{@link #applyAsDouble(double) double applyAsDouble(double operand) 038 * throws E}</b> - The functional method.</li> 039 * <li><b>uncheck</b> - Return a {@code DoubleUnaryOperator}</li> 040 * <li><b>lift</b> - Return a {@code DoubleUnaryOperator}</li> 041 * <li><b>ignore</b> - Return a {@code DoubleUnaryOperator}</li> 042 * </ul> 043 * 044 * @see DoubleUnaryOperator 045 * @param <E> 046 * the type of the potential exception of the function 047 */ 048@FunctionalInterface 049public interface DoubleUnaryOperatorWithException<E extends Exception> 050 extends PrimitiveReturnExceptionHandlerSupport<DoubleUnaryOperator, DoubleUnaryOperatorWithException<E>>, 051 DoubleDefaultValue { 052 053 /** 054 * Applies this operator to the given operand. 055 * 056 * @param operand 057 * the operand 058 * @return the operator result 059 * @throws E 060 * any exception 061 * @see DoubleUnaryOperator#applyAsDouble(double) 062 */ 063 double applyAsDouble(double operand) throws E; 064 065 @Override 066 default DoubleUnaryOperator uncheckOrIgnore(boolean uncheck) { 067 return operand -> { 068 try { 069 return applyAsDouble(operand); 070 } catch (Exception e) { 071 PrimitiveReturnExceptionHandlerSupport.handleException(uncheck, e, exceptionMapper()); 072 return defaultValue(); 073 } 074 }; 075 } 076 077 /** 078 * Returns a composed operator that first applies the {@code before} operator to 079 * its input, and then applies this operator to the result. If evaluation of 080 * either operator throws an exception, it is relayed to the caller of the 081 * composed operator. 082 * 083 * @param before 084 * the operator to apply before this operator is applied 085 * @return a composed operator that first applies the {@code before} operator 086 * and then applies this operator 087 * @throws NullPointerException 088 * if before is null 089 * 090 * @see #andThen(DoubleUnaryOperatorWithException) 091 */ 092 default DoubleUnaryOperatorWithException<E> compose(DoubleUnaryOperatorWithException<? extends E> before) { 093 requireNonNull(before); 094 return v -> applyAsDouble(before.applyAsDouble(v)); 095 } 096 097 /** 098 * Returns a composed operator that first applies this operator to its input, 099 * and then applies the {@code after} operator to the result. If evaluation of 100 * either operator throws an exception, it is relayed to the caller of the 101 * composed operator. 102 * 103 * @param after 104 * the operator to apply after this operator is applied 105 * @return a composed operator that first applies this operator and then applies 106 * the {@code after} operator 107 * @throws NullPointerException 108 * if after is null 109 * 110 * @see #compose(DoubleUnaryOperatorWithException) 111 */ 112 default DoubleUnaryOperatorWithException<E> andThen(DoubleUnaryOperatorWithException<? extends E> after) { 113 requireNonNull(after); 114 return t -> after.applyAsDouble(applyAsDouble(t)); 115 } 116 117 /** 118 * Returns a unary operator that always returns its input argument. 119 * 120 * @return a unary operator that always returns its input argument 121 * 122 * @param <E> 123 * the exception that may be thrown 124 */ 125 static <E extends Exception> DoubleUnaryOperatorWithException<E> identity() { 126 return t -> t; 127 } 128 129 /** 130 * Returns a function that always throw exception. 131 * 132 * @param exceptionBuilder 133 * the supplier to create the exception 134 * @param <E> 135 * the type of the exception 136 * @return a function that always throw exception 137 */ 138 static <E extends Exception> DoubleUnaryOperatorWithException<E> failing(Supplier<E> exceptionBuilder) { 139 return operand -> { 140 throw exceptionBuilder.get(); 141 }; 142 } 143 144 /** 145 * Converts a {@code DoubleUnaryOperatorException} to a 146 * {@code DoubleUnaryOperator} that wraps exception to {@code RuntimeException}. 147 * 148 * @param function 149 * to be unchecked 150 * @param <E> 151 * the type of the potential exception 152 * @return the unchecked function 153 * @see #uncheck() 154 * @see #unchecked(DoubleUnaryOperatorWithException, Function) 155 * @throws NullPointerException 156 * if function is null 157 */ 158 static <E extends Exception> DoubleUnaryOperator unchecked(DoubleUnaryOperatorWithException<E> function) { 159 return verifyFunction(function).uncheck(); 160 } 161 162 /** 163 * Converts a {@code DoubleUnaryOperatorWithException} to a 164 * {@code DoubleUnaryOperator} that wraps exception to {@code RuntimeException} 165 * by using the provided mapping function. 166 * 167 * @param function 168 * the be unchecked 169 * @param exceptionMapper 170 * a function to convert the exception to the runtime exception. 171 * @param <E> 172 * the type of the potential exception 173 * @return the unchecked function 174 * @see #uncheck() 175 * @see #unchecked(DoubleUnaryOperatorWithException) 176 * @throws NullPointerException 177 * if function or exceptionMapper is null 178 */ 179 static <E extends Exception> DoubleUnaryOperator unchecked(DoubleUnaryOperatorWithException<E> function, 180 Function<Exception, RuntimeException> exceptionMapper) { 181 verifyFunction(function); 182 verifyExceptionMapper(exceptionMapper); 183 return new DoubleUnaryOperatorWithException<E>() { 184 185 @Override 186 public double applyAsDouble(double operand) throws E { 187 return function.applyAsDouble(operand); 188 } 189 190 @Override 191 public Function<Exception, RuntimeException> exceptionMapper() { 192 return exceptionMapper; 193 } 194 195 }.uncheck(); 196 } 197 198 /** 199 * Converts a {@code DoubleUnaryOperatorWithException} to a lifted 200 * {@code DoubleUnaryOperator} using {@code 0} as return value in case of error. 201 * 202 * @param function 203 * to be lifted 204 * @param <E> 205 * the type of the potential exception 206 * @return the lifted function 207 * @see #lift() 208 * @throws NullPointerException 209 * if function is null 210 */ 211 static <E extends Exception> DoubleUnaryOperator lifted(DoubleUnaryOperatorWithException<E> function) { 212 return verifyFunction(function).lift(); 213 } 214 215 /** 216 * Converts a {@code DoubleUnaryOperatorWithException} to a lifted 217 * {@code DoubleUnaryOperator} returning {@code 0} in case of exception. 218 * 219 * @param function 220 * to be lifted 221 * @param <E> 222 * the type of the potential exception 223 * @return the lifted function 224 * @see #ignore() 225 * @throws NullPointerException 226 * if function is null 227 */ 228 static <E extends Exception> DoubleUnaryOperator ignored(DoubleUnaryOperatorWithException<E> function) { 229 return verifyFunction(function).ignore(); 230 } 231 232 /** 233 * Converts a {@code DoubleUnaryOperatorWithException} to a lifted 234 * {@code DoubleUnaryOperator} returning a default value in case of exception. 235 * 236 * @param function 237 * to be lifted 238 * @param defaultValue 239 * the default value in case of exception 240 * @param <E> 241 * the type of the potential exception 242 * @return the lifted function 243 * @see #ignore() 244 * @see #ignored(DoubleUnaryOperatorWithException) 245 * @throws NullPointerException 246 * if function is null 247 * @since 3.0.0 248 */ 249 static <E extends Exception> DoubleUnaryOperator ignored(DoubleUnaryOperatorWithException<E> function, 250 double defaultValue) { 251 verifyFunction(function); 252 return new DoubleUnaryOperatorWithException<E>() { 253 254 @Override 255 public double applyAsDouble(double operand) throws E { 256 return function.applyAsDouble(operand); 257 } 258 259 @Override 260 public double defaultValue() { 261 return defaultValue; 262 } 263 264 }.ignore(); 265 } 266 267}