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

io.snice.functional.Either Maven / Gradle / Ivy

package io.snice.functional;

import java.util.function.Function;

import static io.snice.preconditions.PreConditions.assertNotNull;

/**
 * Note:This class is essentially a condensed version of the one find in vavr.io.
 *
 * {@link Either} represents a value of two possible types, either it is a left or it is
 * a right. By convention, the right value is considered the success branch, and the left
 * an error. This {@link Either} is right-biased, meaning operations by default operate
 * on the right value if present.
 *
 * Vavr.io is an excellent library and you should check it out. The reason for not
 * pulling in that library into the various snice.io projects is that, in general, the
 * core of those libraries are to be kept small and as much as possible, only dependent
 * on the JVM. With that said, pretty sure I"ll regret it and soon enough having to swap
 * this {@link Either} out for the full functionality of vavr.io. Time will tell.
 *
 *
 */
public interface Either {


     U fold(Function leftMapper, Function rightMapper);

    static  Either right(final R value) {
        return new Right<>(value);
    }

    static  Left left(final L value) {
        return new Left<>(value);
    }

    default boolean isRight() {
        return false;
    }

    default boolean isLeft() {
        return false;
    }

    default R get() {
        throw new IllegalArgumentException("Unable to get a Right on a Left");
    }

    default L getLeft() {
        throw new IllegalArgumentException("Unable to get a Left on a Right");
    }

    class Right implements Either {


        private final R value;

        private Right(final R value) {
            this.value = value;
        }

        @Override
        public  U fold(final Function leftMapper, final Function rightMapper) {
            assertNotNull(rightMapper, "The right mapper cannot be null");
            return rightMapper.apply(value);
        }

        @Override
        public boolean isRight() {
            return true;
        }

        @Override
        public R get() {
            return value;
        }

        @Override
        public boolean equals(final Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;

            final Right right = (Right) o;

            return value.equals(right.value);
        }

        @Override
        public int hashCode() {
            return value.hashCode();
        }
    }

    class Left implements Either {

        private final L value;

        private Left(final L value) {
            this.value = value;
        }

        @Override
        public  U fold(final Function leftMapper, final Function rightMapper) {
            assertNotNull(leftMapper, "The left mapper cannot be null");
            return leftMapper.apply(value);
        }

        @Override
        public boolean isLeft() {
            return true;
        }

        @Override
        public L getLeft() {
            return value;
        }

        @Override
        public boolean equals(final Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;

            final Left left = (Left) o;

            return value.equals(left.value);
        }

        @Override
        public int hashCode() {
            return value.hashCode();
        }
    }
}