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