All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opendaylight.yangtools.concepts.CheckedValue Maven / Gradle / Ivy

There is a newer version: 14.0.4
Show newest version
/*
 * Copyright (c) 2018 Pantheon Technologies, s.r.o. and others.  All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 */
package org.opendaylight.yangtools.concepts;

import static java.util.Objects.requireNonNull;

import com.google.common.annotations.Beta;
import com.google.common.util.concurrent.FluentFuture;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.SettableFuture;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;

/**
 * Utility holder similar to {@link java.util.Optional}, except the empty case contains an Exception, which should be
 * reported, for example via throwing it. It provides analogous methods such as {@link #isPresent()},
 * {@link #ifPresent(Consumer)}, {@link #get()}, {@link #orElse(Object)}, {@link #orElseGet(Supplier)},
 * {@link #orElseThrow(Function)}.
 *
 * @param  Value type
 * @param  Exception type
 * @author Robert Varga
 */
@Beta
@NonNullByDefault
public class CheckedValue extends Either {
    protected CheckedValue(final T value) {
        super(value);
    }

    protected CheckedValue(final E violation, final @Nullable Void dummy) {
        super(violation, dummy);
    }

    /**
     * Create a new instance containing an {@link Exception}.
     *
     * @param cause Throwable
     * @param  Value type
     * @param  Exception type
     * @return A new instance
     * @throws NullPointerException if {@code cause} is null
     */
    public static  CheckedValue ofException(final E cause) {
        return new CheckedValue<>(cause, null);
    }

    /**
     * Create a new instance containing specified value.
     *
     * @param value Value
     * @param  Value type
     * @param  Exception type
     * @return A new instance
     * @throws NullPointerException if {@code value} is null
     */
    public static  CheckedValue ofValue(final T value) {
        return new CheckedValue<>(value);
    }

    /**
     * Convert a Variant into a {@link CheckedValue}, converting the second value into an exception.
     *
     * @param variant Input variant
     * @param mapper Mapping function from second alternative to an exception
     * @param  First alternative type
     * @param  Second alternative type
     * @param  Exception type
     * @return Resulting {@link CheckedValue}
     */
    public static  CheckedValue ofVariant(final Either variant,
            final Function mapper) {
        requireNonNull(mapper);
        return variant.isFirst() ? new CheckedValue<>(variant.first())
                : new CheckedValue<>(mapper.apply(variant.second()), null);
    }

    /**
     * Return the contained value if {@link #isPresent()} would return true, throws {@link IllegalStateException}
     * otherwise.
     *
     * @return Contained value
     * @throws IllegalStateException if an error string is present.
     */
    public final T get() {
        if (isFirst()) {
            return first();
        }
        throw new IllegalStateException("Value is not present", second());
    }

    /**
     * Return the contained error string if {@link #isPresent()} would return false, throws
     * {@link IllegalStateException} otherwise.
     *
     * @return Throwable which was used to instantiate this object, or absent if it was instantiated using an error
     *         string.
     * @throws IllegalStateException if a value is present.
     */
    public final E getException() {
        if (isSecond()) {
            return second();
        }
        throw new IllegalStateException("Value " + first() + " is present");
    }

    /**
     * Return true if a value is present.
     *
     * @return True if a value is present.
     */
    public final boolean isPresent() {
        return isFirst();
    }

    /**
     * If a value is present, invoke the specified consumer with the value, otherwise do nothing.
     *
     * @param consumer block to be executed if a value is present
     * @throws NullPointerException if value is present and {@code consumer} is null
     */
    public final void ifPresent(final Consumer consumer) {
        if (isFirst()) {
            consumer.accept(first());
        }
    }

    @SuppressWarnings("unchecked")
    public  CheckedValue map(final Function mapper) {
        requireNonNull(mapper);
        return isFirst() ? new CheckedValue<>(mapper.apply(first())) : (CheckedValue) this;
    }

    @SuppressWarnings("unchecked")
    public  CheckedValue mapException(final Function mapper) {
        requireNonNull(mapper);
        return isFirst() ? (CheckedValue) this : new CheckedValue<>(mapper.apply(second()), null);
    }

    @SuppressWarnings("unchecked")
    public  CheckedValue flatMap(final Function> mapper) {
        requireNonNull(mapper);
        return isFirst() ? requireNonNull(mapper.apply(first())) : (CheckedValue) this;
    }

    /**
     * Return contained value if present, otherwise return supplied value.
     *
     * @param other Replacement value
     * @return Contained value or {code other}
     */
    public final T orElse(final T other) {
        return isFirst() ? first() : other;
    }

    /**
     * Return contained value if present, otherwise return the value produced by a supplier.
     *
     * @param supplier Replacement value supplier
     * @return Contained value or supplier's value
     * @throws NullPointerException if {@code supplier} is null
     */
    public final T orElseGet(final Supplier supplier) {
        requireNonNull(supplier);
        return isFirst() ? first() : supplier.get();
    }

    /**
     * Return contained value if present or throw the exception alternative.
     *
     * @return Contained value
     * @throws E When there is no contained value
     */
    public final T orElseThrow() throws E {
        if (isFirst()) {
            return first();
        }
        throw second();
    }

    /**
     * Return contained value if present or throw the exception alternative mapped through provided mapper.
     *
     * @param exceptionMapper Exception mapper
     * @param  Thrown exception type
     * @return Contained value
     * @throws NullPointerException if {@code exceptionMapper} is null
     * @throws X When there is no contained value
     */
    public final  T orElseThrow(final Function exceptionMapper) throws X {
        requireNonNull(exceptionMapper);
        if (isFirst()) {
            return first();
        }
        throw exceptionMapper.apply(second());
    }

    /**
     * Complete target {@link CompletableFuture} either successfully or exceptionally based on the state of this object.
     *
     * @param future Future to complete
     * @return True if this call has transitioned the future to a completed state, false otherwise.
     * @throws NullPointerException if {code future} is null
     */
    public final boolean completeFuture(final CompletableFuture future) {
        return isFirst() ? future.complete(first()) : future.completeExceptionally(second());
    }

    /**
     * Complete target {@link SettableFuture} either successfully or exceptionally based on the state of this object.
     *
     * @param future Future to complete
     * @return True if this call has transitioned the future to a completed state, false otherwise.
     * @throws NullPointerException if {code future} is null
     */
    public final boolean completeFuture(final SettableFuture future) {
        return isFirst() ? future.set(first()) : future.setException(second());
    }

    /**
     * Transform this object into an immediately-completed {@link CompletableFuture}. The future will be successful
     * if this object has a contained value or unsuccessful if this objects contains an exception.
     *
     * @return A {@link CompletableFuture}.
     */
    public final CompletableFuture toCompletableFuture() {
        return isFirst() ? CompletableFuture.completedFuture(first()) : CompletableFuture.failedFuture(second());
    }

    /**
     * Transform this object into an immediately-completed {@link FluentFuture}. The future will be successful
     * if this object has a contained value or unsuccessful if this objects contains an exception.
     *
     * @return A {@link FluentFuture}.
     */
    public final FluentFuture toFluentFuture() {
        return FluentFuture.from(isFirst() ? Futures.immediateFuture(first())
                : Futures.immediateFailedFuture(second()));
    }
}