1 package io.atlassian.fugue.optic;
2
3 import io.atlassian.fugue.Either;
4 import io.atlassian.fugue.Eithers;
5 import io.atlassian.fugue.Iterables;
6 import io.atlassian.fugue.Monoid;
7 import io.atlassian.fugue.Option;
8 import io.atlassian.fugue.Pair;
9 import io.atlassian.fugue.Suppliers;
10
11 import java.util.Collections;
12 import java.util.function.Function;
13 import java.util.function.Supplier;
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 public abstract class POptional<S, T, A, B> {
33
34 POptional() {
35 super();
36 }
37
38
39
40
41
42 public abstract Either<T, A> getOrModify(S s);
43
44
45
46
47 public abstract Function<S, T> set(final B b);
48
49
50
51
52 public abstract Option<A> getOption(final S s);
53
54
55
56
57
58 public abstract <C> Function<S, Function<C, T>> modifyFunctionF(final Function<A, Function<C, B>> f);
59
60
61
62
63
64 public abstract <L> Function<S, Either<L, T>> modifyEitherF(final Function<A, Either<L, B>> f);
65
66
67
68
69
70 public abstract Function<S, Option<T>> modifyOptionF(Function<A, Option<B>> f);
71
72
73
74
75
76 public abstract Function<S, Pair<T, T>> modifyPairF(final Function<A, Pair<B, B>> f);
77
78
79
80
81
82 public abstract Function<S, Supplier<T>> modifySupplierF(Function<A, Supplier<B>> f);
83
84
85
86
87
88 public abstract Function<S, Iterable<T>> modifyIterableF(final Function<A, Iterable<B>> f);
89
90
91
92
93 public abstract Function<S, T> modify(final Function<A, B> f);
94
95
96
97
98
99 public final Function<S, Option<T>> modifyOption(final Function<A, B> f) {
100 return s -> getOption(s).map(__ -> modify(f).apply(s));
101 }
102
103
104
105
106
107 public final Function<S, Option<T>> setOption(final B b) {
108 return modifyOption(__ -> (b));
109 }
110
111
112
113
114 public final boolean isMatching(final S s) {
115 return getOption(s).isDefined();
116
117 }
118
119
120
121
122 public final <S1, T1> POptional<Either<S, S1>, Either<T, T1>, A, B> sum(final POptional<S1, T1, A, B> other) {
123 return pOptional(e -> e.fold(s -> getOrModify(s).left().map(Eithers.toLeft()), s1 -> other.getOrModify(s1).left().map(Eithers.toRight())),
124 b -> e -> e.bimap(set(b), other.set(b)));
125 }
126
127 public <C> POptional<Pair<S, C>, Pair<T, C>, Pair<A, C>, Pair<B, C>> first() {
128 return pOptional(sc -> getOrModify(sc.left()).bimap(t -> Pair.pair(t, sc.right()), a -> Pair.pair(a, sc.right())),
129 bc -> s_ -> Pair.pair(set(bc.left()).apply(s_.left()), bc.right()));
130 }
131
132 public <C> POptional<Pair<C, S>, Pair<C, T>, Pair<C, A>, Pair<C, B>> second() {
133 return pOptional(cs -> getOrModify(cs.right()).bimap(t -> Pair.pair(cs.left(), t), a -> Pair.pair(cs.left(), a)),
134 cb -> _s -> Pair.pair(cb.left(), set(cb.right()).apply(_s.right())));
135 }
136
137
138
139
140
141
142
143
144 public final <C> Fold<S, C> composeFold(final Fold<A, C> other) {
145 return asFold().composeFold(other);
146 }
147
148
149
150
151 public final <C> Fold<S, C> composeGetter(final Getter<A, C> other) {
152 return asFold().composeGetter(other);
153 }
154
155
156
157
158 public final <C, D> PSetter<S, T, C, D> composeSetter(final PSetter<A, B, C, D> other) {
159 return asSetter().composeSetter(other);
160 }
161
162
163
164
165 public final <C, D> PTraversal<S, T, C, D> composeTraversal(final PTraversal<A, B, C, D> other) {
166 return asTraversal().composeTraversal(other);
167 }
168
169
170
171
172 public final <C, D> POptional<S, T, C, D> composeOptional(final POptional<A, B, C, D> other) {
173 final POptional<S, T, A, B> self = this;
174 return new POptional<S, T, C, D>() {
175
176 @Override public Either<T, C> getOrModify(final S s) {
177 return self.getOrModify(s).right().flatMap(a -> other.getOrModify(a).bimap(b -> POptional.this.set(b).apply(s), Function.identity()));
178 }
179
180 @Override public Function<S, T> set(final D d) {
181 return self.modify(other.set(d));
182 }
183
184 @Override public Option<C> getOption(final S s) {
185 return self.getOption(s).flatMap(other::getOption);
186 }
187
188 @Override public <G> Function<S, Function<G, T>> modifyFunctionF(final Function<C, Function<G, D>> f) {
189 return self.modifyFunctionF(other.modifyFunctionF(f));
190 }
191
192 @Override public <L> Function<S, Either<L, T>> modifyEitherF(final Function<C, Either<L, D>> f) {
193 return self.modifyEitherF(other.modifyEitherF(f));
194 }
195
196 @Override public Function<S, Option<T>> modifyOptionF(final Function<C, Option<D>> f) {
197 return self.modifyOptionF(other.modifyOptionF(f));
198 }
199
200 @Override public Function<S, Iterable<T>> modifyIterableF(final Function<C, Iterable<D>> f) {
201 return self.modifyIterableF(other.modifyIterableF(f));
202 }
203
204 @Override public Function<S, Supplier<T>> modifySupplierF(final Function<C, Supplier<D>> f) {
205 return self.modifySupplierF(other.modifySupplierF(f));
206 }
207
208 @Override public Function<S, Pair<T, T>> modifyPairF(final Function<C, Pair<D, D>> f) {
209 return self.modifyPairF(other.modifyPairF(f));
210 }
211
212 @Override public Function<S, T> modify(final Function<C, D> f) {
213 return self.modify(other.modify(f));
214 }
215 };
216 }
217
218
219
220
221 public final <C, D> POptional<S, T, C, D> composePrism(final PPrism<A, B, C, D> other) {
222 return composeOptional(other.asOptional());
223 }
224
225
226
227
228 public final <C, D> POptional<S, T, C, D> composeLens(final PLens<A, B, C, D> other) {
229 return composeOptional(other.asOptional());
230 }
231
232
233
234
235 public final <C, D> POptional<S, T, C, D> composeIso(final PIso<A, B, C, D> other) {
236 return composeOptional(other.asOptional());
237 }
238
239
240
241
242
243
244
245
246 public final Fold<S, A> asFold() {
247 return new Fold<S, A>() {
248 @Override public <M> Function<S, M> foldMap(final Monoid<M> monoid, final Function<A, M> f) {
249 return s -> POptional.this.getOption(s).map(f).getOrElse(monoid.zero());
250 }
251 };
252 }
253
254
255
256
257 public PSetter<S, T, A, B> asSetter() {
258 return new PSetter<S, T, A, B>() {
259 @Override public Function<S, T> modify(final Function<A, B> f) {
260 return POptional.this.modify(f);
261 }
262
263 @Override public Function<S, T> set(final B b) {
264 return POptional.this.set(b);
265 }
266 };
267 }
268
269
270
271
272 public PTraversal<S, T, A, B> asTraversal() {
273 final POptional<S, T, A, B> self = this;
274 return new PTraversal<S, T, A, B>() {
275
276 @Override public <C> Function<S, Function<C, T>> modifyFunctionF(final Function<A, Function<C, B>> f) {
277 return self.modifyFunctionF(f);
278 }
279
280 @Override public <L> Function<S, Either<L, T>> modifyEitherF(final Function<A, Either<L, B>> f) {
281 return self.modifyEitherF(f);
282 }
283
284 @Override public Function<S, Option<T>> modifyOptionF(final Function<A, Option<B>> f) {
285 return self.modifyOptionF(f);
286 }
287
288 @Override public Function<S, Iterable<T>> modifyIterableF(final Function<A, Iterable<B>> f) {
289 return self.modifyIterableF(f);
290 }
291
292 @Override public Function<S, Supplier<T>> modifySupplierF(final Function<A, Supplier<B>> f) {
293 return self.modifySupplierF(f);
294 }
295
296 @Override public Function<S, Pair<T, T>> modifyPairF(final Function<A, Pair<B, B>> f) {
297 return self.modifyPairF(f);
298 }
299
300 @Override public <M> Function<S, M> foldMap(final Monoid<M> monoid, final Function<A, M> f) {
301 return s -> self.getOption(s).map(f).getOrElse(monoid.zero());
302 }
303 };
304 }
305
306 public static <S, T> POptional<S, T, S, T> pId() {
307 return PIso.<S, T> pId().asOptional();
308 }
309
310
311
312
313
314 public static <S, T, A, B> POptional<S, T, A, B> pOptional(final Function<S, Either<T, A>> getOrModify, final Function<B, Function<S, T>> set) {
315 return new POptional<S, T, A, B>() {
316 @Override public Either<T, A> getOrModify(final S s) {
317 return getOrModify.apply(s);
318 }
319
320 @Override public Function<S, T> set(final B b) {
321 return set.apply(b);
322 }
323
324 @Override public Option<A> getOption(final S s) {
325 return getOrModify.apply(s).right().toOption();
326 }
327
328 @Override public <C> Function<S, Function<C, T>> modifyFunctionF(final Function<A, Function<C, B>> f) {
329 return s -> getOrModify.apply(s).fold(t -> __ -> t, a -> f.apply(a).andThen(b -> set.apply(b).apply(s)));
330 }
331
332 @Override public <L> Function<S, Either<L, T>> modifyEitherF(final Function<A, Either<L, B>> f) {
333 return s -> getOrModify.apply(s).fold(Eithers.toRight(), t -> f.apply(t).right().map(b -> set.apply(b).apply(s)));
334 }
335
336 @Override public Function<S, Option<T>> modifyOptionF(final Function<A, Option<B>> f) {
337 return s -> getOrModify.apply(s).fold(Option::some, t -> f.apply(t).map(b -> set.apply(b).apply(s)));
338 }
339
340 @Override public Function<S, Iterable<T>> modifyIterableF(final Function<A, Iterable<B>> f) {
341 return s -> getOrModify.apply(s).fold(Collections::singleton, t -> Iterables.<B, T> map(f.apply(t), b -> set.apply(b).apply(s)));
342 }
343
344 @Override public Function<S, Supplier<T>> modifySupplierF(final Function<A, Supplier<B>> f) {
345 return s -> getOrModify.apply(s).fold(Suppliers::ofInstance, t -> Suppliers.<B, T> compose(b -> set.apply(b).apply(s), f.apply(t)));
346 }
347
348 @Override public Function<S, Pair<T, T>> modifyPairF(final Function<A, Pair<B, B>> f) {
349 return s -> getOrModify.apply(s).fold(t -> Pair.pair(t, t), t -> Pair.<B, T> map(f.apply(t), b -> set.apply(b).apply(s)));
350 }
351
352 @Override public Function<S, T> modify(final Function<A, B> f) {
353 return s -> getOrModify.apply(s).fold(Function.identity(), a -> set.apply(f.apply(a)).apply(s));
354 }
355 };
356 }
357 }