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.verifyOperation;
024
025import java.util.concurrent.CompletionStage;
026import java.util.function.BiFunction;
027import java.util.function.Function;
028import java.util.function.ObjDoubleConsumer;
029import java.util.function.Supplier;
030
031/**
032 * Represents an operation that accepts an object-valued and a
033 * {@code double}-valued argument, and returns no result. This is the
034 * {@code (reference, double)} specialization of
035 * {@link BiConsumerWithException}. Unlike most other functional interfaces,
036 * {@code ObjDoubleConsumerWithException} is expected to operate via
037 * side-effects.
038 * <h3>General contract</h3>
039 * <ul>
040 * <li><b>{@link #accept(Object, double) void accept(T t, double value) throws
041 * E}</b>&nbsp;-&nbsp;The functional method.</li>
042 * <li><b>uncheck</b>&nbsp;-&nbsp;Return a {@code ObjDoubleConsumer<T>}</li>
043 * <li><b>lift</b>&nbsp;-&nbsp;Return a {@code ObjDoubleConsumer<T>}</li>
044 * <li><b>ignore</b>&nbsp;-&nbsp;Return a {@code ObjDoubleConsumer<T>}</li>
045 * </ul>
046 *
047 * @see ObjDoubleConsumer
048 * @param <T>
049 *            the type of the object argument to the operation
050 * @param <E>
051 *            the type of the potential exception of the operation
052 */
053@FunctionalInterface
054public interface ObjDoubleConsumerWithException<T, E extends Exception> extends
055                NoReturnExceptionHandlerSupport<ObjDoubleConsumer<T>, BiFunction<T, Double, CompletionStage<Void>>, ObjDoubleConsumerWithException<T, E>> {
056
057        /**
058         * Performs this operation on the given arguments.
059         *
060         * @param t
061         *            the first input argument
062         * @param value
063         *            the second input argument
064         * @throws E
065         *             any exception
066         * @see ObjDoubleConsumer#accept(Object,double)
067         */
068        void accept(T t, double value) throws E;
069
070        /**
071         * Converts this {@code ObjLongConsumerWithException} to a
072         * {@code ObjDoubleConsumer} that wraps exception to {@code RuntimeException}.
073         *
074         * @return the unchecked operation
075         * @see #unchecked(ObjDoubleConsumerWithException)
076         * @see #unchecked(ObjDoubleConsumerWithException, Function)
077         */
078        @Override
079        default ObjDoubleConsumer<T> uncheck() {
080                return (t, value) -> NoReturnExceptionHandlerSupport.unchecked(() -> accept(t, value), throwingHandler());
081        }
082
083        /**
084         * Converts this {@code ObjLongConsumerWithException} to a <i>lifted</i>
085         * {@code ObjDoubleConsumer} ignoring exception.
086         *
087         * @return the operation that ignore error
088         * @see #ignored(ObjDoubleConsumerWithException)
089         */
090        @Override
091        default ObjDoubleConsumer<T> ignore() {
092                return (t, value) -> NoReturnExceptionHandlerSupport.unchecked(() -> accept(t, value), notThrowingHandler());
093        }
094
095        /**
096         * Converts this {@code ObjDoubleConsumerWithException} to a <i>staged</i>
097         * {@code BiFunction} that return a {@code CompletionStage}.
098         *
099         * @return the staged operation.
100         * @since 1.1.0
101         */
102        @Override
103        default BiFunction<T, Double, CompletionStage<Void>> stage() {
104                return (t, value) -> NoReturnExceptionHandlerSupport.staged(() -> accept(t, value));
105        }
106
107        /**
108         * Returns an operation that always throw exception.
109         *
110         * @param exceptionBuilder
111         *            the supplier to create the exception
112         * @param <T>
113         *            the type of the object argument to the operation
114         * @param <E>
115         *            the type of the exception
116         * @return an operation that always throw exception
117         */
118        static <T, E extends Exception> ObjDoubleConsumerWithException<T, E> failing(Supplier<E> exceptionBuilder) {
119                return (t, u) -> {
120                        throw exceptionBuilder.get();
121                };
122        }
123
124        /**
125         * Converts a {@code ObjDoubleConsumerWithException} to a
126         * {@code ObjDoubleConsumer} that wraps exception to {@code RuntimeException}.
127         *
128         * @param operation
129         *            to be unchecked
130         * @param <T>
131         *            the type of the object argument to the operation
132         * @param <E>
133         *            the type of the potential exception
134         * @return the unchecked operation
135         * @see #uncheck()
136         * @see #unchecked(ObjDoubleConsumerWithException, Function)
137         * @throws NullPointerException
138         *             if operation is null
139         */
140        static <T, E extends Exception> ObjDoubleConsumer<T> unchecked(ObjDoubleConsumerWithException<T, E> operation) {
141                return verifyOperation(operation).uncheck();
142        }
143
144        /**
145         * Converts a {@code ObjLongConsumerWithException} to a
146         * {@code ObjDoubleConsumer} that wraps exception to {@code RuntimeException} by
147         * using the provided mapping function.
148         *
149         * @param operation
150         *            the be unchecked
151         * @param exceptionMapper
152         *            a function to convert the exception to the runtime exception.
153         * @param <T>
154         *            the type of the object argument to the operation
155         * @param <E>
156         *            the type of the potential exception
157         * @return the unchecked operation
158         * @see #uncheck()
159         * @see #unchecked(ObjDoubleConsumerWithException)
160         * @throws NullPointerException
161         *             if operation or exceptionMapper is null
162         */
163        static <T, E extends Exception> ObjDoubleConsumer<T> unchecked(ObjDoubleConsumerWithException<T, E> operation,
164                        Function<Exception, RuntimeException> exceptionMapper) {
165                verifyOperation(operation);
166                verifyExceptionMapper(exceptionMapper);
167                return new ObjDoubleConsumerWithException<T, E>() {
168
169                        @Override
170                        public void accept(T t, double value) throws E {
171                                operation.accept(t, value);
172                        }
173
174                        @Override
175                        public Function<Exception, RuntimeException> exceptionMapper() {
176                                return exceptionMapper;
177                        }
178
179                }.uncheck();
180        }
181
182        /**
183         * Converts a {@code ObjLongConsumerWithException} to a lifted
184         * {@code ObjDoubleConsumer} ignoring exception.
185         *
186         * @param operation
187         *            to be lifted
188         * @param <T>
189         *            the type of the object argument to the operation
190         * @param <E>
191         *            the type of the potential exception
192         * @return the lifted operation
193         * @see #lift()
194         * @throws NullPointerException
195         *             if operation is null
196         */
197        static <T, E extends Exception> ObjDoubleConsumer<T> lifted(ObjDoubleConsumerWithException<T, E> operation) {
198                return verifyOperation(operation).lift();
199        }
200
201        /**
202         * Converts a {@code ObjLongConsumerWithException} to a lifted
203         * {@code ObjDoubleConsumer} ignoring exception.
204         *
205         * @param operation
206         *            to be lifted
207         * @param <T>
208         *            the type of the object argument to the operation
209         * @param <E>
210         *            the type of the potential exception
211         * @return the lifted operation
212         * @see #ignore()
213         * @throws NullPointerException
214         *             if operation is null
215         */
216        static <T, E extends Exception> ObjDoubleConsumer<T> ignored(ObjDoubleConsumerWithException<T, E> operation) {
217                return verifyOperation(operation).ignore();
218        }
219
220        /**
221         * Converts a {@code ObjDoubleConsumerWithException} to a staged
222         * {@code BiFunction} .
223         *
224         * @param operation
225         *            to be staged
226         * @param <T>
227         *            the type of the object argument to the operation
228         * @param <E>
229         *            the type of the potential exception
230         * @return the staged operation
231         * @throws NullPointerException
232         *             if operation is null
233         */
234        static <T, E extends Exception> BiFunction<T, Double, CompletionStage<Void>> staged(
235                        ObjDoubleConsumerWithException<T, E> operation) {
236                return verifyOperation(operation).stage();
237        }
238
239        /**
240         * Converts a {@code ObjDoubleConsumerWithException} to a
241         * {@code BiConsumerWithException} returning {@code null}.
242         *
243         * @param operation
244         *            to be lifted
245         * @param <T>
246         *            the type of the object argument to the operation
247         * @param <E>
248         *            the type of the potential exception
249         * @return the function
250         * @throws NullPointerException
251         *             if operation is null
252         * @since 1.1.0
253         */
254        static <T, E extends Exception> BiConsumerWithException<T, Double, E> asBiConsumer(
255                        ObjDoubleConsumerWithException<T, E> operation) {
256                return verifyOperation(operation)::accept;
257        }
258
259}