Skip to content

Instantly share code, notes, and snippets.

@sergey-scherbina
Created April 23, 2019 19:02
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sergey-scherbina/ce7e426620d57450fc8d7593d2222a54 to your computer and use it in GitHub Desktop.
Save sergey-scherbina/ce7e426620d57450fc8d7593d2222a54 to your computer and use it in GitHub Desktop.
import io.vavr.Tuple;
import io.vavr.collection.Iterator;
import io.vavr.control.Option;
import io.vavr.control.Try;
import java.util.List;
import java.util.function.*;
public interface Mapper<S, T> extends BiFunction<T, S, Boolean> {
interface Setter<A, T> extends BiConsumer<T, A> {
}
default T map(final S s, final T t) {
if (s != null && t != null)
apply(t, s);
return t;
}
default <R extends T> Mapper<S, R> andThen(Mapper<S, R> mapper) {
return (t, s) -> apply(t, s) && mapper.apply(t, s);
}
default Mapper<S, T> orElse(Mapper<S, T> orElse) {
return (t, s) -> apply(t, s) ? true : orElse.apply(t, s);
}
@SafeVarargs
static <S, T> Mapper<S, T> mapping(final Mapper<S, T>... rules) {
return (t, s) -> {
for (final Mapper<S, T> rule : rules) {
rule.apply(t, s);
}
return true;
};
}
static <A, T> Mapper<A, T> setter(final Setter<A, T> set) {
return (t, a) -> {
if (t != null)
set.accept(t, a);
return true;
};
}
static <S, T, A> Mapper<S, T> constant(final A a,
final Setter<A, T> set) {
return (t, s) -> setter(set).apply(t, a);
}
static <S, T, A> Mapper<S, T> rule(final Function<S, A> get,
final Setter<A, T> set) {
return rule(get, setter(set));
}
static <S, T, A> Mapper<S, T> rule(final Function<S, A> get,
final Mapper<A, T> set) {
return rule(get, Function.identity(), set);
}
static <S, T, A, B> Mapper<S, T> rule(final Function<S, A> get,
final Function<A, B> map,
final Setter<B, T> set) {
return rule(get, map, setter(set));
}
static <S, T, A, B> Mapper<S, T> rule(final Function<S, A> get,
final Function<A, B> map,
final Mapper<B, T> set) {
return (t, s) -> Option.of(get.apply(s))
.flatMap(a -> Option.of(map.apply(a)))
.map(b -> set.apply(t, b))
.getOrElse(false);
}
static <S, T, A> Mapper<S, T> forFirst(final Function<S, List<A>> get,
final Setter<A, T> set) {
return forFirst(get, setter(set));
}
static <S, T, A> Mapper<S, T> forFirst(final Function<S, List<A>> get,
final Mapper<A, T> set) {
return rule(get, firstOf(Function.identity()), set);
}
static <A, B> Function<List<A>, B> firstOf(final Function<A, B> map) {
return firstOf(a -> true, map);
}
static <A, B> Function<List<A>, B> firstOf(final Predicate<A> filter,
final Function<A, B> map) {
return list -> Option.of(list).map(Iterator::ofAll)
.flatMap(al -> al.find(filter)).map(map).getOrNull();
}
static <A, B> Function<A, B> create(final Supplier<B> create,
final Setter<A, B> init) {
return create(create, setter(init));
}
@SafeVarargs
static <A, B> Function<A, B> create(final Supplier<B> create,
final Mapper<A, B>... init) {
return create(a -> create.get(), init);
}
static <A, B> Function<A, B> create(final Function<A, B> create,
final Setter<A, B> init) {
return create(create, setter(init));
}
@SafeVarargs
static <A, B> Function<A, B> create(final Function<A, B> create,
final Mapper<A, B>... init) {
return a -> Option.of(a).map(v -> {
final B b = create.apply(v);
mapping(init).apply(b, v);
return b;
}).getOrNull();
}
static <A, B> Function<List<A>, List<B>> forAll(final Function<A, B> map) {
return filter(a -> true, map);
}
static <A, B> Function<List<A>, List<B>> filter(final Predicate<A> filter,
final Function<A, B> map) {
return list -> Option.of(list).map(Iterator::ofAll)
.map(al -> al.filter(filter).flatMap(a -> Option.of(map.apply(a))))
.map(Iterator::toJavaList).getOrNull();
}
static <A, B> Function<List<A>, List<B>> flatMap(final Function<A, List<B>> flatMap) {
return list -> Option.of(list).map(Iterator::ofAll)
.map(al -> al.flatMap(a -> Option.of(flatMap.apply(a))
.map(Iterator::ofAll).iterator()
.flatMap(Function.identity())))
.map(Iterator::toJavaList).getOrNull();
}
static <S, T, A, B, C> Mapper<S, T> zip(
final Function<S, A> getA,
final Function<S, B> getB,
final BiFunction<A, B, C> zip,
final Setter<C, T> set) {
return zip(getA, getB, zip, setter(set));
}
static <S, T, A, B, C> Mapper<S, T> zip(
final Function<S, A> getA,
final Function<S, B> getB,
final BiFunction<A, B, C> zip,
final Mapper<C, T> set) {
return rule(s -> Tuple.of(getA.apply(s), getB.apply(s)),
ab -> zip.apply(ab._1(), ab._2()), set);
}
static <S, T, A, B, C, D> Mapper<S, T> zip(
final Function<S, A> getA,
final Function<S, B> getB,
final Function<S, C> getC,
final BiFunction<A, B, Function<C, D>> zip,
final Setter<D, T> set) {
return zip(getA, getB, getC, zip, setter(set));
}
static <S, T, A, B, C, D> Mapper<S, T> zip(
final Function<S, A> getA,
final Function<S, B> getB,
final Function<S, C> getC,
final BiFunction<A, B, Function<C, D>> zip,
final Mapper<D, T> set) {
return rule(s -> Tuple.of(getA.apply(s), getB.apply(s), getC.apply(s)),
ab -> zip.apply(ab._1(), ab._2()).apply(ab._3()), set);
}
@SafeVarargs
static <S, T> Mapper<S, T> choice(final Mapper<S, T>... mappers) {
return (t, s) -> Iterator.of(mappers).find(m -> m.apply(t, s)).isDefined();
}
@SafeVarargs
static <S, T, R extends T> Mapper<S, T> targetTypeRule(final Class<R> type,
final Mapper<S, R>... mappers) {
return (t, s) -> type.isAssignableFrom(t.getClass()) ?
mapping(mappers).apply(type.cast(t), s) : false;
}
@SafeVarargs
static <S, T, R extends S> Mapper<S, T> srcTypeRule(final Class<R> type,
final Mapper<R, T>... mappers) {
return (t, s) -> type.isAssignableFrom(s.getClass()) ?
mapping(mappers).apply(t, type.cast(s)) : false;
}
static <A, B> Function<A, B> func(final Function<A, B> f) {
return a -> Try.of(() -> f.apply(a)).getOrNull();
}
static <A, B> Function<A, B> func(final Function<A, B> f, final Consumer<Throwable> e) {
return a -> Try.of(() -> f.apply(a)).onFailure(e).getOrNull();
}
static <A, B> Predicate<A> predicate(final Function<A, B> f, final Predicate<B> p) {
return a -> Option.of(f.apply(a)).map(p::test).getOrElse(false);
}
static <A, B, C> Function<A, C> compose(final Function<A, B> ab, final Function<B, C> bc) {
return bc.compose(ab);
}
@SafeVarargs
static <A, B> Function<A, List<B>> concat(final Function<A, List<B>>... maps) {
return a -> Iterator.of(maps).flatMap(m -> Option.of(m.apply(a))
.iterator().flatMap(Iterator::ofAll)).toJavaList();
}
static <A extends Enum<A>, B extends Enum<B>> Function<A, B> enums(
final Class<B> bClass, final Consumer<IllegalArgumentException> error) {
return a -> {
if (a == null) return null;
else try {
return Enum.valueOf(bClass, a.name());
} catch (IllegalArgumentException e) {
error.accept(e);
return null;
}
};
}
class MapperError extends RuntimeException {
public MapperError(final String message) {
super(message);
}
}
static <S, T> Mapper<S, T> error(final String message) {
return error(() -> new MapperError(message));
}
static <S, T, E extends RuntimeException> Mapper<S, T> error(final Supplier<E> error) {
return error((s, t) -> error.get());
}
static <S, T, E extends RuntimeException> Mapper<S, T> error(final BiFunction<S, T, E> error) {
return (t, s) -> {
throw error.apply(s, t);
};
}
@SafeVarargs
static <S, T, R> Mapper<S, T> targetFocus(final Function<T, R> focus, final Mapper<S, R>... mapping) {
return (t, s) -> mapping(mapping).apply(focus.apply(t), s);
}
@SafeVarargs
static <S, T, A> Mapper<S, T> with(final Function<T, A> f, final Mapper<S, A>... rules) {
return (t, s) -> Option.of(f.apply(t)).map(a -> mapping(rules).apply(a, s)).getOrElse(false);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment