171 lines
6.2 KiB
Java
171 lines
6.2 KiB
Java
package tc.oc.commons.core.util;
|
|
|
|
import java.lang.reflect.Method;
|
|
import java.lang.reflect.Type;
|
|
import java.util.Collection;
|
|
import java.util.Collections;
|
|
import java.util.Iterator;
|
|
import java.util.Optional;
|
|
import java.util.Set;
|
|
import java.util.function.BiFunction;
|
|
import java.util.function.Function;
|
|
import java.util.function.Predicate;
|
|
import java.util.function.Supplier;
|
|
import java.util.stream.Collectors;
|
|
import java.util.stream.Stream;
|
|
import javax.annotation.Nullable;
|
|
|
|
import com.google.common.reflect.TypeParameter;
|
|
import com.google.common.reflect.TypeToken;
|
|
import com.google.inject.TypeLiteral;
|
|
import tc.oc.commons.core.reflect.Methods;
|
|
import tc.oc.commons.core.reflect.Types;
|
|
|
|
public final class Optionals {
|
|
private Optionals() {}
|
|
|
|
public static boolean equals(Optional<?> a, Optional<?> b) {
|
|
return a.isPresent() && b.isPresent() && a.get().equals(b.get());
|
|
}
|
|
|
|
public static boolean equals(Optional<?> a, Object b) {
|
|
return a.isPresent() && a.get().equals(b);
|
|
}
|
|
|
|
public static boolean equals(Object a, Optional<?> b) {
|
|
return equals(b, a);
|
|
}
|
|
|
|
public static boolean isInstance(Optional<?> value, Class<?> type) {
|
|
return value.isPresent() && type.isInstance(value.get());
|
|
}
|
|
|
|
public static <T> Optional<T> cast(Optional<? super T> value, Class<T> type) {
|
|
return isInstance(value, type) ? (Optional<T>) value : Optional.empty();
|
|
}
|
|
|
|
public static <T> Optional<T> cast(@Nullable Object obj, Class<T> type) {
|
|
return type.isInstance(obj) ? Optional.ofNullable((T) obj)
|
|
: Optional.empty();
|
|
}
|
|
|
|
public static <T> Optional<T> getIf(boolean condition, Supplier<T> supplier) {
|
|
return condition ? Optional.of(supplier.get())
|
|
: Optional.empty();
|
|
}
|
|
|
|
public static <T, E extends Throwable> Optional<T> ofThrows(Class<E> exception, ThrowingSupplier<T, E> supplier) {
|
|
try {
|
|
return Optional.of(supplier.getThrows());
|
|
} catch(Throwable e) {
|
|
if(exception.isInstance(e)) {
|
|
return Optional.empty();
|
|
}
|
|
throw (RuntimeException) e;
|
|
}
|
|
}
|
|
|
|
public static <T> Optional<T> filter(T value, Predicate<? super T> filter) {
|
|
return Optional.of(value).filter(filter);
|
|
}
|
|
|
|
public static boolean contains(Optional<?> container, Object value) {
|
|
return container.isPresent() && container.get().equals(value);
|
|
}
|
|
|
|
public static <T> Set<T> toSet(Optional<T> t) {
|
|
return t.isPresent() ? Collections.singleton(t.get())
|
|
: Collections.emptySet();
|
|
}
|
|
|
|
public static <T> Stream<T> stream(Optional<T> t) {
|
|
return t.map(Stream::of).orElse(Stream.empty());
|
|
}
|
|
|
|
public static <T> Set<T> union(Stream<Optional<? extends T>> optionals) {
|
|
return optionals.filter(Optional::isPresent)
|
|
.map(Optional::get)
|
|
.collect(Collectors.toSet());
|
|
}
|
|
|
|
public static <T> Set<T> union(Collection<Optional<? extends T>> optionals) {
|
|
return union(optionals.stream());
|
|
}
|
|
|
|
public static <T> Set<T> union(Optional<? extends T>... optionals) {
|
|
return union(Stream.of(optionals));
|
|
}
|
|
|
|
public static <T> Optional<T> first(Iterable<T> iterable) {
|
|
final Iterator<T> iterator = iterable.iterator();
|
|
return iterator.hasNext() ? Optional.of(iterator.next()) : Optional.empty();
|
|
}
|
|
|
|
public static <T> Optional<T> first(Stream<Optional<? extends T>> options) {
|
|
return (Optional<T>) options.filter(Optional::isPresent)
|
|
.findFirst()
|
|
.orElse(Optional.empty());
|
|
}
|
|
|
|
public static <T> Optional<T> first(Collection<Optional<? extends T>> options) {
|
|
return first(options.stream());
|
|
}
|
|
|
|
public static <T> Optional<T> first(Optional<? extends T>... options) {
|
|
return first(Stream.of(options));
|
|
}
|
|
|
|
public static <T> TypeToken<Optional<T>> optionalType(TypeToken<T> type) {
|
|
return new TypeToken<Optional<T>>(){}.where(new TypeParameter<T>(){}, type);
|
|
}
|
|
|
|
public static <T> TypeLiteral<Optional<T>> optionalType(TypeLiteral<T> type) {
|
|
return Types.toLiteral(optionalType(Types.toToken(type)));
|
|
}
|
|
|
|
public static <T> TypeToken<Optional<? extends T>> optionalSubtypes(TypeToken<T> type) {
|
|
return new TypeToken<Optional<? extends T>>(){}.where(new TypeParameter<T>(){}, type);
|
|
}
|
|
|
|
public static <T> TypeLiteral<Optional<? extends T>> optionalSubtypes(TypeLiteral<T> type) {
|
|
return Types.toLiteral(optionalSubtypes(Types.toToken(type)));
|
|
}
|
|
|
|
private static final Method GET_METHOD = Methods.method(Optional.class, "get");
|
|
|
|
public static <T> TypeToken<T> elementType(TypeToken<Optional<T>> optionalType) {
|
|
return (TypeToken<T>) optionalType.method(GET_METHOD).getReturnType();
|
|
}
|
|
|
|
public static <T> TypeLiteral<T> elementType(TypeLiteral<Optional<T>> optionalType) {
|
|
return (TypeLiteral<T>) optionalType.getReturnType(GET_METHOD);
|
|
}
|
|
|
|
public static <T> TypeToken<T> elementType(Type optionalType) {
|
|
return elementType((TypeToken<Optional<T>>) TypeToken.of(optionalType));
|
|
}
|
|
|
|
/**
|
|
* If the given {@link Optional} is present, return the result of combining its value
|
|
* with the identity value, using the given combiner function. Otherwise, return the
|
|
* identity value directly.
|
|
*/
|
|
public static <T, R> R reduce(R identity, Optional<T> optional, BiFunction<? super R, ? super T, ? extends R> combiner) {
|
|
return optional.<R>map(value -> combiner.apply(identity, value))
|
|
.orElse(identity);
|
|
}
|
|
|
|
public static <T, U> Optional<Pair<T, U>> both(Optional<T> t, Optional<U> u) {
|
|
return mapBoth(t, u, Pair::of);
|
|
}
|
|
|
|
public static <T, U, R> Optional<R> mapBoth(Optional<T> t, Optional<U> u, BiFunction<T, U, R> mapper) {
|
|
return flatMapBoth(t, u, mapper.andThen(Optional::of));
|
|
}
|
|
|
|
public static <T, U, R> Optional<R> flatMapBoth(Optional<T> t, Optional<U> u, BiFunction<T, U, Optional<R>> mapper) {
|
|
return t.isPresent() && u.isPresent() ? mapper.apply(t.get(), u.get())
|
|
: Optional.empty();
|
|
}
|
|
}
|