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