2 * Copyright (c) 2018 Pantheon Technologies, s.r.o. and others. All rights reserved.
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
8 package org.opendaylight.yangtools.concepts;
10 import static java.util.Objects.requireNonNull;
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.ListenableFuture;
16 import com.google.common.util.concurrent.SettableFuture;
17 import java.util.concurrent.CompletableFuture;
18 import java.util.function.Consumer;
19 import java.util.function.Function;
20 import java.util.function.Supplier;
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.eclipse.jdt.annotation.Nullable;
25 * Utility holder similar to {@link java.util.Optional}, except the empty case contains an Exception, which should be
26 * reported, for example via throwing it. It provides analogous methods such as {@link #isPresent()},
27 * {@link #ifPresent(Consumer)}, {@link #get()}, {@link #orElse(Object)}, {@link #orElseGet(Supplier)},
28 * {@link #orElseThrow(Function)}.
30 * @param <T> Value type
31 * @param <E> Exception type
32 * @author Robert Varga
36 public class CheckedValue<T, E extends Exception> extends Variant<T, E> {
37 protected CheckedValue(final T value) {
41 protected CheckedValue(final E violation, final @Nullable Void dummy) {
42 super(violation, dummy);
46 * Create a new instance containing an {@link Exception}.
48 * @param cause Throwable
49 * @param <T> Value type
50 * @param <E> Exception type
51 * @return A new instance
52 * @throws NullPointerException if {@code cause} is null
54 public static <T, E extends Exception> CheckedValue<T, E> ofException(final E cause) {
55 return new CheckedValue<>(cause, null);
59 * Create a new instance containing specified value.
62 * @param <T> Value type
63 * @param <E> Exception type
64 * @return A new instance
65 * @throws NullPointerException if {@code value} is null
67 public static <T, E extends Exception> CheckedValue<T, E> ofValue(final T value) {
68 return new CheckedValue<>(value);
72 * Convert a Variant into a {@link CheckedValue}, converting the second value into an exception.
74 * @param variant Input variant
75 * @param mapper Mapping function from second alternative to an exception
76 * @param <T> First alternative type
77 * @param <U> Second alternative type
78 * @param <E> Exception type
79 * @return Resulting {@link CheckedValue}
81 public static <T, U, E extends Exception> CheckedValue<T, E> ofVariant(final Variant<T, U> variant,
82 final Function<U, E> mapper) {
83 requireNonNull(mapper);
84 return variant.isFirst() ? new CheckedValue<>(variant.first())
85 : new CheckedValue<>(mapper.apply(variant.second()), null);
89 * Return the contained value if {@link #isPresent()} would return true, throws {@link IllegalStateException}
92 * @return Contained value
93 * @throws IllegalStateException if an error string is present.
95 public final T get() {
99 throw new IllegalStateException("Value is not present", second());
103 * Return the contained error string if {@link #isPresent()} would return false, throws
104 * {@link IllegalStateException} otherwise.
106 * @return Throwable which was used to instantiate this object, or absent if it was instantiated using an error
108 * @throws IllegalStateException if a value is present.
110 public final E getException() {
114 throw new IllegalStateException("Value " + first() + " is present");
118 * Return true if a value is present.
120 * @return True if a value is present.
122 public final boolean isPresent() {
127 * If a value is present, invoke the specified consumer with the value, otherwise do nothing.
129 * @param consumer block to be executed if a value is present
130 * @throws NullPointerException if value is present and {@code consumer} is null
132 public final void ifPresent(final Consumer<? super T> consumer) {
134 consumer.accept(first());
138 @SuppressWarnings("unchecked")
139 public <U> CheckedValue<U, E> map(final Function<? super T, U> mapper) {
140 requireNonNull(mapper);
141 return isFirst() ? new CheckedValue<>(mapper.apply(first())) : (CheckedValue<U, E>) this;
144 @SuppressWarnings("unchecked")
145 public <X extends Exception> CheckedValue<T, X> mapException(final Function<? super E, X> mapper) {
146 requireNonNull(mapper);
148 return (CheckedValue<T, X>) this;
150 return new CheckedValue<>(mapper.apply(second()), null);
154 @SuppressWarnings("unchecked")
155 public <U> CheckedValue<U, E> flatMap(final Function<? super T, CheckedValue<U, E>> mapper) {
156 requireNonNull(mapper);
157 return isFirst() ? requireNonNull(mapper.apply(first())) : (CheckedValue<U, E>) this;
161 * Return contained value if present, otherwise return supplied value.
163 * @param other Replacement value
164 * @return Contained value or {code other}
166 public final T orElse(final T other) {
167 return isFirst() ? first() : other;
171 * Return contained value if present, otherwise return the value produced by a supplier.
173 * @param supplier Replacement value supplier
174 * @return Contained value or supplier's value
175 * @throws NullPointerException if {@code supplier} is null
177 public final T orElseGet(final Supplier<T> supplier) {
178 requireNonNull(supplier);
179 return isFirst() ? first() : supplier.get();
183 * Return contained value if present or throw the exception alternative.
185 * @return Contained value
186 * @throws E When there is no contained value
188 public final T orElseThrow() throws E {
196 * Return contained value if present or throw the exception alternative mapped through provided mapper.
198 * @param exceptionMapper Exception mapper
199 * @param <X> Thrown exception type
200 * @return Contained value
201 * @throws NullPointerException if {@code exceptionMapper} is null
202 * @throws X When there is no contained value
204 public final <X extends Throwable> T orElseThrow(final Function<E, X> exceptionMapper) throws X {
205 requireNonNull(exceptionMapper);
209 throw exceptionMapper.apply(second());
213 * Return contained value if present or throw the exception supplied by supplier.
215 * @param supplier Exception supplier
216 * @param <X> Thrown exception type
217 * @return Contained value
218 * @throws NullPointerException if {@code exceptionMapper} is null
219 * @throws X When there is no contained value
221 public final <X extends Throwable> T orElseThrow(final Supplier<X> supplier) throws X {
222 requireNonNull(supplier);
226 throw supplier.get();
230 * Complete target {@link CompletableFuture} either successfully or exceptionally based on the state of this object.
232 * @param future Future to complete
233 * @return True if this call has transitioned the future to a completed state, false otherwise.
234 * @throws NullPointerException if {code future} is null
236 public final boolean completeFuture(final CompletableFuture<T> future) {
237 return isFirst() ? future.complete(first()) : future.completeExceptionally(second());
241 * Complete target {@link SettableFuture} either successfully or exceptionally based on the state of this object.
243 * @param future Future to complete
244 * @return True if this call has transitioned the future to a completed state, false otherwise.
245 * @throws NullPointerException if {code future} is null
247 public final boolean completeFuture(final SettableFuture<T> future) {
248 return isFirst() ? future.set(first()) : future.setException(second());
252 * Transform this object into an immediately-completed {@link CompletableFuture}. The future will be successful
253 * if this object has a contained value or unsuccessful if this objects contains an exception.
255 * @return A {@link CompletableFuture}.
257 public final CompletableFuture<T> toCompletableFuture() {
259 return CompletableFuture.completedFuture(first());
261 // FIXME: Java 9: use CompletableFuture.failedFuture()
262 final CompletableFuture<T> future = new CompletableFuture<>();
263 future.completeExceptionally(second());
268 * Transform this object into an immediately-completed {@link FluentFuture}. The future will be successful
269 * if this object has a contained value or unsuccessful if this objects contains an exception.
271 * @return A {@link FluentFuture}.
273 public final FluentFuture<T> toFluentFuture() {
274 final ListenableFuture<T> future;
276 future = Futures.immediateFuture(first());
278 future = Futures.immediateFailedFuture(second());
280 return FluentFuture.from(future);