java-commons/commons/src/main/java/io/gitlab/jfronny/commons/switchsupport/Opt.java

139 lines
3.8 KiB
Java

package io.gitlab.jfronny.commons.switchsupport;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Stream;
public sealed interface Opt<T> {
record Some<T>(T value) implements Opt<T> {
public static <T> Some<T> of(T value) {
return new Some<>(value);
}
}
record None<T>() implements Opt<T> {
public static <T> None<T> of() {
return new None<>();
}
}
static <T> Opt<T> empty() {
return None.of();
}
static <T> Opt<T> of(T value) {
return value == null ? None.of() : Some.of(value);
}
/**
* Converts an Optional to an Opt.
* Useful as a static import for switching over Optionals.
*
* @param optional Optional to convert to Opt
* @param <T> Type of the Optional
* @return Opt of the Optional
*/
static <T> Opt<T> over(Optional<T> optional) {
return optional.map(Opt::of).orElseGet(Opt::empty);
}
default T get() {
return switch (this) {
case Some(var value) -> value;
case None none -> throw new IllegalStateException("Opt is None");
};
}
default T getOrElse(T defaultValue) {
return switch (this) {
case Some(var value) -> value;
case None none -> defaultValue;
};
}
default T getOrElseGet(Supplier<T> supplier) {
return switch (this) {
case Some(var value) -> value;
case None none -> supplier.get();
};
}
default <X extends Throwable> T getOrElseThrow(Supplier<X> exceptionSupplier) throws X {
return switch (this) {
case Some(var value) -> value;
case None none -> throw exceptionSupplier.get();
};
}
default <R> Opt<R> map(Function<T, R> mapper) {
return switch (this) {
case Some(var value) -> Some.of(mapper.apply(value));
case None none -> None.of();
};
}
default <R> Opt<R> flatMap(Function<T, Opt<R>> mapper) {
return switch (this) {
case Some(var value) -> mapper.apply(value);
case None none -> None.of();
};
}
default void ifPresent(Consumer<T> consumer) {
if (this instanceof Some(var value)) consumer.accept(value);
}
default void ifPresentOrElse(Consumer<T> consumer, Runnable runnable) {
switch (this) {
case Some(var value) -> consumer.accept(value);
case None none -> runnable.run();
}
}
default Opt<T> filter(Predicate<T> predicate) {
return switch (this) {
case Some(var value) when predicate.test(value) -> this;
case Some some -> None.of();
case None none -> this;
};
}
default Opt<T> or(Supplier<Opt<T>> supplier) {
return switch (this) {
case Some some -> this;
case None none -> supplier.get();
};
}
default Opt<T> orElse(Opt<T> other) {
return switch (this) {
case Some some -> this;
case None none -> other;
};
}
default T orElseGet(Supplier<T> supplier) {
return switch (this) {
case Some(var value) -> value;
case None none -> supplier.get();
};
}
default <X> Result<T, X> toResult(Supplier<X> errorSupplier) {
return switch (this) {
case Some(var value) -> Result.success(value);
case None none -> Result.failure(errorSupplier.get());
};
}
default Stream<T> stream() {
return switch (this) {
case Some(var value) -> Stream.of(value);
case None none -> Stream.empty();
};
}
}