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