/* __ __ __ __ __ ___
* \ \ / / \ \ / / __/
* \ \/ / /\ \ \/ / /
* \____/__/ \__\____/__/.ɪᴏ
* ᶜᵒᵖʸʳᶦᵍʰᵗ ᵇʸ ᵛᵃᵛʳ ⁻ ˡᶦᶜᵉⁿˢᵉᵈ ᵘⁿᵈᵉʳ ᵗʰᵉ ᵃᵖᵃᶜʰᵉ ˡᶦᶜᵉⁿˢᵉ ᵛᵉʳˢᶦᵒⁿ ᵗʷᵒ ᵈᵒᵗ ᶻᵉʳᵒ
*/
package io.vavr.control;
import io.vavr.Value;
import io.vavr.collection.Iterator;
import java.io.Serializable;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
/**
* Either represents a value of two possible types. An Either is either a {@link Left} or a
* {@link Right}.
* <p>
* If the given Either is a Right and projected to a Left, the Left operations have no effect on the Right value.<br>
* If the given Either is a Left and projected to a Right, the Right operations have no effect on the Left value.<br>
* If a Left is projected to a Left or a Right is projected to a Right, the operations have an effect.
* <p>
* <strong>Example:</strong> A compute() function, which results either in an Integer value (in the case of success) or
* in an error message of type String (in the case of failure). By convention the success case is Right and the failure
* is Left.
*
* <pre>
* <code>
* Either<String,Integer> value = compute().right().map(i -> i * 2).toEither();
* </code>
* </pre>
*
* If the result of compute() is Right(1), the value is Right(2).<br>
* If the result of compute() is Left("error"), the value is Left("error").
*
* @param <L> The type of the Left value of an Either.
* @param <R> The type of the Right value of an Either.
* @author Daniel Dietrich
*/
public interface Either<L, R> extends Value<R>, Serializable {
long serialVersionUID = 1L;
/**
* Constructs a {@link Right}
*
* @param right The value.
* @param <L> Type of left value.
* @param <R> Type of right value.
* @return A new {@code Right} instance.
*/
static <L, R> Either<L, R> right(R right) {
return new Right<>(right);
}
/**
* Constructs a {@link Left}
*
* @param left The value.
* @param <L> Type of left value.
* @param <R> Type of right value.
* @return A new {@code Left} instance.
*/
static <L, R> Either<L, R> left(L left) {
return new Left<>(left);
}
/**
* Narrows a widened {@code Either<? extends L, ? extends R>} to {@code Either<L, R>}
* by performing a type-safe cast. This is eligible because immutable/read-only
* collections are covariant.
*
* @param either A {@code Either}.
* @param <L> Type of left value.
* @param <R> Type of right value.
* @return the given {@code either} instance as narrowed type {@code Either<L, R>}.
*/
@SuppressWarnings("unchecked")
static <L, R> Either<L, R> narrow(Either<? extends L, ? extends R> either) {
return (Either<L, R>) either;
}
/**
* Returns the left value.
*
* @return The left value.
* @throws NoSuchElementException if this is a {@code Right}.
*/
L getLeft();
/**
* Returns whether this Either is a Left.
*
* @return true, if this is a Left, false otherwise
*/
boolean isLeft();
/**
* Returns whether this Either is a Right.
*
* @return true, if this is a Right, false otherwise
*/
boolean isRight();
/**
* Returns a LeftProjection of this Either.
*
* @return a new LeftProjection of this
*/
default LeftProjection<L, R> left() {
return new LeftProjection<>(this);
}
/**
* Returns a RightProjection of this Either.
*
* @return a new RightProjection of this
*/
default RightProjection<L, R> right() {
return new RightProjection<>(this);
}
/**
* Maps either the left or the right side of this disjunction.
*
* @param leftMapper maps the left value if this is a Left
* @param rightMapper maps the right value if this is a Right
* @param <X> The new left type of the resulting Either
* @param <Y> The new right type of the resulting Either
* @return A new Either instance
*/
default <X, Y> Either<X, Y> bimap(Function<? super L, ? extends X> leftMapper, Function<? super R, ? extends Y> rightMapper) {
Objects.requireNonNull(leftMapper, "leftMapper is null");
Objects.requireNonNull(rightMapper, "rightMapper is null");
if (isRight()) {
return new Right<>(rightMapper.apply(get()));
} else {
return new Left<>(leftMapper.apply(getLeft()));
}
}
/**
* Folds either the left or the right side of this disjunction.
*
* @param leftMapper maps the left value if this is a Left
* @param rightMapper maps the right value if this is a Right
* @param <U> type of the folded value
* @return A value of type U
*/
default <U> U fold(Function<? super L, ? extends U> leftMapper, Function<? super R, ? extends U> rightMapper) {
Objects.requireNonNull(leftMapper, "leftMapper is null");
Objects.requireNonNull(rightMapper, "rightMapper is null");
if (isRight()) {
return rightMapper.apply(get());
} else {
return leftMapper.apply(getLeft());
}
}
/**
* Gets the Right value or an alternate value, if the projected Either is a Left.
*
* @param other a function which converts a Left value to an alternative Right value
* @return the right value, if the underlying Either is a Right or else the alternative Right value provided by
* {@code other} by applying the Left value.
*/
default R getOrElseGet(Function<? super L, ? extends R> other) {
Objects.requireNonNull(other, "other is null");
if (isRight()) {
return get();
} else {
return other.apply(getLeft());
}
}
/**
* Runs an action in the case this is a projection on a Left value.
*
* @param action an action which consumes a Left value
*/
default void orElseRun(Consumer<? super L> action) {
Objects.requireNonNull(action, "action is null");
if (isLeft()) {
action.accept(getLeft());
}
}
/**
* Gets the Right value or throws, if the projected Either is a Left.
*
* @param <X> a throwable type
* @param exceptionFunction a function which creates an exception based on a Left value
* @return the right value, if the underlying Either is a Right or else throws the exception provided by
* {@code exceptionFunction} by applying the Left value.
* @throws X if the projected Either is a Left
*/
default <X extends Throwable> R getOrElseThrow(Function<? super L, X> exceptionFunction) throws X {
Objects.requireNonNull(exceptionFunction, "exceptionFunction is null");
if (isRight()) {
return get();
} else {
throw exceptionFunction.apply(getLeft());
}
}
/**
* Converts a {@code Left} to a {@code Right} vice versa by wrapping the value in a new type.
*
* @return a new {@code Either}
*/
default Either<R, L> swap() {
if (isRight()) {
return new Left<>(get());
} else {
return new Right<>(getLeft());
}
}
// -- Adjusted return types of Monad methods
/**
* FlatMaps this right-biased Either.
*
* @param mapper A mapper
* @param <U> Component type of the mapped right value
* @return this as {@code Either<L, U>} if this is a Left, otherwise the right mapping result
* @throws NullPointerException if {@code mapper} is null
*/
@SuppressWarnings("unchecked")
default <U> Either<L, U> flatMap(Function<? super R, ? extends Either<L, ? extends U>> mapper) {
Objects.requireNonNull(mapper, "mapper is null");
if (isRight()) {
return (Either<L, U>) mapper.apply(get());
} else {
return (Either<L, U>) this;
}
}
/**
* Maps the value of this Either if it is a Right, performs no operation if this is a Left.
*
* <pre><code>
* import static io.vavr.API.*;
*
* class Example {{
*
* // = Right("A")
* Right("a").map(String::toUpperCase);
*
* // = Left(1)
* Left(1).map(String::toUpperCase);
*
* }}
* </code></pre>
*
* @param mapper A mapper
* @param <U> Component type of the mapped right value
* @return a mapped {@code Monad}
* @throws NullPointerException if {@code mapper} is null
*/
@SuppressWarnings("unchecked")
@Override
default <U> Either<L, U> map(Function<? super R, ? extends U> mapper) {
Objects.requireNonNull(mapper, "mapper is null");
if (isRight()) {
return Either.right(mapper.apply(get()));
} else {
return (Either<L, U>) this;
}
}
/**
* Maps the value of this Either if it is a Left, performs no operation if this is a Right.
*
* <pre>{@code
* import static io.vavr.API.*;
*
* class Example {
*
* // = Left(2)
* Left(1).mapLeft(i -> i + 1);
*
* // = Right("a")
* Right("a").mapLeft(i -> i + 1);
*
* }
* }</pre>
*
* @param leftMapper A mapper
* @param <U> Component type of the mapped right value
* @return a mapped {@code Monad}
* @throws NullPointerException if {@code mapper} is null
*/
@SuppressWarnings("unchecked")
default <U> Either<U, R> mapLeft(Function<? super L, ? extends U> leftMapper) {
Objects.requireNonNull(leftMapper, "leftMapper is null");
if (isLeft()) {
return Either.left(leftMapper.apply(getLeft()));
} else {
return (Either<U, R>) this;
}
}
// -- Adjusted return types of Value methods
/**
* Filters this right-biased {@code Either} by testing a predicate.
* <p>
*
* @param predicate A predicate
* @return a new {@code Option} instance
* @throws NullPointerException if {@code predicate} is null
*/
default Option<Either<L, R>> filter(Predicate<? super R> predicate) {
Objects.requireNonNull(predicate, "predicate is null");
return isLeft() || predicate.test(get()) ? Option.some(this) : Option.none();
}
/**
* Gets the right value if this is a {@code Right} or throws if this is a {@code Left}.
*
* @return the right value
* @throws NoSuchElementException if this is a {@code Left}.
*/
@Override
R get();
@Override
default boolean isEmpty() {
return isLeft();
}
@SuppressWarnings("unchecked")
default Either<L, R> orElse(Either<? extends L, ? extends R> other) {
Objects.requireNonNull(other, "other is null");
return isRight() ? this : (Either<L, R>) other;
}
@SuppressWarnings("unchecked")
default Either<L, R> orElse(Supplier<? extends Either<? extends L, ? extends R>> supplier) {
Objects.requireNonNull(supplier, "supplier is null");
return isRight() ? this : (Either<L, R>) supplier.get();
}
/**
* A right-biased {@code Either}'s value is computed synchronously.
*
* @return false
*/
@Override
default boolean isAsync() {
return false;
}
/**
* A right-biased {@code Either}'s value is computed eagerly.
*
* @return false
*/
@Override
default boolean isLazy() {
return false;
}
/**
* A right-biased {@code Either} is single-valued.
*
* @return {@code true}
*/
@Override
default boolean isSingleValued() {
return true;
}
@Override
default Iterator<R> iterator() {
if (isRight()) {
return Iterator.of(get());
} else {
return Iterator.empty();
}
}
@Override
default Either<L, R> peek(Consumer<? super R> action) {
Objects.requireNonNull(action, "action is null");
if (isRight()) {
action.accept(get());
}
return this;
}
default Either<L, R> peekLeft(Consumer<? super L> action) {
Objects.requireNonNull(action, "action is null");
if (isLeft()) {
action.accept(getLeft());
}
return this;
}
// -- Object.*
@Override
boolean equals(Object o);
@Override
int hashCode();
@Override
String toString();
// -- Left/Right projections
/**
* A left projection of an Either.
*
* @param <L> The type of the Left value of an Either.
* @param <R> The type of the Right value of an Either.
*/
final class LeftProjection<L, R> implements Value<L> {
private final Either<L, R> either;
private LeftProjection(Either<L, R> either) {
this.either = either;
}
public <L2, R2> LeftProjection<L2, R2> bimap(Function<? super L, ? extends L2> leftMapper, Function<? super R, ? extends R2> rightMapper) {
return either.<L2, R2> bimap(leftMapper, rightMapper).left();
}
/**
* A {@code LeftProjection}'s value is computed synchronously.
*
* @return false
*/
@Override
public boolean isAsync() {
return false;
}
@Override
public boolean isEmpty() {
return either.isRight();
}
/**
* A {@code LeftProjection}'s value is computed eagerly.
*
* @return false
*/
@Override
public boolean isLazy() {
return false;
}
/**
* A {@code LeftProjection} is single-valued.
*
* @return {@code true}
*/
@Override
public boolean isSingleValued() {
return true;
}
/**
* Gets the {@code Left} value or throws.
*
* @return the left value, if the underlying {@code Either} is a {@code Left}
* @throws NoSuchElementException if the underlying {@code Either} of this {@code LeftProjection} is a {@code Right}
*/
@Override
public L get() {
if (either.isLeft()) {
return either.getLeft();
} else {
throw new NoSuchElementException("LeftProjection.get() on Right");
}
}
@SuppressWarnings("unchecked")
public LeftProjection<L, R> orElse(LeftProjection<? extends L, ? extends R> other) {
Objects.requireNonNull(other, "other is null");
return either.isLeft() ? this : (LeftProjection<L, R>) other;
}
@SuppressWarnings("unchecked")
public LeftProjection<L, R> orElse(Supplier<? extends LeftProjection<? extends L, ? extends R>> supplier) {
Objects.requireNonNull(supplier, "supplier is null");
return either.isLeft() ? this : (LeftProjection<L, R>) supplier.get();
}
/**
* Gets the Left value or an alternate value, if the projected Either is a Right.
*
* @param other an alternative value
* @return the left value, if the underlying Either is a Left or else {@code other}
* @throws NoSuchElementException if the underlying either of this LeftProjection is a Right
*/
@Override
public L getOrElse(L other) {
return either.isLeft() ? either.getLeft() : other;
}
/**
* Gets the Left value or an alternate value, if the projected Either is a Right.
*
* @param other a function which converts a Right value to an alternative Left value
* @return the left value, if the underlying Either is a Left or else the alternative Left value provided by
* {@code other} by applying the Right value.
*/
public L getOrElseGet(Function<? super R, ? extends L> other) {
Objects.requireNonNull(other, "other is null");
if (either.isLeft()) {
return either.getLeft();
} else {
return other.apply(either.get());
}
}
/**
* Runs an action in the case this is a projection on a Right value.
*
* @param action an action which consumes a Right value
*/
public void orElseRun(Consumer<? super R> action) {
Objects.requireNonNull(action, "action is null");
if (either.isRight()) {
action.accept(either.get());
}
}
/**
* Gets the Left value or throws, if the projected Either is a Right.
*
* @param <X> a throwable type
* @param exceptionFunction a function which creates an exception based on a Right value
* @return the left value, if the underlying Either is a Left or else throws the exception provided by
* {@code exceptionFunction} by applying the Right value.
* @throws X if the projected Either is a Right
*/
public <X extends Throwable> L getOrElseThrow(Function<? super R, X> exceptionFunction) throws X {
Objects.requireNonNull(exceptionFunction, "exceptionFunction is null");
if (either.isLeft()) {
return either.getLeft();
} else {
throw exceptionFunction.apply(either.get());
}
}
/**
* Returns the underlying either of this projection.
*
* @return the underlying either
*/
public Either<L, R> toEither() {
return either;
}
/**
* Returns {@code Some} value of type L if this is a left projection of a Left value and the predicate
* applies to the underlying value.
*
* @param predicate A predicate
* @return A new Option
*/
public Option<LeftProjection<L, R>> filter(Predicate<? super L> predicate) {
Objects.requireNonNull(predicate, "predicate is null");
return either.isRight() || predicate.test(either.getLeft()) ? Option.some(this) : Option.none();
}
/**
* FlatMaps this LeftProjection.
*
* @param mapper A mapper
* @param <U> Component type of the mapped left value
* @return this as {@code LeftProjection<L, U>} if a Right is underlying, otherwise a the mapping result of the left value.
* @throws NullPointerException if {@code mapper} is null
*/
@SuppressWarnings("unchecked")
public <U> LeftProjection<U, R> flatMap(Function<? super L, ? extends LeftProjection<? extends U, R>> mapper) {
Objects.requireNonNull(mapper, "mapper is null");
if (either.isLeft()) {
return (LeftProjection<U, R>) mapper.apply(either.getLeft());
} else {
return (LeftProjection<U, R>) this;
}
}
/**
* Maps the left value if the projected Either is a Left.
*
* @param mapper A mapper which takes a left value and returns a value of type U
* @param <U> The new type of a Left value
* @return A new LeftProjection
*/
@SuppressWarnings("unchecked")
@Override
public <U> LeftProjection<U, R> map(Function<? super L, ? extends U> mapper) {
Objects.requireNonNull(mapper, "mapper is null");
if (either.isLeft()) {
return either.mapLeft((Function<L, U>) mapper).left();
} else {
return (LeftProjection<U, R>) this;
}
}
/**
* Applies the given action to the value if the projected either is a Left. Otherwise nothing happens.
*
* @param action An action which takes a left value
* @return this LeftProjection
*/
@Override
public LeftProjection<L, R> peek(Consumer<? super L> action) {
Objects.requireNonNull(action, "action is null");
if (either.isLeft()) {
action.accept(either.getLeft());
}
return this;
}
/**
* Transforms this {@code LeftProjection}.
*
* @param f A transformation
* @param <U> Type of transformation result
* @return An instance of type {@code U}
* @throws NullPointerException if {@code f} is null
*/
public <U> U transform(Function<? super LeftProjection<L, R>, ? extends U> f) {
Objects.requireNonNull(f, "f is null");
return f.apply(this);
}
@Override
public Iterator<L> iterator() {
if (either.isLeft()) {
return Iterator.of(either.getLeft());
} else {
return Iterator.empty();
}
}
@Override
public boolean equals(Object obj) {
return (obj == this) || (obj instanceof LeftProjection && Objects.equals(either, ((LeftProjection<?, ?>) obj).either));
}
@Override
public int hashCode() {
return either.hashCode();
}
@Override
public String stringPrefix() {
return "LeftProjection";
}
@Override
public String toString() {
return stringPrefix() + "(" + either + ")";
}
}
/**
* A right projection of an Either.
*
* @param <L> The type of the Left value of an Either.
* @param <R> The type of the Right value of an Either.
*/
final class RightProjection<L, R> implements Value<R> {
private final Either<L, R> either;
private RightProjection(Either<L, R> either) {
this.either = either;
}
public <L2, R2> RightProjection<L2, R2> bimap(Function<? super L, ? extends L2> leftMapper, Function<? super R, ? extends R2> rightMapper) {
return either.<L2, R2> bimap(leftMapper, rightMapper).right();
}
/**
* A {@code RightProjection}'s value is computed synchronously.
*
* @return false
*/
@Override
public boolean isAsync() {
return false;
}
@Override
public boolean isEmpty() {
return either.isLeft();
}
/**
* A {@code RightProjection}'s value is computed eagerly.
*
* @return false
*/
@Override
public boolean isLazy() {
return false;
}
/**
* A {@code RightProjection} is single-valued.
*
* @return {@code true}
*/
@Override
public boolean isSingleValued() {
return true;
}
/**
* Gets the {@code Right} value or throws.
*
* @return the right value, if the underlying {@code Either} is a {@code Right}
* @throws NoSuchElementException if the underlying {@code Either} of this {@code RightProjection} is a {@code Left}
*/
@Override
public R get() {
if (either.isRight()) {
return either.get();
} else {
throw new NoSuchElementException("RightProjection.get() on Left");
}
}
@SuppressWarnings("unchecked")
public RightProjection<L, R> orElse(RightProjection<? extends L, ? extends R> other) {
Objects.requireNonNull(other, "other is null");
return either.isRight() ? this : (RightProjection<L, R>) other;
}
@SuppressWarnings("unchecked")
public RightProjection<L, R> orElse(Supplier<? extends RightProjection<? extends L, ? extends R>> supplier) {
Objects.requireNonNull(supplier, "supplier is null");
return either.isRight() ? this : (RightProjection<L, R>) supplier.get();
}
/**
* Gets the Right value or an alternate value, if the projected Either is a Left.
*
* @param other an alternative value
* @return the right value, if the underlying Either is a Right or else {@code other}
* @throws NoSuchElementException if the underlying either of this RightProjection is a Left
*/
@Override
public R getOrElse(R other) {
return either.getOrElse(other);
}
/**
* Gets the Right value or an alternate value, if the projected Either is a Left.
*
* @param other a function which converts a Left value to an alternative Right value
* @return the right value, if the underlying Either is a Right or else the alternative Right value provided by
* {@code other} by applying the Left value.
*/
public R getOrElseGet(Function<? super L, ? extends R> other) {
Objects.requireNonNull(other, "other is null");
return either.getOrElseGet(other);
}
/**
* Runs an action in the case this is a projection on a Left value.
*
* @param action an action which consumes a Left value
*/
public void orElseRun(Consumer<? super L> action) {
Objects.requireNonNull(action, "action is null");
either.orElseRun(action);
}
/**
* Gets the Right value or throws, if the projected Either is a Left.
*
* @param <X> a throwable type
* @param exceptionFunction a function which creates an exception based on a Left value
* @return the right value, if the underlying Either is a Right or else throws the exception provided by
* {@code exceptionFunction} by applying the Left value.
* @throws X if the projected Either is a Left
*/
public <X extends Throwable> R getOrElseThrow(Function<? super L, X> exceptionFunction) throws X {
Objects.requireNonNull(exceptionFunction, "exceptionFunction is null");
return either.getOrElseThrow(exceptionFunction);
}
/**
* Returns the underlying either of this projection.
*
* @return the underlying either
*/
public Either<L, R> toEither() {
return either;
}
/**
* Returns {@code Some} value of type R if this is a right projection of a Right value and the predicate
* applies to the underlying value.
*
* @param predicate A predicate
* @return A new Option
*/
public Option<RightProjection<L, R>> filter(Predicate<? super R> predicate) {
Objects.requireNonNull(predicate, "predicate is null");
return either.isLeft() || predicate.test(either.get()) ? Option.some(this) : Option.none();
}
/**
* FlatMaps this RightProjection.
*
* @param mapper A mapper
* @param <U> Component type of the mapped right value
* @return this as {@code RightProjection<L, U>} if a Left is underlying, otherwise a the mapping result of the right value.
* @throws NullPointerException if {@code mapper} is null
*/
@SuppressWarnings("unchecked")
public <U> RightProjection<L, U> flatMap(Function<? super R, ? extends RightProjection<L, ? extends U>> mapper) {
Objects.requireNonNull(mapper, "mapper is null");
if (either.isRight()) {
return (RightProjection<L, U>) mapper.apply(either.get());
} else {
return (RightProjection<L, U>) this;
}
}
/**
* Maps the right value if the projected Either is a Right.
*
* @param mapper A mapper which takes a right value and returns a value of type U
* @param <U> The new type of a Right value
* @return A new RightProjection
*/
@SuppressWarnings("unchecked")
@Override
public <U> RightProjection<L, U> map(Function<? super R, ? extends U> mapper) {
Objects.requireNonNull(mapper, "mapper is null");
if (either.isRight()) {
return either.map((Function<R, U>) mapper).right();
} else {
return (RightProjection<L, U>) this;
}
}
/**
* Applies the given action to the value if the projected either is a Right. Otherwise nothing happens.
*
* @param action An action which takes a right value
* @return this {@code Either} instance
*/
@Override
public RightProjection<L, R> peek(Consumer<? super R> action) {
Objects.requireNonNull(action, "action is null");
if (either.isRight()) {
action.accept(either.get());
}
return this;
}
/**
* Transforms this {@code RightProjection}.
*
* @param f A transformation
* @param <U> Type of transformation result
* @return An instance of type {@code U}
* @throws NullPointerException if {@code f} is null
*/
public <U> U transform(Function<? super RightProjection<L, R>, ? extends U> f) {
Objects.requireNonNull(f, "f is null");
return f.apply(this);
}
@Override
public Iterator<R> iterator() {
return either.iterator();
}
@Override
public boolean equals(Object obj) {
return (obj == this) || (obj instanceof RightProjection && Objects.equals(either, ((RightProjection<?, ?>) obj).either));
}
@Override
public int hashCode() {
return either.hashCode();
}
@Override
public String stringPrefix() {
return "RightProjection";
}
@Override
public String toString() {
return stringPrefix() + "(" + either + ")";
}
}
/**
* The {@code Left} version of an {@code Either}.
*
* @param <L> left component type
* @param <R> right component type
* @author Daniel Dietrich
*/
final class Left<L, R> implements Either<L, R>, Serializable {
private static final long serialVersionUID = 1L;
private final L value;
/**
* Constructs a {@code Left}.
*
* @param value a left value
*/
private Left(L value) {
this.value = value;
}
@Override
public R get() {
throw new NoSuchElementException("get() on Left");
}
@Override
public L getLeft() {
return value;
}
@Override
public boolean isLeft() {
return true;
}
@Override
public boolean isRight() {
return false;
}
@Override
public boolean equals(Object obj) {
return (obj == this) || (obj instanceof Left && Objects.equals(value, ((Left<?, ?>) obj).value));
}
@Override
public int hashCode() {
return Objects.hashCode(value);
}
@Override
public String stringPrefix() {
return "Left";
}
@Override
public String toString() {
return stringPrefix() + "(" + value + ")";
}
}
/**
* The {@code Right} version of an {@code Either}.
*
* @param <L> left component type
* @param <R> right component type
* @author Daniel Dietrich
*/
final class Right<L, R> implements Either<L, R>, Serializable {
private static final long serialVersionUID = 1L;
private final R value;
/**
* Constructs a {@code Right}.
*
* @param value a right value
*/
private Right(R value) {
this.value = value;
}
@Override
public R get() {
return value;
}
@Override
public L getLeft() {
throw new NoSuchElementException("getLeft() on Right");
}
@Override
public boolean isLeft() {
return false;
}
@Override
public boolean isRight() {
return true;
}
@Override
public boolean equals(Object obj) {
return (obj == this) || (obj instanceof Right && Objects.equals(value, ((Right<?, ?>) obj).value));
}
@Override
public int hashCode() {
return Objects.hashCode(value);
}
@Override
public String stringPrefix() {
return "Right";
}
@Override
public String toString() {
return stringPrefix() + "(" + value + ")";
}
}
}