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

io.streamthoughts.azkarra.api.monad.Either Maven / Gradle / Ivy

There is a newer version: 0.9.2
Show newest version
/*
 * Copyright 2019-2020 StreamThoughts.
 *
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.streamthoughts.azkarra.api.monad;

import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;

/**
 * Simple {@link Either} monad type.
 *
 * @param    the {@link Left} type.
 * @param    the {@link Right} type.
 */
public abstract class Either {

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

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

    private final L left;
    private final R right;

    Either(final L left, final R right) {
        this.left = left;
        this.right = right;
    }

    /**
     * Returns {@code true} if this is a {@link Left}, {@code false} otherwise.
     */
    public abstract boolean isLeft();
    /**
     * Returns {@code true} if this is a {@link Right}, {@code false} otherwise.
     */
    public abstract boolean isRight();

    public LeftProjection left() {
        return new LeftProjection<>(this);
    }

    public RightProjection right() {
        return new RightProjection<>(this);
    }

    public  T fold(final Function fl, final Function fr) {
        return isLeft() ? fl.apply(left) : fr.apply(right);
    }

    public static class Left extends Either {

        private Left(L left) {
            super(left, null);
        }
        /**
         * @return {@code true}.
         */
        @Override
        public boolean isLeft() {
            return true;
        }
        /**
         * @return {@code false}.
         */
        @Override
        public boolean isRight() {
            return false;
        }
    }

    public static class Right extends Either {

        private Right(R right) {
            super(null, right);
        }

        /**
         * @return {@code false}.
         */
        @Override
        public boolean isLeft() {
            return false;
        }

        /**
         * @return {@code true}.
         */
        @Override
        public boolean isRight() {
            return true;
        }
    }

    public static class LeftProjection {

        private final Either either;

        LeftProjection(final Either either) {
            Objects.requireNonNull(either, "either can't be null");
            this.either = either;
        }

        public boolean exists() {
            return either.isLeft();
        }

        public L get() {
            if (either.isLeft()) return either.left;
            else throw new NoSuchElementException("This is Right");
        }

        public  Either map(final Function fn) {
            if (either.isLeft()) return Either.left(fn.apply(either.left));
            else return Either.right(either.right);
        }

        public  Either flatMap(final Function> fn) {
            if (either.isLeft()) return fn.apply(either.left);
            else return Either.right(either.right);
        }

        public Optional toOptional() {
            return exists() ? Optional.of(either.left) : Optional.empty();
        }
    }

    public static class RightProjection {

        private final Either either;

        RightProjection(final Either either) {
            Objects.requireNonNull(either, "either can't be null");
            this.either = either;
        }

        public boolean exists() {
            return either.isRight();
        }

        public R get() {
            if (either.isRight()) return either.right;
            else throw new NoSuchElementException("This is Left");
        }

        public  Either map(final Function fn) {
            if (either.isRight()) return Either.right(fn.apply(either.right));
            else return Either.left(either.left);
        }

        public  Either flatMap(final Function> fn) {
            if (either.isRight()) return fn.apply(either.right);
            else return Either.left(either.left);
        }

        public Optional toOptional() {
            return exists() ? Optional.of(either.right) : Optional.empty();
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy