1 package io.atlassian.fugue.optic;
2
3 import io.atlassian.fugue.Either;
4 import io.atlassian.fugue.Eithers;
5 import io.atlassian.fugue.Functions;
6 import io.atlassian.fugue.Iterables;
7 import io.atlassian.fugue.Monoid;
8 import io.atlassian.fugue.Monoids;
9 import io.atlassian.fugue.Option;
10 import io.atlassian.fugue.Options;
11 import io.atlassian.fugue.Pair;
12 import io.atlassian.fugue.Suppliers;
13
14 import java.util.Collections;
15 import java.util.function.BiFunction;
16 import java.util.function.Function;
17 import java.util.function.Predicate;
18 import java.util.function.Supplier;
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 public abstract class PTraversal<S, T, A, B> {
34
35
36
37
38
39 public abstract <C> Function<S, Function<C, T>> modifyFunctionF(Function<A, Function<C, B>> f);
40
41
42
43
44
45 public abstract <L> Function<S, Either<L, T>> modifyEitherF(Function<A, Either<L, B>> f);
46
47
48
49
50
51 public abstract Function<S, Option<T>> modifyOptionF(Function<A, Option<B>> f);
52
53
54
55
56
57 public abstract Function<S, Iterable<T>> modifyIterableF(Function<A, Iterable<B>> f);
58
59
60
61
62
63 public abstract Function<S, Supplier<T>> modifySupplierF(Function<A, Supplier<B>> f);
64
65
66
67
68
69 public abstract Function<S, Pair<T, T>> modifyPairF(Function<A, Pair<B, B>> f);
70
71
72
73
74 public abstract <M> Function<S, M> foldMap(Monoid<M> monoid, Function<A, M> f);
75
76
77
78
79 public final Function<S, A> fold(final Monoid<A> monoid) {
80 return foldMap(monoid, Function.identity());
81 }
82
83
84
85
86 public final Iterable<A> getAll(final S s) {
87 return foldMap(Monoids.iterable(), Collections::singleton).apply(s);
88 }
89
90
91
92
93 public final Function<S, Option<A>> find(final Predicate<A> p) {
94 return foldMap(Monoids.firstOption(), a -> p.test(a) ? Option.some(a) : Option.none());
95 }
96
97
98
99
100 public final Option<A> headOption(final S s) {
101 return find(__ -> (Boolean.TRUE)).apply(s);
102 }
103
104
105
106
107 public final Predicate<S> exist(final Predicate<A> p) {
108 return foldMap(Monoids.disjunction, p::test)::apply;
109 }
110
111
112
113
114 public final Predicate<S> all(final Predicate<A> p) {
115 return foldMap(Monoids.conjunction, p::test)::apply;
116 }
117
118
119
120
121 public final Function<S, T> modify(final Function<A, B> f) {
122 return s -> this.modifySupplierF(a -> Suppliers.ofInstance(f.apply(a))).apply(s).get();
123 }
124
125
126
127
128 public final Function<S, T> set(final B b) {
129 return modify(__ -> (b));
130 }
131
132
133
134
135 public final <S1, T1> PTraversal<Either<S, S1>, Either<T, T1>, A, B> sum(final PTraversal<S1, T1, A, B> other) {
136 final PTraversal<S, T, A, B> self = this;
137 return new PTraversal<Either<S, S1>, Either<T, T1>, A, B>() {
138
139 @Override public <C> Function<Either<S, S1>, Function<C, Either<T, T1>>> modifyFunctionF(final Function<A, Function<C, B>> f) {
140 return ss1 -> ss1.fold(s -> self.modifyFunctionF(f).apply(s).andThen(Eithers.toLeft()),
141 s1 -> other.modifyFunctionF(f).apply(s1).andThen(Eithers.toRight()));
142 }
143
144 @Override public <L> Function<Either<S, S1>, Either<L, Either<T, T1>>> modifyEitherF(final Function<A, Either<L, B>> f) {
145 return ss1 -> ss1.fold(s -> self.modifyEitherF(f).apply(s).right().map(Eithers.toLeft()),
146 s1 -> other.modifyEitherF(f).apply(s1).right().map(Eithers.toRight()));
147 }
148
149 @Override public Function<Either<S, S1>, Option<Either<T, T1>>> modifyOptionF(final Function<A, Option<B>> f) {
150 return ss1 -> ss1.fold(s -> self.modifyOptionF(f).apply(s).map(Eithers.toLeft()),
151 s1 -> other.modifyOptionF(f).apply(s1).map(Eithers.toRight()));
152 }
153
154 @Override public Function<Either<S, S1>, Iterable<Either<T, T1>>> modifyIterableF(final Function<A, Iterable<B>> f) {
155 return ss1 -> ss1.fold(s -> Iterables.map(self.modifyIterableF(f).apply(s), Eithers.toLeft()),
156 s1 -> Iterables.map(other.modifyIterableF(f).apply(s1), Eithers.toRight()));
157 }
158
159 @Override public Function<Either<S, S1>, Supplier<Either<T, T1>>> modifySupplierF(final Function<A, Supplier<B>> f) {
160 return ss1 -> ss1.fold(s -> Suppliers.compose(Eithers.toLeft(), self.modifySupplierF(f).apply(s)),
161 s1 -> Suppliers.compose(Eithers.toRight(), other.modifySupplierF(f).apply(s1)));
162 }
163
164 @Override public Function<Either<S, S1>, Pair<Either<T, T1>, Either<T, T1>>> modifyPairF(final Function<A, Pair<B, B>> f) {
165 return ss1 -> ss1.fold(s -> Pair.map(self.modifyPairF(f).apply(s), Eithers.toLeft()),
166 s1 -> Pair.map(other.modifyPairF(f).apply(s1), Eithers.toRight()));
167 }
168
169 @Override public <M> Function<Either<S, S1>, M> foldMap(final Monoid<M> monoid, final Function<A, M> f) {
170 return ss1 -> ss1.fold(self.foldMap(monoid, f), other.foldMap(monoid, f));
171 }
172
173 };
174 }
175
176
177
178
179
180
181
182
183 public final <C> Fold<S, C> composeFold(final Fold<A, C> other) {
184 return asFold().composeFold(other);
185 }
186
187
188
189
190
191
192 public final <C> Fold<S, C> composeFold(final Getter<A, C> other) {
193 return asFold().composeGetter(other);
194 }
195
196
197
198
199 public final <C, D> PSetter<S, T, C, D> composeSetter(final PSetter<A, B, C, D> other) {
200 return asSetter().composeSetter(other);
201 }
202
203
204
205
206 public final <C, D> PTraversal<S, T, C, D> composeTraversal(final PTraversal<A, B, C, D> other) {
207 final PTraversal<S, T, A, B> self = this;
208 return new PTraversal<S, T, C, D>() {
209
210 @Override public <G> Function<S, Function<G, T>> modifyFunctionF(final Function<C, Function<G, D>> f) {
211 return self.modifyFunctionF(other.modifyFunctionF(f));
212 }
213
214 @Override public <L> Function<S, Either<L, T>> modifyEitherF(final Function<C, Either<L, D>> f) {
215 return self.modifyEitherF(other.modifyEitherF(f));
216 }
217
218 @Override public Function<S, Option<T>> modifyOptionF(final Function<C, Option<D>> f) {
219 return self.modifyOptionF(other.modifyOptionF(f));
220 }
221
222 @Override public Function<S, Iterable<T>> modifyIterableF(final Function<C, Iterable<D>> f) {
223 return self.modifyIterableF(other.modifyIterableF(f));
224 }
225
226 @Override public Function<S, Supplier<T>> modifySupplierF(final Function<C, Supplier<D>> f) {
227 return self.modifySupplierF(other.modifySupplierF(f));
228 }
229
230 @Override public Function<S, Pair<T, T>> modifyPairF(final Function<C, Pair<D, D>> f) {
231 return self.modifyPairF(other.modifyPairF(f));
232 }
233
234 @Override public <M> Function<S, M> foldMap(final Monoid<M> monoid, final Function<C, M> f) {
235 return self.foldMap(monoid, other.foldMap(monoid, f));
236 }
237 };
238 }
239
240
241
242
243 public final <C, D> PTraversal<S, T, C, D> composeOptional(final POptional<A, B, C, D> other) {
244 return composeTraversal(other.asTraversal());
245 }
246
247
248
249
250 public final <C, D> PTraversal<S, T, C, D> composePrism(final PPrism<A, B, C, D> other) {
251 return composeTraversal(other.asTraversal());
252 }
253
254
255
256
257 public final <C, D> PTraversal<S, T, C, D> composeLens(final PLens<A, B, C, D> other) {
258 return composeTraversal(other.asTraversal());
259 }
260
261
262
263
264 public final <C, D> PTraversal<S, T, C, D> composeIso(final PIso<A, B, C, D> other) {
265 return composeTraversal(other.asTraversal());
266 }
267
268
269
270
271
272
273
274
275 public final Fold<S, A> asFold() {
276 return new Fold<S, A>() {
277 @Override public <M> Function<S, M> foldMap(final Monoid<M> monoid, final Function<A, M> f) {
278 return PTraversal.this.foldMap(monoid, f);
279 }
280 };
281 }
282
283
284
285
286 public PSetter<S, T, A, B> asSetter() {
287 return PSetter.pSetter(this::modify);
288 }
289
290 public static <S, T> PTraversal<S, T, S, T> pId() {
291 return PIso.<S, T> pId().asTraversal();
292 }
293
294 public static <S, T> PTraversal<Either<S, S>, Either<T, T>, S, T> pCodiagonal() {
295 return new PTraversal<Either<S, S>, Either<T, T>, S, T>() {
296
297 @Override public <C> Function<Either<S, S>, Function<C, Either<T, T>>> modifyFunctionF(final Function<S, Function<C, T>> f) {
298 return s -> s.bimap(f, f).fold(f1 -> f1.andThen(Eithers.toLeft()), f1 -> f1.andThen(Eithers.toRight()));
299 }
300
301 @Override public <L> Function<Either<S, S>, Either<L, Either<T, T>>> modifyEitherF(final Function<S, Either<L, T>> f) {
302 return s -> s.bimap(f, f).fold(e -> e.right().map(Eithers.toLeft()), e -> e.right().map(Eithers.toRight()));
303 }
304
305 @Override public Function<Either<S, S>, Option<Either<T, T>>> modifyOptionF(final Function<S, Option<T>> f) {
306 return s -> s.bimap(f, f).fold(o -> o.map(Eithers.toLeft()), o -> o.map(Eithers.toRight()));
307 }
308
309 @Override public Function<Either<S, S>, Iterable<Either<T, T>>> modifyIterableF(final Function<S, Iterable<T>> f) {
310 return s -> s.bimap(f, f).fold(ts -> Iterables.map(ts, Eithers.toLeft()), ts -> Iterables.map(ts, Eithers.toRight()));
311 }
312
313 @Override public Function<Either<S, S>, Supplier<Either<T, T>>> modifySupplierF(final Function<S, Supplier<T>> f) {
314 return s -> s.bimap(f, f).fold(p1 -> Suppliers.compose(Eithers.toLeft(), p1), p1 -> Suppliers.compose(Eithers.toRight(), p1));
315 }
316
317 @Override public Function<Either<S, S>, Pair<Either<T, T>, Either<T, T>>> modifyPairF(final Function<S, Pair<T, T>> f) {
318 return s -> s.bimap(f, f).fold(tt -> Pair.map(tt, Eithers.toLeft()), tt -> Pair.map(tt, Eithers.toRight()));
319 }
320
321 @Override public <M> Function<Either<S, S>, M> foldMap(final Monoid<M> monoid, final Function<S, M> f) {
322 return s -> s.fold(f, f);
323 }
324 };
325 }
326
327 public static <S, T, A, B> PTraversal<S, T, A, B> pTraversal(final Function<S, A> get1, final Function<S, A> get2,
328 final BiFunction<B, B, Function<S, T>> set) {
329 return new PTraversal<S, T, A, B>() {
330
331 @Override public <C> Function<S, Function<C, T>> modifyFunctionF(final Function<A, Function<C, B>> f) {
332 return s -> Functions.ap(f.apply(get2.apply(s)), f.apply(get1.apply(s)).andThen(b1 -> b2 -> set.apply(b1, b2).apply(s)));
333 }
334
335 @Override public <L> Function<S, Either<L, T>> modifyEitherF(final Function<A, Either<L, B>> f) {
336 return s -> f.apply(get2.apply(s)).right().ap(f.apply(get1.apply(s)).right().<Function<B, T>> map(b1 -> b2 -> set.apply(b1, b2).apply(s)));
337 }
338
339 @Override public Function<S, Option<T>> modifyOptionF(final Function<A, Option<B>> f) {
340 return s -> Options.ap(f.apply(get2.apply(s)), f.apply(get1.apply(s)).<Function<B, T>> map(b1 -> b2 -> set.apply(b1, b2).apply(s)));
341 }
342
343 @Override public Function<S, Iterable<T>> modifyIterableF(final Function<A, Iterable<B>> f) {
344 return s -> Iterables.ap(f.apply(get2.apply(s)), Iterables.map(f.apply(get1.apply(s)), b1 -> b2 -> set.apply(b1, b2).apply(s)));
345 }
346
347 @Override public Function<S, Supplier<T>> modifySupplierF(final Function<A, Supplier<B>> f) {
348 return s -> Suppliers.ap(f.apply(get2.apply(s)), Suppliers.compose(b1 -> b2 -> set.apply(b1, b2).apply(s), f.apply(get1.apply(s))));
349 }
350
351 @Override public Function<S, Pair<T, T>> modifyPairF(final Function<A, Pair<B, B>> f) {
352 return s -> Pair.ap(f.apply(get2.apply(s)), Pair.map(f.apply(get1.apply(s)), b1 -> b2 -> set.apply(b1, b2).apply(s)));
353 }
354
355 @Override public <M> Function<S, M> foldMap(final Monoid<M> monoid, final Function<A, M> f) {
356 return s -> monoid.append(f.apply(get1.apply(s)), f.apply(get2.apply(s)));
357 }
358 };
359 }
360
361 public static <S, T, A, B> PTraversal<S, T, A, B> pTraversal(final Function<S, A> get1, final Function<S, A> get2, final Function<S, A> get3,
362 final Function<B, Function<B, Function<B, Function<S, T>>>> set) {
363 return fromCurried(pTraversal(get1, get2, (b1, b2) -> s -> (b3 -> set.apply(b1).apply(b2).apply(b3).apply(s))), get3);
364 }
365
366 public static <S, T, A, B> PTraversal<S, T, A, B> pTraversal(final Function<S, A> get1, final Function<S, A> get2, final Function<S, A> get3,
367 final Function<S, A> get4, final Function<B, Function<B, Function<B, Function<B, Function<S, T>>>>> set) {
368 return fromCurried(pTraversal(get1, get2, get3, b1 -> b2 -> b3 -> s -> b4 -> set.apply(b1).apply(b2).apply(b3).apply(b4).apply(s)), get4);
369 }
370
371 public static <S, T, A, B> PTraversal<S, T, A, B> pTraversal(final Function<S, A> get1, final Function<S, A> get2, final Function<S, A> get3,
372 final Function<S, A> get4, final Function<S, A> get5, final Function<B, Function<B, Function<B, Function<B, Function<B, Function<S, T>>>>>> set) {
373 return fromCurried(
374 pTraversal(get1, get2, get3, get4, b1 -> b2 -> b3 -> b4 -> s -> b5 -> set.apply(b1).apply(b2).apply(b3).apply(b4).apply(b5).apply(s)), get5);
375 }
376
377 public static <S, T, A, B> PTraversal<S, T, A, B> pTraversal(final Function<S, A> get1, final Function<S, A> get2, final Function<S, A> get3,
378 final Function<S, A> get4, final Function<S, A> get5, final Function<S, A> get6,
379 final Function<B, Function<B, Function<B, Function<B, Function<B, Function<B, Function<S, T>>>>>>> set) {
380 return fromCurried(
381 pTraversal(get1, get2, get3, get4, get5,
382 b1 -> b2 -> b3 -> b4 -> b5 -> s -> b6 -> set.apply(b1).apply(b2).apply(b3).apply(b4).apply(b5).apply(b6).apply(s)), get6);
383 }
384
385 private static <S, T, A, B> PTraversal<S, T, A, B> fromCurried(final PTraversal<S, Function<B, T>, A, B> curriedTraversal,
386 final Function<S, A> lastGet) {
387 return new PTraversal<S, T, A, B>() {
388
389 @Override public <C> Function<S, Function<C, T>> modifyFunctionF(final Function<A, Function<C, B>> f) {
390 return s -> Functions.ap(f.apply(lastGet.apply(s)), curriedTraversal.modifyFunctionF(f).apply(s));
391 }
392
393 @Override public <L> Function<S, Either<L, T>> modifyEitherF(final Function<A, Either<L, B>> f) {
394 return s -> f.apply(lastGet.apply(s)).right().ap(curriedTraversal.modifyEitherF(f).apply(s));
395 }
396
397 @Override public Function<S, Option<T>> modifyOptionF(final Function<A, Option<B>> f) {
398 return s -> Options.ap(f.apply(lastGet.apply(s)), curriedTraversal.modifyOptionF(f).apply(s));
399 }
400
401 @Override public Function<S, Iterable<T>> modifyIterableF(final Function<A, Iterable<B>> f) {
402 return s -> Iterables.ap(f.apply(lastGet.apply(s)), curriedTraversal.modifyIterableF(f).apply(s));
403 }
404
405 @Override public Function<S, Supplier<T>> modifySupplierF(final Function<A, Supplier<B>> f) {
406 return s -> Suppliers.ap(f.apply(lastGet.apply(s)), curriedTraversal.modifySupplierF(f).apply(s));
407 }
408
409 @Override public Function<S, Pair<T, T>> modifyPairF(final Function<A, Pair<B, B>> f) {
410 return s -> Pair.ap(f.apply(lastGet.apply(s)), curriedTraversal.modifyPairF(f).apply(s));
411 }
412
413 @Override public <M> Function<S, M> foldMap(final Monoid<M> monoid, final Function<A, M> f) {
414 return s -> monoid.append(curriedTraversal.foldMap(monoid, f).apply(s), f.apply(lastGet.apply(s)));
415 }
416 };
417 }
418 }