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.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;
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)}.
29 * @param <T> Value type
30 * @param <E> Exception type
31 * @author Robert Varga
35 public class CheckedValue<T, E extends Exception> extends Either<T, E> {
36 protected CheckedValue(final T value) {
40 protected CheckedValue(final E violation, final @Nullable Void dummy) {
41 super(violation, dummy);
45 * Create a new instance containing an {@link Exception}.
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
53 public static <T, E extends Exception> CheckedValue<T, E> ofException(final E cause) {
54 return new CheckedValue<>(cause, null);
58 * Create a new instance containing specified value.
61 * @param <T> Value type
62 * @param <E> Exception type
63 * @return A new instance
64 * @throws NullPointerException if {@code value} is null
66 public static <T, E extends Exception> CheckedValue<T, E> ofValue(final T value) {
67 return new CheckedValue<>(value);
71 * Convert a Variant into a {@link CheckedValue}, converting the second value into an exception.
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}
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);
88 * Return the contained value if {@link #isPresent()} would return true, throws {@link IllegalStateException}
91 * @return Contained value
92 * @throws IllegalStateException if an error string is present.
94 public final T get() {
98 throw new IllegalStateException("Value is not present", second());
102 * Return the contained error string if {@link #isPresent()} would return false, throws
103 * {@link IllegalStateException} otherwise.
105 * @return Throwable which was used to instantiate this object, or absent if it was instantiated using an error
107 * @throws IllegalStateException if a value is present.
109 public final E getException() {
113 throw new IllegalStateException("Value " + first() + " is present");
117 * Return true if a value is present.
119 * @return True if a value is present.
121 public final boolean isPresent() {
126 * If a value is present, invoke the specified consumer with the value, otherwise do nothing.
128 * @param consumer block to be executed if a value is present
129 * @throws NullPointerException if value is present and {@code consumer} is null
131 public final void ifPresent(final Consumer<? super T> consumer) {
133 consumer.accept(first());
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;
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);
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;
156 * Return contained value if present, otherwise return supplied value.
158 * @param other Replacement value
159 * @return Contained value or {code other}
161 public final T orElse(final T other) {
162 return isFirst() ? first() : other;
166 * Return contained value if present, otherwise return the value produced by a supplier.
168 * @param supplier Replacement value supplier
169 * @return Contained value or supplier's value
170 * @throws NullPointerException if {@code supplier} is null
172 public final T orElseGet(final Supplier<T> supplier) {
173 requireNonNull(supplier);
174 return isFirst() ? first() : supplier.get();
178 * Return contained value if present or throw the exception alternative.
180 * @return Contained value
181 * @throws E When there is no contained value
183 public final T orElseThrow() throws E {
191 * Return contained value if present or throw the exception alternative mapped through provided mapper.
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
199 public final <X extends Throwable> T orElseThrow(final Function<E, X> exceptionMapper) throws X {
200 requireNonNull(exceptionMapper);
204 throw exceptionMapper.apply(second());
208 * Complete target {@link CompletableFuture} either successfully or exceptionally based on the state of this object.
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
214 public final boolean completeFuture(final CompletableFuture<T> future) {
215 return isFirst() ? future.complete(first()) : future.completeExceptionally(second());
219 * Complete target {@link SettableFuture} either successfully or exceptionally based on the state of this object.
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
225 public final boolean completeFuture(final SettableFuture<T> future) {
226 return isFirst() ? future.set(first()) : future.setException(second());
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.
233 * @return A {@link CompletableFuture}.
235 public final CompletableFuture<T> toCompletableFuture() {
236 return isFirst() ? CompletableFuture.completedFuture(first()) : CompletableFuture.failedFuture(second());
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.
243 * @return A {@link FluentFuture}.
245 public final FluentFuture<T> toFluentFuture() {
246 return FluentFuture.from(isFirst() ? Futures.immediateFuture(first())
247 : Futures.immediateFailedFuture(second()));