Remove CheckedValue.orElseThrow(Supplier)
[yangtools.git] / common / concepts / src / main / java / org / opendaylight / yangtools / concepts / CheckedValue.java
1 /*
2  * Copyright (c) 2018 Pantheon Technologies, s.r.o. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.yangtools.concepts;
9
10 import static java.util.Objects.requireNonNull;
11
12 import com.google.common.annotations.Beta;
13 import com.google.common.util.concurrent.FluentFuture;
14 import com.google.common.util.concurrent.Futures;
15 import com.google.common.util.concurrent.SettableFuture;
16 import java.util.concurrent.CompletableFuture;
17 import java.util.function.Consumer;
18 import java.util.function.Function;
19 import java.util.function.Supplier;
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.eclipse.jdt.annotation.Nullable;
22
23 /**
24  * Utility holder similar to {@link java.util.Optional}, except the empty case contains an Exception, which should be
25  * reported, for example via throwing it. It provides analogous methods such as {@link #isPresent()},
26  * {@link #ifPresent(Consumer)}, {@link #get()}, {@link #orElse(Object)}, {@link #orElseGet(Supplier)},
27  * {@link #orElseThrow(Function)}.
28  *
29  * @param <T> Value type
30  * @param <E> Exception type
31  * @author Robert Varga
32  */
33 @Beta
34 @NonNullByDefault
35 public class CheckedValue<T, E extends Exception> extends Either<T, E> {
36     protected CheckedValue(final T value) {
37         super(value);
38     }
39
40     protected CheckedValue(final E violation, final @Nullable Void dummy) {
41         super(violation, dummy);
42     }
43
44     /**
45      * Create a new instance containing an {@link Exception}.
46      *
47      * @param cause Throwable
48      * @param <T> Value type
49      * @param <E> Exception type
50      * @return A new instance
51      * @throws NullPointerException if {@code cause} is null
52      */
53     public static <T, E extends Exception> CheckedValue<T, E> ofException(final E cause) {
54         return new CheckedValue<>(cause, null);
55     }
56
57     /**
58      * Create a new instance containing specified value.
59      *
60      * @param value Value
61      * @param <T> Value type
62      * @param <E> Exception type
63      * @return A new instance
64      * @throws NullPointerException if {@code value} is null
65      */
66     public static <T, E extends Exception> CheckedValue<T, E> ofValue(final T value) {
67         return new CheckedValue<>(value);
68     }
69
70     /**
71      * Convert a Variant into a {@link CheckedValue}, converting the second value into an exception.
72      *
73      * @param variant Input variant
74      * @param mapper Mapping function from second alternative to an exception
75      * @param <T> First alternative type
76      * @param <U> Second alternative type
77      * @param <E> Exception type
78      * @return Resulting {@link CheckedValue}
79      */
80     public static <T, U, E extends Exception> CheckedValue<T, E> ofVariant(final Either<T, U> variant,
81             final Function<U, E> mapper) {
82         requireNonNull(mapper);
83         return variant.isFirst() ? new CheckedValue<>(variant.first())
84                 : new CheckedValue<>(mapper.apply(variant.second()), null);
85     }
86
87     /**
88      * Return the contained value if {@link #isPresent()} would return true, throws {@link IllegalStateException}
89      * otherwise.
90      *
91      * @return Contained value
92      * @throws IllegalStateException if an error string is present.
93      */
94     public final T get() {
95         if (isFirst()) {
96             return first();
97         }
98         throw new IllegalStateException("Value is not present", second());
99     }
100
101     /**
102      * Return the contained error string if {@link #isPresent()} would return false, throws
103      * {@link IllegalStateException} otherwise.
104      *
105      * @return Throwable which was used to instantiate this object, or absent if it was instantiated using an error
106      *         string.
107      * @throws IllegalStateException if a value is present.
108      */
109     public final E getException() {
110         if (isSecond()) {
111             return second();
112         }
113         throw new IllegalStateException("Value " + first() + " is present");
114     }
115
116     /**
117      * Return true if a value is present.
118      *
119      * @return True if a value is present.
120      */
121     public final boolean isPresent() {
122         return isFirst();
123     }
124
125     /**
126      * If a value is present, invoke the specified consumer with the value, otherwise do nothing.
127      *
128      * @param consumer block to be executed if a value is present
129      * @throws NullPointerException if value is present and {@code consumer} is null
130      */
131     public final void ifPresent(final Consumer<? super T> consumer) {
132         if (isFirst()) {
133             consumer.accept(first());
134         }
135     }
136
137     @SuppressWarnings("unchecked")
138     public <U> CheckedValue<U, E> map(final Function<? super T, U> mapper) {
139         requireNonNull(mapper);
140         return isFirst() ? new CheckedValue<>(mapper.apply(first())) : (CheckedValue<U, E>) this;
141     }
142
143     @SuppressWarnings("unchecked")
144     public <X extends Exception> CheckedValue<T, X> mapException(final Function<? super E, X> mapper) {
145         requireNonNull(mapper);
146         return isFirst() ? (CheckedValue<T, X>) this : new CheckedValue<>(mapper.apply(second()), null);
147     }
148
149     @SuppressWarnings("unchecked")
150     public <U> CheckedValue<U, E> flatMap(final Function<? super T, CheckedValue<U, E>> mapper) {
151         requireNonNull(mapper);
152         return isFirst() ? requireNonNull(mapper.apply(first())) : (CheckedValue<U, E>) this;
153     }
154
155     /**
156      * Return contained value if present, otherwise return supplied value.
157      *
158      * @param other Replacement value
159      * @return Contained value or {code other}
160      */
161     public final T orElse(final T other) {
162         return isFirst() ? first() : other;
163     }
164
165     /**
166      * Return contained value if present, otherwise return the value produced by a supplier.
167      *
168      * @param supplier Replacement value supplier
169      * @return Contained value or supplier's value
170      * @throws NullPointerException if {@code supplier} is null
171      */
172     public final T orElseGet(final Supplier<T> supplier) {
173         requireNonNull(supplier);
174         return isFirst() ? first() : supplier.get();
175     }
176
177     /**
178      * Return contained value if present or throw the exception alternative.
179      *
180      * @return Contained value
181      * @throws E When there is no contained value
182      */
183     public final T orElseThrow() throws E {
184         if (isFirst()) {
185             return first();
186         }
187         throw second();
188     }
189
190     /**
191      * Return contained value if present or throw the exception alternative mapped through provided mapper.
192      *
193      * @param exceptionMapper Exception mapper
194      * @param <X> Thrown exception type
195      * @return Contained value
196      * @throws NullPointerException if {@code exceptionMapper} is null
197      * @throws X When there is no contained value
198      */
199     public final <X extends Throwable> T orElseThrow(final Function<E, X> exceptionMapper) throws X {
200         requireNonNull(exceptionMapper);
201         if (isFirst()) {
202             return first();
203         }
204         throw exceptionMapper.apply(second());
205     }
206
207     /**
208      * Complete target {@link CompletableFuture} either successfully or exceptionally based on the state of this object.
209      *
210      * @param future Future to complete
211      * @return True if this call has transitioned the future to a completed state, false otherwise.
212      * @throws NullPointerException if {code future} is null
213      */
214     public final boolean completeFuture(final CompletableFuture<T> future) {
215         return isFirst() ? future.complete(first()) : future.completeExceptionally(second());
216     }
217
218     /**
219      * Complete target {@link SettableFuture} either successfully or exceptionally based on the state of this object.
220      *
221      * @param future Future to complete
222      * @return True if this call has transitioned the future to a completed state, false otherwise.
223      * @throws NullPointerException if {code future} is null
224      */
225     public final boolean completeFuture(final SettableFuture<T> future) {
226         return isFirst() ? future.set(first()) : future.setException(second());
227     }
228
229     /**
230      * Transform this object into an immediately-completed {@link CompletableFuture}. The future will be successful
231      * if this object has a contained value or unsuccessful if this objects contains an exception.
232      *
233      * @return A {@link CompletableFuture}.
234      */
235     public final CompletableFuture<T> toCompletableFuture() {
236         return isFirst() ? CompletableFuture.completedFuture(first()) : CompletableFuture.failedFuture(second());
237     }
238
239     /**
240      * Transform this object into an immediately-completed {@link FluentFuture}. The future will be successful
241      * if this object has a contained value or unsuccessful if this objects contains an exception.
242      *
243      * @return A {@link FluentFuture}.
244      */
245     public final FluentFuture<T> toFluentFuture() {
246         return FluentFuture.from(isFirst() ? Futures.immediateFuture(first())
247                 : Futures.immediateFailedFuture(second()));
248     }
249 }