Created
April 23, 2019 19:02
-
-
Save sergey-scherbina/ce7e426620d57450fc8d7593d2222a54 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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