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

io.github.selcukes.collections.Try Maven / Gradle / Ivy

There is a newer version: 2.3.12
Show newest version
/*
 *  Copyright (c) Ramesh Babu Prudhvi.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package io.github.selcukes.collections;

import lombok.Getter;

import java.util.Optional;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.function.UnaryOperator;

/**
 * Represents the result of an operation that may fail with an exception. A
 * `Try` instance can either contain a result of type `T` or an exception.
 *
 * @param  The type of the result that can be contained in the `Try`
 *            instance.
 */
public class Try {
    private final T result;

    @Getter
    private final Exception exception;

    /**
     * Constructs a new `Try` instance with the given result and exception.
     *
     * @param result    The result of the operation, or `null` if an exception
     *                  was thrown.
     * @param exception The exception that was thrown, or `null` if the
     *                  operation succeeded.
     */
    private Try(T result, Exception exception) {
        this.result = result;
        this.exception = exception;
    }

    /**
     * Runs the given `runnable` without throwing any checked exceptions. If the
     * `runnable` throws an exception, a `Try` instance with the exception is
     * returned.
     *
     * @param  runnable The `CheckedRunnable` to run.
     * @return          A `Try` instance with the result set to `null` and the
     *                  exception set to the one thrown by the `runnable`.
     */
    public static Try of(CheckedRunnable runnable) {
        try {
            runnable.run();
            return new Try<>(null, null);
        } catch (Exception e) {
            return new Try<>(null, e);
        }
    }

    /**
     * Runs the given `supplier` without throwing any checked exceptions. If the
     * `supplier` throws an exception, a `Try` instance with the exception is
     * returned.
     *
     * @param  supplier The `CheckedSupplier` to run.
     * @param        The type of the result that can be contained in the
     *                  `Try` instance.
     * @return          A `Try` instance with the result set to `null` and the
     *                  exception set to the one thrown by the `supplier`.
     */
    public static  Try of(CheckedSupplier supplier) {
        try {
            return new Try<>(supplier.get(), null);
        } catch (Exception e) {
            return new Try<>(null, e);
        }
    }

    /**
     * Returns the result of the operation if it was successful, or throws the
     * exception wrapped in a runtime exception if the operation failed.
     *
     * @return                  the result of the operation if it was successful
     * @throws RuntimeException if the operation failed
     */
    public T orElseThrow() {
        if (isFailure()) {
            throw wrapAsRuntimeException(exception);
        }
        return result;
    }

    /**
     * Returns the result of the operation if it was successful, or throws a
     * runtime exception generated by the given error handler if the operation
     * failed.
     *
     * @param  errorHandler     a function that takes the exception thrown by
     *                          the operation and returns a runtime exception to
     *                          be thrown instead
     * @return                  the result of the operation if it was successful
     * @throws RuntimeException if the operation failed
     */
    public T orElseThrow(UnaryOperator errorHandler) {
        return or(
            ex -> {
                throw wrapAsRuntimeException(errorHandler.apply(ex));
            },
            Function.identity());
    }

    /**
     * Invokes the given `supplier` to create a resource of type `T` and applies
     * the `resourceMapper` to the resource. The resource is automatically
     * closed after the `resourceMapper` is applied.
     *
     * @param  supplier       The `CheckedSupplier` to create the resource.
     * @param  resourceMapper The `CheckedFunction` to apply to the resource.
     * @param              The type of the resource to create.
     * @param              The type of the result that can be contained in
     *                        the `Try` instance.
     * @return                A `Try` instance with the result set to the value
     *                        returned by the `resourceMapper` and the exception
     *                        set to the one caught.
     */
    public static  Try with(
            CheckedSupplier supplier, CheckedFunction resourceMapper
    ) {
        try (T resource = supplier.get()) {
            return new Try<>(resourceMapper.apply(resource), null);
        } catch (Exception e) {
            return new Try<>(null, e);
        }
    }

    /**
     * Returns `true` if the operation succeeded (i.e., no exception was
     * thrown).
     *
     * @return `true` if the operation succeeded, `false` otherwise.
     */
    public boolean isSuccess() {
        return exception == null;
    }

    /**
     * Returns `true` if the operation failed (i.e., an exception was thrown).
     *
     * @return `true` if the operation failed, `false` otherwise.
     */
    public boolean isFailure() {
        return exception != null;
    }

    /**
     * Returns the result held by this Try object wrapped in an Optional.
     *
     * @return an Optional containing the result held by this Try object, or an
     *         empty Optional if this Try object represents a failure
     */
    public Optional getResult() {
        return Optional.ofNullable(result);
    }

    /**
     * Applies the given function to the result of this Try, which produces a
     * new Try. If this Try contains an exception, a new Try containing the
     * exception is returned.
     *
     * @param  mapper the function to apply to the result of this Try
     * @param      the type of the result of the new Try
     * @return        a new Try containing the result of the given function or
     *                an exception
     */
    public  Try flatMap(Function> mapper) {
        if (isFailure()) {
            return new Try<>(null, exception);
        }
        try {
            return mapper.apply(result);
        } catch (Exception e) {
            return new Try<>(null, e);
        }
    }

    /**
     * Returns the result of this Try if it contains one, otherwise returns the
     * result of the given fallback supplier.
     *
     * @param  fallback the fallback supplier to call if this Try contains an
     *                  exception
     * @return          the result of this Try if it contains one, otherwise the
     *                  result of the fallback supplier
     */
    public T orElse(Supplier fallback) {
        return getResult().orElseGet(fallback);
    }

    /**
     * Returns the result of applying the successHandler function to the result
     * of this Try if it contains one, otherwise returns the result of applying
     * the errorHandler function to the exception contained in this Try.
     *
     * @param  errorHandler   the function to apply to the exception contained
     *                        in this Try
     * @param  successHandler the function to apply to the result of this Try if
     *                        it contains one
     * @param              the type of the result of the function applied to
     *                        the result of this Try or the exception contained
     *                        in this Try
     * @return                the result of applying the successHandler function
     *                        to the result of this Try if it contains one,
     *                        otherwise the result of applying the errorHandler
     *                        function to the exception contained in this Try
     */
    public  R or(Function errorHandler, Function successHandler) {
        return isFailure() ? errorHandler.apply(exception) : successHandler.apply(result);
    }

    /**
     * A functional interface representing a function that takes an argument of
     * type T and returns a result of type R, and may throw an Exception.
     *
     * @param  the type of the input to the function
     * @param  the type of the result of the function
     */
    @FunctionalInterface
    public interface CheckedFunction {
        @SuppressWarnings("squid:S112")
        R apply(T t) throws Exception;
    }

    /**
     * A functional interface representing a supplier of values of type T, which
     * may throw an Exception.
     *
     * @param  the type of results supplied by this supplier
     */
    @FunctionalInterface
    public interface CheckedSupplier {
        @SuppressWarnings("squid:S112")
        T get() throws Exception;
    }

    /**
     * A functional interface representing an operation that may throw an
     * Exception.
     */
    @FunctionalInterface
    public interface CheckedRunnable {
        @SuppressWarnings("squid:S112")
        void run() throws Exception;
    }

    /**
     * Wraps the given Throwable object as a RuntimeException if necessary. If
     * the Throwable object is an instance of RuntimeException or one of its
     * subtypes, it is returned as-is. If it is an instance of Error, it is
     * thrown immediately. Otherwise, a new RuntimeException object is created
     * with the Throwable object as its cause, and returned.
     *
     * @param  throwable the Throwable object to wrap as a RuntimeException
     * @return           a RuntimeException object representing the original
     *                   Throwable
     * @throws Error     if the Throwable object is an instance of Error
     */
    private static RuntimeException wrapAsRuntimeException(Throwable throwable) {
        if (throwable instanceof RuntimeException runtimeException) {
            return runtimeException;
        } else if (throwable instanceof Error error) {
            throw error;
        } else {
            return new RuntimeException(throwable);
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy