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