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