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