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