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

io.github.cwdesautels.monad.Try Maven / Gradle / Ivy

package io.github.cwdesautels.monad;

import io.github.cwdesautels.function.CheckedFunction;
import io.github.cwdesautels.function.CheckedRunnable;
import io.github.cwdesautels.function.CheckedSupplier;

import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
 * Eager opinionated try monad.
 */
public interface Try {

    // Constructors

    static  Try of(CheckedSupplier supplier) {
        Objects.requireNonNull(supplier);

        try {
            return success(supplier.get());
        } catch (Exception e) {
            return failure(e);
        }
    }

    static Try ofRunnable(CheckedRunnable runnable) {
        Objects.requireNonNull(runnable);

        return of(() -> {
            runnable.run();

            return null;
        });
    }

    static  Try success(T value) {
        return ImmutableSuccess.builder()
                .get(value)
                .build();
    }

    static  Try failure(Throwable error) {
        return ImmutableFailure.builder()
                .cause(error)
                .build();
    }

    // Behaviour

    T get();

    Throwable getCause();

    boolean isSuccess();

    boolean isFailure();

    // Templates

    default  Try map(CheckedFunction function) {
        Objects.requireNonNull(function);

        if (isSuccess()) {
            return of(() -> function.apply(get()));
        } else {
            return failure(getCause());
        }
    }

    default  Try flatMap(CheckedFunction> function) {
        Objects.requireNonNull(function);

        if (isSuccess()) {
            return of(() -> function.apply(get()))
                    .map(Objects::requireNonNull)
                    .map(Try::get);
        } else {
            return failure(getCause());
        }
    }

    default T orElse(T other) {
        if (isFailure()) {
            return other;
        } else {
            return get();
        }
    }

    default T orElseGet(Supplier other) {
        Objects.requireNonNull(other);

        if (isFailure()) {
            return other.get();
        } else {
            return get();
        }
    }

    default  T orElseThrow(Function mapper) throws X {
        Objects.requireNonNull(mapper);

        if (isFailure()) {
            throw mapper.apply(getCause());
        } else {
            return get();
        }
    }

    default Try ifSuccess(Consumer consumer) {
        Objects.requireNonNull(consumer);

        if (isSuccess()) {
            consumer.accept(get());
        }

        return this;
    }

    default Try ifFailure(Consumer consumer) {
        Objects.requireNonNull(consumer);

        if (isFailure()) {
            consumer.accept(getCause());
        }

        return this;
    }

    default Try recover(CheckedFunction function) {
        return recoverWhen(t -> true, function);
    }

    default Try recoverWhen(Predicate predicate, CheckedFunction function) {
        Objects.requireNonNull(predicate);
        Objects.requireNonNull(function);

        if (isSuccess() || !predicate.test(getCause())) {
            return this;
        } else {
            return of(() -> function.apply(getCause()));
        }
    }

    default Try exchange(CheckedFunction> function) {
        return exchangeWhen(t -> true, function);
    }

    default Try exchangeWhen(Predicate predicate, CheckedFunction> function) {
        Objects.requireNonNull(predicate);
        Objects.requireNonNull(function);

        if (isSuccess() || !predicate.test(getCause())) {
            return this;
        } else {
            return of(() -> function.apply(getCause()))
                    .map(Objects::requireNonNull)
                    .map(Try::get);
        }
    }

    default Either toEither() {
        if (isSuccess()) {
            return Either.right(get());
        } else {
            return Either.left(getCause());
        }
    }

    default Optional toOptional() {
        if (isSuccess()) {
            return Optional.ofNullable(get());
        } else {
            return Optional.empty();
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy