io.activej.common.collection.Either Maven / Gradle / Ivy
/*
* Copyright (C) 2020 ActiveJ LLC.
*
* Licensed 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 io.activej.common.collection;
import io.activej.common.recycle.Recyclers;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.function.*;
import static io.activej.common.Checks.checkState;
public final class Either {
static {
Recyclers.register(Either.class, either -> {
Recyclers.recycle(either.left);
Recyclers.recycle(either.right);
});
}
@Nullable
private final L left;
@Nullable
private final R right;
private final boolean isRight; // so that this either supports nulls
private Either(@Nullable L left, @Nullable R right, boolean isRight) {
this.left = left;
this.right = right;
this.isRight = isRight;
}
public static Either left(@Nullable L left) {
return new Either<>(left, null, false);
}
public static Either right(@Nullable R right) {
return new Either<>(null, right, true);
}
@Contract(pure = true)
public boolean isLeft() {
return !isRight;
}
@Contract(pure = true)
public boolean isRight() {
return isRight;
}
@Contract(pure = true)
public L getLeft() {
checkState(isLeft());
return left;
}
@Contract(pure = true)
public R getRight() {
checkState(isRight());
return right;
}
@Contract(pure = true)
@Nullable
public L getLeftOrNull() {
return left;
}
@Contract(pure = true)
@Nullable
public R getRightOrNull() {
return right;
}
@Contract(pure = true)
public L getLeftOr(@Nullable L defaultValue) {
return isLeft() ? left : defaultValue;
}
@Contract(pure = true)
public R getRightOr(@Nullable R defaultValue) {
return isRight() ? right : defaultValue;
}
@Contract(pure = true)
public L getLeftOrSupply(@NotNull Supplier extends L> defaultValueSupplier) {
return isLeft() ? left : defaultValueSupplier.get();
}
@Contract(pure = true)
public R getRightOrSupply(@NotNull Supplier extends R> defaultValueSupplier) {
return isRight() ? right : defaultValueSupplier.get();
}
@Contract(pure = true)
@NotNull
public Either ifLeft(@NotNull Consumer super L> leftConsumer) {
if (isLeft()) {
leftConsumer.accept(left);
}
return this;
}
@Contract(pure = true)
@NotNull
public Either ifRight(@NotNull Consumer super R> rightConsumer) {
if (isRight()) {
rightConsumer.accept(right);
}
return this;
}
@Contract(pure = true)
@NotNull
public Either consume(@NotNull BiConsumer super L, ? super R> consumer) {
consumer.accept(left, right);
return this;
}
@Contract(pure = true)
@NotNull
public Either consume(@NotNull Consumer super L> leftConsumer, @NotNull Consumer super R> rightConsumer) {
if (isLeft()) {
leftConsumer.accept(left);
} else {
rightConsumer.accept(right);
}
return this;
}
@Contract(pure = true)
public U reduce(@NotNull Function super L, ? extends U> leftFn, @NotNull Function super R, ? extends U> rightFn) {
return isLeft() ? leftFn.apply(left) : rightFn.apply(right);
}
@Contract(pure = true)
public U reduce(@NotNull BiFunction super L, ? super R, ? extends U> fn) {
return fn.apply(left, right);
}
@Contract(pure = true)
@NotNull
public Either swap() {
return new Either<>(right, left, !isRight);
}
@SuppressWarnings("unchecked")
@Contract(pure = true)
@NotNull
public Either mapLeft(@NotNull Function super L, ? extends T> fn) {
return isLeft() ?
new Either<>(fn.apply(left), null, false) :
(Either) this;
}
@SuppressWarnings("unchecked")
@Contract(pure = true)
@NotNull
public Either mapRight(@NotNull Function super R, ? extends T> fn) {
return isRight() ?
new Either<>(null, fn.apply(right), true) :
(Either) this;
}
@SuppressWarnings("unchecked")
@Contract(pure = true)
@NotNull
public Either flatMapLeft(@NotNull Function super L, Either> fn) {
return isLeft() ?
fn.apply(left) :
(Either) this;
}
@SuppressWarnings("unchecked")
@Contract(pure = true)
@NotNull
public Either flatMapRight(@NotNull Function super R, Either> fn) {
return isRight() ?
fn.apply(right) :
(Either) this;
}
}