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

com.bluecatcode.common.base.Either Maven / Gradle / Ivy

package com.bluecatcode.common.base;

import com.google.common.base.Function;

import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
import java.io.Serializable;

import static com.bluecatcode.common.contract.Preconditions.require;

/**
 * Represents a value of one of two possible types (a disjoint union).
 * Instances of {@code Either} are either an instance of {@code Left} or {@code Right}.
 * 

* Either is an algebraic data type similar to the {@link com.google.common.base.Optional}. *

* A common use of {@code Either} is as an alternative to {@code Optional} for dealing with possible missing values. * In this usage, {@code Absent} is replaced with a {@code Left} which can contain useful information. * {@code Right} takes the place of {@code Present}. * Convention dictates that {@code Left} is used for failure and {@code Right} is used for success. *

* A non-null {@code Either} reference can be used as an alternative to the classic error handling (exceptions). *

*

 *  public static Either divide(int x, int y) {
 *    try {
 *      return Either.valueOf(x / y);
 *    } catch (Exception e) {
 *      return Either.errorOf(e);
 *    }
 *  }
 * 
* * @param the type of left instance that can be contained. * @param the type of right instance that can be contained. * @since 1.0.5 */ @CheckReturnValue public abstract class Either implements Serializable { private static final long serialVersionUID = 0; Either() { /* Empty */ } /** * Same as {@link #rightOf}, a convenience method for Value/Error use case. */ public static Either valueOf(R reference) { return rightOf(reference); } /** * Same as {@link #leftOf}, a convenience method for Value/Error use case. */ public static Either errorOf(L reference) { return leftOf(reference); } /** * Returns an {@code Either} instance containing the given non-null reference. * * @throws NullPointerException if {@code reference} is null */ public static Either leftOf(L reference) { require(reference != null, "Expected non-null reference"); return new Left<>(reference); } /** * Returns an {@code Either} instance containing the given non-null reference. * * @throws NullPointerException if {@code reference} is null */ public static Either rightOf(R reference) { require(reference != null, "Expected non-null reference"); return new Right<>(reference); } /** * Same as {@link #isRight()}, a convenience method for Value/Error use case. */ public boolean isValue() { return isRight(); } /** * Same as {@link #isLeft}, a convenience method for Value/Error use case. */ public boolean isError() { return isLeft(); } /** * @return true if this is a Left, false otherwise. */ public abstract boolean isLeft(); /** * @return true if this is a Right, false otherwise. */ public abstract boolean isRight(); /** * Same as {@link #right()}, a convenience method for Value/Error use case. */ public R value() { return right(); } /** * Same as {@link #left()}, a convenience method for Value/Error use case. */ public L error() { return left(); } /** * Returns the contained instance, which must be present. * * @throws IllegalStateException if the instance is absent ({@link #isLeft()} returns * {@code false}); depending on this specific exception type (over the more general * {@link RuntimeException}) is discouraged */ public abstract L left(); /** * Returns the contained instance, which must be present. * * @throws IllegalStateException if the instance is absent ({@link #isRight()} returns * {@code false}); depending on this specific exception type (over the more general * {@link RuntimeException}) is discouraged */ public abstract R right(); /** * Returns this {@code Either} if it has the right value present; {@code secondChoice} otherwise. */ public abstract Either or(Either secondChoice); /** * Returns the left instance if it is present; {@code throw leftFunction.apply(left())} otherwise. * * @throws NullPointerException if right value is absent and the function returns {@code null} */ public abstract R orThrow(Function leftFunction) throws E; /** * Applies {@code leftFunction} if this is a Left or {@code rightFunction if this is a Right. * * @return the result of the {@code function}. * @throws NullPointerException if the function returns {@code null} */ public abstract V either(Function leftFunction, Function rightFunction); /** * Applies {@code leftFunction} if this is a Left or {@code rightFunction if this is a Right. * * @return the result of the {@code function}. * @throws NullPointerException if the function returns {@code null} */ public abstract Either transform(Function leftFunction, Function rightFunction); /** * If this is a Left, then return the left value in Right or vice versa. * * @return a new {@code Either} */ public abstract Either swap(); /** * Returns {@code true} if {@code object} is an {@code Either} instance, and either * the contained references are {@linkplain Object#equals equal} to each other. * Note that {@code Either} instances of differing parameterized types can * be equal. */ @Override public abstract boolean equals(@Nullable Object object); /** * Returns a hash code for this instance. */ @Override public abstract int hashCode(); /** * Returns a string representation for this instance. */ @Override public abstract String toString(); }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy