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

org.apache.isis.commons.functional.Either Maven / Gradle / Ivy

/*
 *  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 org.apache.isis.commons.functional;

import java.io.Serializable;
import java.util.Optional;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;

import lombok.AccessLevel;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;

/**
 * The {@link Either} type represents a value of one of two possible types (a disjoint union),
 * referred to by {@code left} or {@code right}.
 * 

* Factory methods {@link Either#left(Object)} and {@link Either#right(Object)} * correspond to the two possible values. * * @since 2.0 {@index} */ public interface Either { // -- FACTORIES public static Either left(final @NonNull L left) { return new Left<>(left); } public static Either right(final @NonNull R right) { return new Right<>(right); } // -- ACCESSORS Optional left(); Optional right(); L leftIfAny(); R rightIfAny(); // -- PREDICATES boolean isLeft(); boolean isRight(); // -- MAPPING Either mapLeft(final @NonNull Function leftMapper); Either mapRight(final @NonNull Function rightMapper); Either map( final @NonNull Function leftMapper, final @NonNull Function rightMapper); // -- FOLDING T fold(@NonNull BiFunction biMapper); T fold( @NonNull Function leftMapper, @NonNull Function rightMapper); // -- TERMINALS void accept( @NonNull Consumer leftConsumer, @NonNull Consumer rightConsumer); // -- LEFT @lombok.Value @RequiredArgsConstructor(access=AccessLevel.PROTECTED) static final class Left implements Either, Serializable { private static final long serialVersionUID = 1L; private final L left; @Override public Optional left() { return Optional.ofNullable(left); } @Override public Optional right() { return Optional.empty(); } @Override public L leftIfAny() { return left; } @Override public R rightIfAny() { return null; } @Override public final boolean isLeft() { return true; } @Override public final boolean isRight() { return false; } @Override public final Either mapLeft(final @NonNull Function leftMapper){ return Either.left(leftMapper.apply(left)); } @Override public final Either mapRight(final @NonNull Function rightMapper){ return Either.left(left); } @Override public final Either map( final @NonNull Function leftMapper, final @NonNull Function rightMapper){ return Either.left(leftMapper.apply(left)); } @Override public final T fold(final @NonNull BiFunction biMapper){ return biMapper.apply(left, null); } @Override public final T fold( final @NonNull Function leftMapper, final @NonNull Function rightMapper){ return leftMapper.apply(left); } @Override public final void accept( final @NonNull Consumer leftConsumer, final @NonNull Consumer rightConsumer) { leftConsumer.accept(left); } } // -- RIGHT @lombok.Value @RequiredArgsConstructor(access=AccessLevel.PROTECTED) static final class Right implements Either, Serializable { private static final long serialVersionUID = 1L; private final R right; @Override public Optional left() { return Optional.empty(); } @Override public Optional right() { return Optional.ofNullable(right); } @Override public L leftIfAny() { return null; } @Override public R rightIfAny() { return right; } @Override public final boolean isLeft() { return false; } @Override public final boolean isRight() { return true; } @Override public final Either mapLeft(final @NonNull Function leftMapper){ return Either.right(right); } @Override public final Either mapRight(final @NonNull Function rightMapper){ return Either.right(rightMapper.apply(right)); } @Override public final Either map( final @NonNull Function leftMapper, final @NonNull Function rightMapper){ return Either.right(rightMapper.apply(right)); } @Override public final T fold(final @NonNull BiFunction biMapper){ return biMapper.apply(null, right); } @Override public final T fold( final @NonNull Function leftMapper, final @NonNull Function rightMapper){ return rightMapper.apply(right); } @Override public final void accept( final @NonNull Consumer leftConsumer, final @NonNull Consumer rightConsumer) { rightConsumer.accept(right); } } // -- TYPE COMPOSITION @FunctionalInterface public static interface HasEither extends Either { Either getEither(); @Override default Optional left() { return getEither().left(); } @Override default Optional right() { return getEither().right(); } @Override default L leftIfAny() { return getEither().leftIfAny(); } @Override default R rightIfAny() { return getEither().rightIfAny(); } @Override default boolean isLeft() { return getEither().isLeft(); } @Override default boolean isRight() { return getEither().isRight(); } @Override default Either mapLeft(final @NonNull Function leftMapper){ return getEither().mapLeft(leftMapper); } @Override default Either mapRight(final @NonNull Function rightMapper){ return getEither().mapRight(rightMapper); } @Override default Either map( final @NonNull Function leftMapper, final @NonNull Function rightMapper){ return getEither().map(leftMapper, rightMapper); } @Override default T fold(final @NonNull BiFunction biMapper){ return getEither().fold(biMapper); } @Override default T fold( final @NonNull Function leftMapper, final @NonNull Function rightMapper){ return getEither().fold(leftMapper, rightMapper); } @Override default void accept( final @NonNull Consumer leftConsumer, final @NonNull Consumer rightConsumer) { getEither().accept(leftConsumer, rightConsumer); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy