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.LongConsumer;
029import java.util.function.LongFunction;
030import java.util.function.Supplier;
031
032/**
033 * Represents an operation that accepts a single {@code long}-valued argument,
034 * may throw exception and returns no result. This is the primitive type
035 * specialization of {@link ConsumerWithException} for {@code long}. Unlike most
036 * other functional interfaces, {@code LongConsumerWithException} is expected to
037 * operate via side-effects.
038 * <h3>General contract</h3>
039 * <ul>
040 * <li><b>{@link #accept(long) void accept(long value) throws
041 * E}</b>&nbsp;-&nbsp;The functional method.</li>
042 * <li><b>uncheck</b>&nbsp;-&nbsp;Return a {@code LongConsumer}</li>
043 * <li><b>lift</b>&nbsp;-&nbsp;Return a {@code LongConsumer}</li>
044 * <li><b>ignore</b>&nbsp;-&nbsp;Return a {@code LongConsumer}</li>
045 * </ul>
046 *
047 * @see LongConsumer
048 * @param <E>
049 *            the type of the potential exception of the operation
050 */
051@FunctionalInterface
052public interface LongConsumerWithException<E extends Exception> extends
053                NoReturnExceptionHandlerSupport<LongConsumer, LongFunction<CompletionStage<Void>>, LongConsumerWithException<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 LongConsumer#accept(long)
063         */
064        void accept(long value) throws E;
065
066        /**
067         * Converts this {@code LongConsumerWithException} to a {@code LongConsumer}
068         * that convert exception to {@code RuntimeException}.
069         *
070         * @return the unchecked operation
071         * @see #unchecked(LongConsumerWithException)
072         * @see #unchecked(LongConsumerWithException, Function)
073         */
074        @Override
075        default LongConsumer uncheck() {
076                return t -> NoReturnExceptionHandlerSupport.unchecked(() -> accept(t), throwingHandler());
077        }
078
079        /**
080         * Converts this {@code LongConsumerWithException} to a <i>lifted</i>
081         * {@code LongConsumer} ignoring exception.
082         *
083         * @return the operation that ignore error
084         * @see #ignored(LongConsumerWithException)
085         */
086        @Override
087        default LongConsumer ignore() {
088                return t -> NoReturnExceptionHandlerSupport.unchecked(() -> accept(t), notThrowingHandler());
089        }
090
091        /**
092         * Converts this {@code LongConsumerWithException} to a <i>staged</i>
093         * {@code LongFunction} that return a {@code CompletionStage}.
094         *
095         * @return the staged operation.
096         * @since 1.1.0
097         */
098        @Override
099        default LongFunction<CompletionStage<Void>> stage() {
100                return t -> NoReturnExceptionHandlerSupport.staged(() -> accept(t));
101        }
102
103        /**
104         * Returns a composed {@code LongConsumerWithException} 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 LongConsumer} 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 LongConsumer#andThen(LongConsumer)
119         */
120        default LongConsumerWithException<E> andThen(LongConsumerWithException<? 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> LongConsumerWithException<E> failing(Supplier<E> exceptionBuilder) {
138                return t -> {
139                        throw exceptionBuilder.get();
140                };
141        }
142
143        /**
144         * Converts a {@code LongConsumerWithException} to a {@code LongConsumer} that
145         * convert 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(LongConsumerWithException, Function)
154         * @throws NullPointerException
155         *             if operation is null
156         */
157        static <E extends Exception> LongConsumer unchecked(LongConsumerWithException<E> operation) {
158                return verifyOperation(operation).uncheck();
159        }
160
161        /**
162         * Converts a {@code LongConsumerWithException} to a {@code LongConsumer} that
163         * convert 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(LongConsumerWithException)
175         * @throws NullPointerException
176         *             if operation or exceptionMapper is null
177         */
178        static <E extends Exception> LongConsumer unchecked(LongConsumerWithException<E> operation,
179                        Function<Exception, RuntimeException> exceptionMapper) {
180                verifyOperation(operation);
181                verifyExceptionMapper(exceptionMapper);
182                return new LongConsumerWithException<E>() {
183
184                        @Override
185                        public void accept(long 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 LongConsumerWithException} to a lifted {@code LongConsumer}
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         * @throws NullPointerException
208         *             if operation is null
209         */
210        static <E extends Exception> LongConsumer lifted(LongConsumerWithException<E> operation) {
211                return verifyOperation(operation).lift();
212        }
213
214        /**
215         * Converts a {@code LongConsumerWithException} to a lifted {@code LongConsumer}
216         * ignoring exception.
217         *
218         * @param operation
219         *            to be lifted
220         * @param <E>
221         *            the type of the potential exception
222         * @return the lifted operation
223         * @see #ignore()
224         * @throws NullPointerException
225         *             if operation is null
226         */
227        static <E extends Exception> LongConsumer ignored(LongConsumerWithException<E> operation) {
228                return verifyOperation(operation).ignore();
229        }
230
231        /**
232         * Converts a {@code LongConsumerWithException} to a staged {@code LongFunction}
233         * .
234         *
235         * @param operation
236         *            to be staged
237         * @param <E>
238         *            the type of the potential exception
239         * @return the staged operation
240         * @throws NullPointerException
241         *             if operation is null
242         * @since 1.1.0
243         */
244        static <E extends Exception> LongFunction<CompletionStage<Void>> staged(LongConsumerWithException<E> operation) {
245                return verifyOperation(operation).stage();
246        }
247
248        /**
249         * Converts a {@code LongConsumerWithException} to a
250         * {@code ConsumerWithException}.
251         *
252         * @param operation
253         *            to be converted
254         * @param <E>
255         *            the type of the potential exception
256         * @return the consumer
257         * @throws NullPointerException
258         *             if operation is null
259         */
260        static <E extends Exception> ConsumerWithException<Long, E> asConsumer(LongConsumerWithException<E> operation) {
261                return verifyOperation(operation)::accept;
262        }
263}