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