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