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