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