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 java.util.Objects;
023import java.util.function.Function;
024import java.util.function.Supplier;
025
026/**
027 * Root interface to support global operations related to exception handling.
028 *
029 * @param <F>
030 *            the type of the java standard functional interface. For example,
031 *            {@code Function<T,R>}.
032 * @param <L>
033 *            the type of the lifted functional interface. For example,
034 *            {@code Function<T,Optional<R>>}.
035 * @param <Z>
036 *            the type of the interface it self.
037 */
038public interface ExceptionHandlerSupport<F, L, Z extends ExceptionHandlerSupport<F, L, Z>> {
039
040        /**
041         * Mapping operation to convert the exception that may be thrown during
042         * execution to {@code RuntimeException}.
043         * <p>
044         * The default mapper function may be changed by :
045         * <ul>
046         * <li>Using the second argument of the various {@code unchecked} methods. This
047         * override only the current interface.</li>
048         * <li>By defining global {@code ExceptionMapper}, using the module syntax :
049         * {@code provides ch.powerunit.extensions.exceptions.ExceptionMapper with XXX}</li>
050         * </ul>
051         *
052         * @return the mapping function, which is by default constructing
053         *         {@code WrappedException}.
054         * @see WrappedException
055         */
056        default Function<Exception, RuntimeException> exceptionMapper() {
057                return Constants.MAPPERS;
058        }
059
060        /**
061         * Converts this functional interface to the corresponding one in java and wrap
062         * exception using {@link #exceptionMapper()}.
063         * <p>
064         * Conceptually, the exception encapsulation is done in the following way :
065         *
066         * <pre>
067         * (xxx) -&gt; {
068         *      try {
069         *              // do the underlying functional interface action and return result if
070         *              // applicable
071         *      } catch (Exception e) {
072         *              throw new exceptionMapper().apply(e);
073         *      }
074         * }
075         * </pre>
076         *
077         * @return the unchecked operation
078         * @see #lift()
079         * @see #ignore()
080         */
081        F uncheck();
082
083        /**
084         * Converts this functional interface to a lifted one. A lifted version may or
085         * may not have the same return type of the original one. When possible a
086         * version returning an {@code Optional} is provided. For functional interface
087         * without return value, this method will be identical to {@link #ignore()}.
088         * <p>
089         * For functional interface with Object result, the principle is :
090         *
091         * <pre>
092         * (xxx) -&gt; {
093         *      try {
094         *              return Optional.ofNullable(realaction(xxx));
095         *      } catch (Exception e) {
096         *              return Optional.empty();
097         *      }
098         * }
099         * </pre>
100         *
101         * For functional interface with primitive result, the principle is :
102         *
103         * <pre>
104         * (xxx) -&gt; {
105         *      try {
106         *              return realaction(xxx);
107         *      } catch (Exception e) {
108         *              return defaultValue;
109         *      }
110         * }
111         * </pre>
112         *
113         * For functional interface without result, the principle is :
114         *
115         * <pre>
116         * (xxx) -&gt; {
117         *      try {
118         *              realaction(xxx);
119         *      } catch (Exception e) {
120         *              // do nothing
121         *      }
122         * }
123         * </pre>
124         *
125         * @return the lifted function
126         * @see #uncheck()
127         * @see #ignore()
128         */
129        L lift();
130
131        /**
132         * Converts this functional interface to the corresponding java standard
133         * functional interface returning a default value in case of error. For function
134         * interface without return value, error will be silently ignored.
135         *
136         * <p>
137         * For functional interface with Object result, the principle is :
138         *
139         * <pre>
140         * (xxx) -&gt; {
141         *      try {
142         *              return realaction(xxx);
143         *      } catch (Exception e) {
144         *              return null;
145         *      }
146         * }
147         * </pre>
148         *
149         * For functional interface with primitive result, the principle is :
150         *
151         * <pre>
152         * (xxx) -&gt; {
153         *      try {
154         *              return realaction(xxx);
155         *      } catch (Exception e) {
156         *              return defaultValue;
157         *      }
158         * }
159         * </pre>
160         *
161         * For functional interface without result, the principle is :
162         *
163         * <pre>
164         * (xxx) -&gt; {
165         *      try {
166         *              realaction(xxx);
167         *      } catch (Exception e) {
168         *              // do nothing
169         *      }
170         * }
171         * </pre>
172         *
173         * @return the operation that ignore error
174         * @see #uncheck()
175         * @see #lift()
176         */
177        F ignore();
178
179        /**
180         * Add a {@code toString} method to the existing interface based on the received
181         * {@code Supplier}.
182         * 
183         * @param toString
184         *            the supplier to be used
185         * @return a new interface, with {@code toString} using the received supplier.
186         * @throws NullPointerException
187         *             if toString is null
188         * @since 3.0.0
189         */
190        @SuppressWarnings("unchecked")
191        default Z documented(Supplier<String> toString) {
192                return (Z) InternalHelper.documented(this, Objects.requireNonNull(toString, "toString can't be null"));
193        }
194
195}