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