com.shapesecurity.shift.es2017.utils.Either3 Maven / Gradle / Ivy
package com.shapesecurity.shift.es2017.utils;
import com.shapesecurity.functional.F;
import com.shapesecurity.functional.data.Maybe;
import javax.annotation.CheckReturnValue;
import javax.annotation.Nonnull;
import java.util.Objects;
// TODO port this to shape-functional-java
@CheckReturnValue
public final class Either3 {
private final Object data;
private enum Tag {
LEFT, MIDDLE, RIGHT
}
private final Tag tag;
private Either3(Object data, Tag tag) {
super();
this.data = data;
this.tag = tag;
}
@Nonnull
public static Either3 left(@Nonnull A a) {
return new Either3<>(a, Tag.LEFT);
}
@Nonnull
public static Either3 middle(@Nonnull B b) {
return new Either3<>(b, Tag.MIDDLE);
}
@Nonnull
public static Either3 right(@Nonnull C c) {
return new Either3<>(c, Tag.RIGHT);
}
public final boolean isLeft() {
return this.tag == Tag.LEFT;
}
public final boolean isMiddle() {
return this.tag == Tag.MIDDLE;
}
public final boolean isRight() {
return this.tag == Tag.RIGHT;
}
@SuppressWarnings("unchecked")
public X either(F f1, F f2, F f3) {
if (this.tag == Tag.LEFT) {
return f1.apply((A) this.data);
} else if (this.tag == Tag.MIDDLE) {
return f2.apply((B) this.data);
} else {
return f3.apply((C) this.data);
}
}
@Nonnull
public Either3 map(F f1, F f2, F f3) {
return this.either(a -> Either3.left(f1.apply(a)), b -> Either3.middle(f2.apply(b)), c -> Either3.right(f3.apply(c)));
}
@Nonnull
public Either3 mapLeft(@Nonnull F f) {
return this.map(f, b -> b, c -> c);
}
@Nonnull
public Either3 mapMiddle(@Nonnull F f) {
return this.map(a -> a, f, c -> c);
}
@Nonnull
public Either3 mapRight(@Nonnull F f) {
return this.map(a -> a, b -> b, f);
}
@SuppressWarnings("unchecked")
@Nonnull
public Maybe left() {
return this.tag == Tag.LEFT ? Maybe.of((A) this.data) : Maybe.empty();
}
@SuppressWarnings("unchecked")
@Nonnull
public Maybe middle() {
return this.tag == Tag.MIDDLE ? Maybe.of((B) this.data) : Maybe.empty();
}
@SuppressWarnings("unchecked")
@Nonnull
public Maybe right() {
return this.tag == Tag.RIGHT ? Maybe.of((C) this.data) : Maybe.empty();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Either3, ?, ?> either3 = (Either3, ?, ?>) o;
return tag == either3.tag && Objects.equals(data, either3.data);
}
@Override
public int hashCode() {
return Objects.hash(data, tag);
}
}