1 package io.atlassian.fugue.optic.law;
2
3 import io.atlassian.fugue.*;
4 import io.atlassian.fugue.law.IsEq;
5 import io.atlassian.fugue.optic.PTraversal;
6
7 import java.util.Collections;
8 import java.util.List;
9 import java.util.function.Function;
10 import java.util.stream.Collectors;
11 import java.util.stream.StreamSupport;
12
13 import static io.atlassian.fugue.law.IsEq.isEq;
14 import static java.util.Spliterator.ORDERED;
15 import static java.util.Spliterators.spliteratorUnknownSize;
16 import static java.util.stream.Collectors.toList;
17 import static java.util.stream.StreamSupport.stream;
18
19 public final class TraversalLaws<S, A> {
20
21 private final PTraversal<S, S, A, A> traversal;
22
23 public TraversalLaws(PTraversal<S, S, A, A> traversal) {
24 this.traversal = traversal;
25 }
26
27
28
29
30 public IsEq<List<A>> setGetAll(S s, A a) {
31 return isEq(stream(traversal.getAll(traversal.set(a).apply(s)).spliterator(), false).collect(Collectors.toList()),
32 stream(Iterables.map(traversal.getAll(s), __ -> a).spliterator(), false).collect(Collectors.toList()));
33 }
34
35
36
37
38 public IsEq<S> setIdempotent(S s, A a) {
39 return isEq(traversal.set(a).apply(traversal.set(a).apply(s)), traversal.set(a).apply(s));
40 }
41
42
43
44
45 public IsEq<S> modifyIdentity(S s) {
46 return isEq(traversal.modify(Function.<A> identity()).apply(s), s);
47 }
48
49
50
51
52 public IsEq<S> modifySupplierFPoint(S s) {
53 return isEq(traversal.modifySupplierF(Suppliers::ofInstance).apply(s).get(), s);
54 }
55
56
57
58
59 public IsEq<Either<String, S>> modifyEitherFPoint(S s) {
60 return isEq(traversal.<String> modifyEitherF(Eithers.toRight()).apply(s), Either.right(s));
61 }
62
63
64
65
66 public IsEq<Option<S>> modifyOptionFPoint(S s) {
67 return isEq(traversal.modifyOptionF(Options.toOption()).apply(s), Option.some(s));
68 }
69
70
71
72
73 public IsEq<Pair<S, S>> modifyPairFPoint(S s) {
74 return isEq(traversal.modifyPairF(a -> Pair.pair(a, a)).apply(s), Pair.pair(s, s));
75 }
76
77
78
79
80 public IsEq<S> modifyFunctionFPoint(S s) {
81 return isEq(traversal.<String> modifyFunctionF(a -> __ -> a).apply(s).apply(""), s);
82 }
83
84
85
86
87 public IsEq<List<S>> modifyIterableFPoint(S s) {
88 return isEq(
89 stream(spliteratorUnknownSize(traversal.modifyIterableF(Collections::singleton).apply(s).iterator(), ORDERED), false).collect(toList()),
90 Collections.singletonList(s));
91 }
92
93
94
95
96 public IsEq<Option<A>> headOption(S s) {
97 return isEq(traversal.headOption(s), Iterables.first(traversal.getAll(s)));
98 }
99
100 }