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.verifySupplier;
024
025import java.util.function.DoubleSupplier;
026import java.util.function.Function;
027import java.util.function.Supplier;
028
029/**
030 * Represents a supplier of {@code double}-valued results and may throw
031 * exception. This is the {@code double}-producing primitive specialization of
032 * {@link SupplierWithException}.
033 * <p>
034 * There is no requirement that a distinct result be returned each time the
035 * supplier is invoked.
036 * <h3>General contract</h3>
037 * <ul>
038 * <li><b>{@link #getAsDouble() double getAsDouble() throws
039 * E}</b>&nbsp;-&nbsp;The functional method.</li>
040 * <li><b>uncheck</b>&nbsp;-&nbsp;Return a {@code DoubleSupplier}</li>
041 * <li><b>lift</b>&nbsp;-&nbsp;Return a {@code DoubleSupplier}</li>
042 * <li><b>ignore</b>&nbsp;-&nbsp;Return a {@code DoubleSupplier}</li>
043 * </ul>
044 *
045 * @see DoubleSupplier
046 * @param <E>
047 *            the type of the potential exception of the operation
048 */
049@FunctionalInterface
050public interface DoubleSupplierWithException<E extends Exception> extends
051                PrimitiveReturnExceptionHandlerSupport<DoubleSupplier, DoubleSupplierWithException<E>>, DoubleDefaultValue {
052
053        /**
054         * Gets a result.
055         *
056         * @throws E
057         *             any exception
058         * @return a result
059         * @see DoubleSupplier#getAsDouble()
060         */
061        double getAsDouble() throws E;
062
063        @Override
064        default DoubleSupplier uncheckOrIgnore(boolean uncheck) {
065                return () -> {
066                        try {
067                                return getAsDouble();
068                        } catch (Exception e) {
069                                PrimitiveReturnExceptionHandlerSupport.handleException(uncheck, e, exceptionMapper());
070                                return defaultValue();
071                        }
072                };
073        }
074
075        /**
076         * Returns a supplier that always throw exception.
077         *
078         * @param exceptionBuilder
079         *            the supplier to create the exception
080         * @param <E>
081         *            the type of the exception
082         * @return an operation that always throw exception
083         */
084        static <E extends Exception> DoubleSupplierWithException<E> failing(Supplier<E> exceptionBuilder) {
085                return () -> {
086                        throw exceptionBuilder.get();
087                };
088        }
089
090        /**
091         * Converts a {@code DoubleSupplierWithException} to a {@code DoubleSupplier}
092         * that wraps exception to {@code RuntimeException}.
093         *
094         * @param supplier
095         *            to be unchecked
096         * @param <E>
097         *            the type of the potential exception
098         * @return the unchecked supplier
099         * @see #uncheck()
100         * @see #unchecked(DoubleSupplierWithException, Function)
101         * @throws NullPointerException
102         *             if supplier is null
103         */
104        static <E extends Exception> DoubleSupplier unchecked(DoubleSupplierWithException<E> supplier) {
105                return verifySupplier(supplier).uncheck();
106        }
107
108        /**
109         * Converts a {@code DoubleSupplierWithException} to a {@code DoubleSupplier}
110         * that wraps exception to {@code RuntimeException} by using the provided
111         * mapping function.
112         *
113         * @param supplier
114         *            the be unchecked
115         * @param exceptionMapper
116         *            a function to convert the exception to the runtime exception.
117         * @param <E>
118         *            the type of the potential exception
119         * @return the unchecked supplier
120         * @see #uncheck()
121         * @see #unchecked(DoubleSupplierWithException)
122         * @throws NullPointerException
123         *             if supplier or exceptionMapper is null
124         */
125        static <E extends Exception> DoubleSupplier unchecked(DoubleSupplierWithException<E> supplier,
126                        Function<Exception, RuntimeException> exceptionMapper) {
127                verifySupplier(supplier);
128                verifyExceptionMapper(exceptionMapper);
129                return new DoubleSupplierWithException<E>() {
130
131                        @Override
132                        public double getAsDouble() throws E {
133                                return supplier.getAsDouble();
134                        }
135
136                        @Override
137                        public Function<Exception, RuntimeException> exceptionMapper() {
138                                return exceptionMapper;
139                        }
140
141                }.uncheck();
142        }
143
144        /**
145         * Converts a {@code DoubleSupplierWithException} to a lifted
146         * {@code DoubleSupplier} returning {@code 0} in case of exception.
147         *
148         * @param supplier
149         *            to be lifted
150         * @param <E>
151         *            the type of the potential exception
152         * @return the lifted supplier
153         * @see #lift()
154         * @throws NullPointerException
155         *             if supplier is null
156         */
157        static <E extends Exception> DoubleSupplier lifted(DoubleSupplierWithException<E> supplier) {
158                return verifySupplier(supplier).lift();
159        }
160
161        /**
162         * Converts a {@code DoubleSupplierWithException} to a lifted
163         * {@code DoubleSupplier} returning {@code 0} in case of exception.
164         *
165         * @param supplier
166         *            to be lifted
167         * @param <E>
168         *            the type of the potential exception
169         * @return the lifted supplier
170         * @see #ignore()
171         * @throws NullPointerException
172         *             if supplier is null
173         */
174        static <E extends Exception> DoubleSupplier ignored(DoubleSupplierWithException<E> supplier) {
175                return verifySupplier(supplier).ignore();
176        }
177
178        /**
179         * Converts a {@code DoubleSupplierWithException} to a lifted
180         * {@code DoubleSupplier} returning a default value in case of exception.
181         *
182         * @param supplier
183         *            to be lifted
184         * @param defaultValue
185         *            the default value in case of exception
186         * @param <E>
187         *            the type of the potential exception
188         * @return the lifted supplier
189         * @see #ignore()
190         * @see #ignored(DoubleSupplierWithException)
191         * @throws NullPointerException
192         *             if supplier is null
193         * @since 3.0.0
194         */
195        static <E extends Exception> DoubleSupplier ignored(DoubleSupplierWithException<E> supplier, double defaultValue) {
196                verifySupplier(supplier);
197                return new DoubleSupplierWithException<E>() {
198
199                        @Override
200                        public double getAsDouble() throws E {
201                                return supplier.getAsDouble();
202                        }
203
204                        @Override
205                        public double defaultValue() {
206                                return defaultValue;
207                        }
208
209                }.ignore();
210        }
211
212}