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

net.calledtoconstruct.Either Maven / Gradle / Ivy

package net.calledtoconstruct;

import java.util.function.BiFunction;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

public interface Either {

    /**
     * Given that the existing {@link Either} is of type {@link Left}, the {@code onLeftApply} transforms the contained value of type {@code TLeft}
     * using the supplied function, returning a new instance of {@link Left} as {@link Either} containing the transformed value of type {@code TOther}.
     * When the {@link Either} is of type {@link Right}, then {@code function} is not invoked, and the same instance is returned.
     * 
     * @param  Type of the value returned by {@code function}.
     * @param function A function that receives the value of type {@code TLeft} and returns a value of type {@code TOther}.
     * @return A new {@link Left} instance as {@link Either} containing the transformed value of type {@code TOther},
     * or the existing instance of type {@link Right} as {@link Either}.
     */
     Either onLeftApply(Function function);
    
    /**
     * Given that the existing {@link Either} is of type {@link Left}, the {@code onLeftAccept} provides the contained value of type {@code TLeft}
     * to the provided consumer.  The contained value of type {@code TLeft} is retained.  When the {@link Either} is of type {@link Right}
     * the {@code consumer} is not invoked, and the same instance is returned.
     * 
     * @param consumer A method that receives the value of type {@code TLeft}.
     * @return The existing {@link Left} or {@link Right} instance as {@link Either}.
     */
    Either onLeftAccept(Consumer consumer);

    /**
     * Given that the existing {@link Either} is of type {@link Left}, the {@code onLeftSupply} invokes {@code supplier} which returns
     * a value of type {@code TOther}.  A new {@link Left} instance is returned as type {@link Either} containing the supplied
     * value of type {@code TOther}.  When the {@link Either} is of type {@link Right}, the {@code supplier} is not invoked, and the same
     * instance is returned.
     * 
     * @param  Type of value supplied by the {@code supplier} function.
     * @param supplier A method that provides a new value of type {@code TLeft}.
     * @return A new {@link Left} as {@link Either} containing the supplied value, or the existing instance of {@link Right} as {@link Either}.
     */
     Either onLeftSupply(Supplier supplier);

    /**
     * Given that the existing {@link Either} is of type {@link Left}, {@code onLeftFlatMap} transforms the contained value of
     * type {@code TLeft} to {@code Optional} using the supplied {@code function}.  If the value returned is present,
     * a new instance of {@link Left} as {@link Either} is returned containing the transformed value.  If the value returned is
     * empty, then {@code otherwise} is invoked and the provided value is used instead.  When the {@link Either} is of type
     * {@link Right}, {@code function} is not invoked, and an instance of {@link Right} is returned retaining its value.
     * 
     * @param  The type of the transformed {@link Left} value.
     * @param function A function that accepts the {@code TLeft} value and returns an {@code Optional}.
     * @param otherwise A function that accepts the {@code TLeft} value and returns an {@code TLeftOut} when {@code function} returns empty.
     * @return An {@link Either} containing a {@link Left} or {@link Right} based on the above rules.
     */
     Either onLeftFlatMap(
        Function> function,
        Function otherwise
    );

    /**
     * Given that the existing {@link Either} is of type {@link Right}, the {@code onRightApply} transforms the contained value of
     * type {@code TRight} using the supplied {@code function}, returning a new instance of {@link Right} as {@link Either}
     * containing the transformed value of type {@code TOther}. When the {@link Either} is of type {@link Left}, the {@code function}
     * is not invoked, and the same instance is returned.
     * 
     * @param  Type of the value returned by {@code function}.
     * @param function A function that receives the value of type {@code TRight} and returns a transformed value of type {@code TOther}.
     * @return A new {@link Right} instance as {@link Either} containing the transformed value of type {@code TOther},
     * or the existing instance of type {@link Left} as {@link Either}.
     */
     Either onRightApply(Function function);

    /**
     * Given that the existing {@link Either} is of type {@link Right}, the {@code onRightAccept} provides the contained value of
     * type {@code TRight} to {@code consumer}.  The contained value is maintained.  When the {@link Either} is of type {@link Left}
     * the consumer is not invoked, and the same instance is returned.
     * 
     * @param consumer A method that receives the value of type {@code TRight}.
     * @return The existing {@link Left} or {@link Right} instance as {@link Either}.
     */
    Either onRightAccept(Consumer consumer);

    /**
     * Given that the existing {@link Either} is of type {@link Right}, the {@code onRightSupply} accepts a new value of type {@code TOther}
     * from the provided {@code supplier}.  A new {@link Right} is returned which contains the supplied
     * value.  When the {@link Either} is of type {@link Left}, the {@code supplier} is not invoked, and the same
     * instance is returned.
     * 
     * @param  Type of value supplied by {@code supplier}.
     * @param supplier A method that provides a new value of type {@code TOther}.
     * @return A new instance of {@link Right} containing the supplied value, or the existing instance of type {@link Left}.
     */
     Either onRightSupply(Supplier supplier);

    /**
     * Given that the existing {@link Either} is of type {@link Right}, {@code onRightFlatMap} transforms the contained value of
     * type {@code TRight} to {@code Optional} using the supplied {@code function}.  If the value returned is present,
     * a new instance of {@link Right} as {@link Either} is returned containing the transformed value.  If the value returned is
     * empty, then {@code otherwise} is invoked and the provided value is used instead.  When the {@link Either} is of type
     * {@link Left}, {@code function} is not invoked, and an instance of {@link Left} is returned retaining its value.
     * 
     * @param  The type of the transformed {@link Right} value.
     * @param function A function that accepts the {@code TRight} value and returns an {@code Optional}.
     * @param otherwise A function that accepts the {@code TRight} value and returns an {@code TRightOut} when {@code function} returns empty.
     * @return An {@link Either} containing a {@link Left} or {@link Right} based on the above rules.
     */
     Either onRightFlatMap(
        Function> function,
        Function otherwise
    );

    /**
     * Given the current {@link Either} and a provided "other" {@link Either}, attempt to merge the values they contain such that
     * the following rules are applied:
     *      {@link Left} + {@link Left} returns a new instance of type {@link Left} as {@link Either} with the two values of types
     * {@code TLeft} and {@code TOtherLeft} transformed by {@code functionMergeLeft}.
     *      {@link Right} + {@link Right} returns a new instance of type {@link Right} as {@link Either} with the two values of types
     * {@code TRight} and {@code TOtherRight} transformed by {@code functionMergeRight}
     * 
     * If it is not possible due to a mis-matched set of {@link Left} and {@link Right}, then this function will favor the {@link Left}
     * and return a new instance of type {@link Left} with the value of type {@code TLeft} transformed by {@code transformThis}
     * or of type {@code TOtherLeft} transformed by {@code transformOther}.  When this instance is of type {@link Left}, its values is
     * passed to {@code transformThis} and the result of type {@code TLeftOut} is returned.  When the "other" instance is of type
     * {@link Left}, its value is passed to {@code transformOther} and the result of type {@code TLeftOut} is returned.
     * 
     * @param  The type of value for the {@link Left} of the "other" {@link Either}.
     * @param  The type of value for the {@link Right} of the "other" {@link Either}.
     * @param  The type of value for the {@link Left} of the resulting {@link Either}.
     * @param  The type of value for the {@link Right} of the resulting {@link Either}.
     * @param other The "other" instance of {@link Either} being merged.
     * @param functionMergeLeft A function which takes values of type {@code TLeft} and {@code TOtherLeft} and produces a value of type
     * {@code TLeftOut} effectively merging the two left values.
     * @param functionMergeRight A function which takes values of type {@code TRight} and {@code TOtherRight} and produces a value of type
     * {@code TRightOut} effectively merging the two right values.
     * @param transformThis A function which takes a value of type {@code TLeft} and transforms the value to type {@code TLeftOut}.
     * @param transformOther A function which takes a value of type {@code TOtherLeft} and transforms the value to type {@code TLeftOut}.
     * @return An instance of type {@link Left} or {@link Right} as {@link Either} with value types of {@code TLeftOut} and {@code TRightOut} based on the above rules.
     */
     Either mergeFailToLeft(
        Either other,
        BiFunction functionMergeLeft,
        BiFunction functionMergeRight,
        Function transformThis,
        Function transformOther
    );

    /**
     * Given the current {@link Either} and a provided "other" {@link Either}, attempt to merge the values they contain such that
     * the following rules are applied:
     *      {@link Left} + {@link Left} returns a new instance of type {@link Left} as {@link Either} with the two values of types
     * {@code TLeft} and {@code TOtherLeft} transformed by {@code functionMergeLeft}.
     *      {@link Right} + {@link Right} returns a new instance of type {@link Right} as {@link Either} with the two values of types
     * {@code TRight} and {@code TOtherRight} transformed by {@code functionMergeRight}
     * 
     * If it is not possible due to a mis-matched set of {@link Left} and {@link Right}, then this function will favor the {@link Right}
     * and return a new instance of type {@link Right} with the value of type {@code TRight} transformed by {@code transformThis}
     * or of type {@code TOtherRight} transformed by {@code transformOther}.  When this instance is of type {@link Right}, its values is
     * passed to {@code transformThis} and the result of type {@code TRightOut} is returned.  When the "other" instance is of type
     * {@link Right}, its value is passed to {@code transformOther} and the result of type {@code TRightOut} is returned.
     * 
     * @param  The type of value for the {@link Left} of the "other" {@link Either}.
     * @param  The type of value for the {@link Right} of the "other" {@link Either}.
     * @param  The type of value for the {@link Left} of the resulting {@link Either}.
     * @param  The type of value for the {@link Right} of the resulting {@link Either}.
     * @param other The "other" instance of {@link Either} being merged.
     * @param functionMergeLeft A function which takes values of type {@code TLeft} and {@code TOtherLeft} and produces a value of type
     * {@code TLeftOut} effectively merging the two left values.
     * @param functionMergeRight A function which takes values of type {@code TRight} and {@code TOtherRight} and produces a value of type
     * {@code TRightOut} effectively merging the two right values.
     * @param transformOther A function which takes a value of {@code TOtherRight} and transforms the value to {@code TRightOut}.
     * @param transformThis A function which takes a value of {@code TRight} and transforms the value to {@code TRightOut}.
     * @return An instance of type {@link Left} or {@link Right} as {@link Either} with value types {@code TLeftOut} and {@code TRightOut} based on the above rules.
     */
     Either mergeFailToRight(
        Either other,
        BiFunction functionMergeLeft,
        BiFunction functionMergeRight,
        Function transformThis,
        Function transformOther
    );

    /**
     * Retains the value, whether {@code TLeft} or {@code TRight}, but inverts the
     * container.  So, {@link Left} {@code .flip()} will return an instance of {@link Right}, 
     * and {@link Right} {@code .flip()} will return an instance of {@link Left}.
     * 
     * @return When the current instance is {@link Left}, this returns an instance
     * of {@link Right} containing the value of type {@code TLeft}.  When the current instance
     * is {@link Right}, this returns and instance of {@link Left} containing the value of
     * type {@code TRight}.
     */
    Either flip();

    /**
     * When an {@link Either} uses the same type for both the {@code TLeft} and {@code TRight}, the coalesce function will
     * extract the value from either implementation and return it.
     * 
     * @param  The type used for the {@code TLeft} and {@code TRight} values.
     * @param either The {@link Either} containing the value to extract.
     * @return The value, regardless of whether the {@link Either} is a {@link Left} or a {@link Right}.
     */
    static  TOther coalesce(final Either either) {
        if (either instanceof Left left) {
            return left.getValue();
        } else if (either instanceof Right right) {
            return right.getValue();
        } else {
            throw new UnexpectedNeitherException();
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy