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 java.util.concurrent.CompletableFuture.completedFuture;
023import static java.util.concurrent.CompletableFuture.failedFuture;
024
025import java.util.concurrent.CompletionStage;
026import java.util.function.Consumer;
027
028/**
029 * Root interface to support global operations related to exception handling for
030 * functional interface without return value.
031 *
032 * @param <F>
033 *            the type of the java standard functional interface. For example,
034 *            {@code Consumer<T>}. The same functional interface is also used
035 *            for the lifted and ignored version.
036 * @param <S>
037 *            the type of a java standard function interface to return a
038 *            {@code CompletionStage}.
039 */
040public interface NoReturnExceptionHandlerSupport<F, S, Z extends NoReturnExceptionHandlerSupport<F, S, Z>>
041                extends ExceptionHandlerSupport<F, F, Z> {
042
043        /**
044         * Converts this functional interface to the corresponding one in java and wrap
045         * exception using {@link #exceptionMapper()}.
046         * <p>
047         * Conceptually, the exception encapsulation is done in the following way :
048         *
049         * <pre>
050         * (xxx) -&gt; {
051         *      try {
052         *              // do the underlying functional interface action and return result if
053         *              // applicable
054         *      } catch (Exception e) {
055         *              throw new exceptionMapper().apply(e);
056         *      }
057         * }
058         * </pre>
059         *
060         * @return the unchecked operation
061         * @see #lift()
062         * @see #ignore()
063         */
064        @Override
065        F uncheck();
066
067        /**
068         * Converts this functional interface to a lifted one.
069         * <p>
070         * The concept is :
071         *
072         * <pre>
073         * (xxx) -&gt; {
074         *      try {
075         *              realaction(xxx);
076         *      } catch (Exception e) {
077         *              // do nothing
078         *      }
079         * }
080         * </pre>
081         *
082         * @return the lifted function
083         * @see #uncheck()
084         * @see #ignore()
085         */
086        @Override
087        default F lift() {
088                return ignore();
089        }
090
091        /**
092         * Converts this functional interface to a lifted one.
093         * <p>
094         * The concept is :
095         *
096         * <pre>
097         * (xxx) -&gt; {
098         *      try {
099         *              realaction(xxx);
100         *      } catch (Exception e) {
101         *              // do nothing
102         *      }
103         * }
104         * </pre>
105         *
106         * @return the lifted function
107         * @see #uncheck()
108         * @see #ignore()
109         */
110        @Override
111        F ignore();
112
113        /**
114         * Converts this functional interface to a lifted one, using a
115         * {@code CompletionStage} as a return value.
116         *
117         * @return the lifted function
118         * @since 1.1.0
119         */
120        S stage();
121
122        /**
123         * Used internally to support the exception interception.
124         *
125         * @param internal
126         *            the call to be done
127         * @param exceptionhandler
128         *            the exception handler. May throw RuntimeException..
129         * @throws RuntimeException
130         *             in case of error
131         */
132        static void unchecked(RunnableWithException<?> internal, Consumer<Exception> exceptionhandler) {
133                try {
134                        internal.run();
135                } catch (Exception e) {
136                        // exceptionhandler must throw the exception if needed
137                        exceptionhandler.accept(e);
138                }
139        }
140
141        /**
142         * Used internally to support the exception interception.
143         *
144         * @param internal
145         *            the call to be done
146         * @return the completion stage
147         * @throws RuntimeException
148         *             in case of error
149         */
150        static CompletionStage<Void> staged(RunnableWithException<?> internal) {
151                try {
152                        internal.run();
153                        return completedFuture(null);
154                } catch (Exception e) {
155                        return failedFuture(e);
156                }
157        }
158
159        /**
160         * Used internally to support the exception interception.
161         *
162         * @return exception handler to support exception control
163         */
164        default Consumer<Exception> throwingHandler() {
165                return e -> {
166                        throw exceptionMapper().apply(e);
167                };
168        }
169
170        /**
171         * Used internally to support the exception interception.
172         *
173         * @return exception handler to ignore exception control
174         */
175        default Consumer<Exception> notThrowingHandler() {
176                return e -> {
177                };
178        }
179}