1 package io.atlassian.fugue;
2
3 import java.io.Externalizable;
4 import java.io.IOException;
5 import java.io.ObjectInput;
6 import java.io.ObjectOutput;
7 import java.io.Serializable;
8 import java.util.Collections;
9 import java.util.Iterator;
10 import java.util.NoSuchElementException;
11 import java.util.Optional;
12 import java.util.concurrent.atomic.AtomicReference;
13 import java.util.function.Consumer;
14 import java.util.function.Function;
15 import java.util.function.Predicate;
16 import java.util.function.Supplier;
17 import java.util.stream.Collector;
18 import java.util.stream.Collectors;
19 import java.util.stream.Stream;
20
21 import static io.atlassian.fugue.Either.left;
22 import static io.atlassian.fugue.Either.right;
23 import static io.atlassian.fugue.Option.none;
24 import static io.atlassian.fugue.Option.some;
25 import static io.atlassian.fugue.Suppliers.memoize;
26 import static io.atlassian.fugue.Suppliers.ofInstance;
27 import static io.atlassian.fugue.Unit.Unit;
28 import static java.util.Objects.requireNonNull;
29 import static java.util.function.Function.identity;
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 @SuppressWarnings("WeakerAccess") public abstract class Try<A> implements Serializable, Iterable<A> {
53 private static final long serialVersionUID = -999421999482330308L;
54
55
56
57
58
59
60
61
62 public static <A> Try<A> failure(final Exception e) {
63 return new Failure<>(e);
64 }
65
66
67
68
69
70
71
72
73 public static <A> Try<A> successful(final A value) {
74 return new Success<>(value);
75 }
76
77
78
79
80
81
82
83
84
85
86 public static <A> Try<A> delayed(final Supplier<Try<A>> supplier) {
87 return Delayed.fromSupplier(supplier);
88 }
89
90
91
92
93
94
95
96
97
98
99 public static <A> Try<Iterable<A>> sequence(final Iterable<Try<A>> trys) {
100 return sequence(trys, Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
101 }
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116 public static <T, A, R> Try<R> sequence(final Iterable<Try<T>> trys, final Collector<T, A, R> collector) {
117 A accumulator = collector.supplier().get();
118 for (final Try<T> t : trys) {
119 if (t.isFailure()) {
120 return Try.failure(t.fold(identity(), x -> {
121 throw new NoSuchElementException();
122 }));
123 }
124 collector.accumulator().accept(accumulator, t.fold(f -> {
125 throw new NoSuchElementException();
126 }, identity()));
127 }
128 return Try.successful(collector.finisher().apply(accumulator));
129 }
130
131
132
133
134
135
136
137
138 public static <A> Try<A> flatten(Try<Try<A>> t) {
139 return t.flatMap(identity());
140 }
141
142
143
144
145
146
147
148
149
150 public abstract boolean isFailure();
151
152
153
154
155
156
157
158
159
160 public abstract boolean isSuccess();
161
162
163
164
165
166
167
168
169
170
171
172
173 public abstract <B> Try<B> flatMap(Function<? super A, Try<B>> f);
174
175
176
177
178
179
180
181
182
183
184
185
186
187 public abstract <B> Try<B> map(Function<? super A, ? extends B> f);
188
189
190
191
192
193
194
195
196
197
198
199
200 public abstract Try<A> recover(Function<? super Exception, A> f);
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216 public abstract <X extends Exception> Try<A> recover(Class<X> exceptionType, Function<? super X, A> f);
217
218
219
220
221
222
223
224
225
226
227
228
229 public abstract Try<A> recoverWith(Function<? super Exception, Try<A>> f);
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245 public abstract <X extends Exception> Try<A> recoverWith(Class<X> exceptionType, Function<? super X, Try<A>> f);
246
247
248
249
250
251
252
253
254
255
256
257 public abstract A getOrElse(Supplier<A> s);
258
259
260
261
262
263
264
265
266
267
268
269
270 public final Try<A> orElse(final Try<? extends A> orElse) {
271 return this.orElse(ofInstance(orElse));
272 }
273
274
275
276
277
278
279
280
281
282
283
284
285 public abstract Try<A> orElse(final Supplier<? extends Try<? extends A>> orElse);
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308 public abstract Try<A> filterOrElse(Predicate<? super A> p, Supplier<Exception> orElseSupplier);
309
310
311
312
313
314
315
316
317
318
319
320
321
322 public abstract <B> B fold(Function<? super Exception, B> failureF, Function<A, B> successF);
323
324
325
326
327
328
329
330
331
332
333
334 public abstract Either<Exception, A> toEither();
335
336
337
338
339
340
341
342
343
344
345
346 public abstract Option<A> toOption();
347
348
349
350
351
352
353
354
355
356
357
358 public abstract Optional<A> toOptional();
359
360
361
362
363
364
365
366
367
368
369
370 public abstract Stream<A> toStream();
371
372
373
374
375
376
377
378
379
380
381
382
383 public abstract void forEach(Consumer<? super A> action);
384
385
386
387
388
389
390
391
392
393
394
395
396
397 @Override public final Iterator<A> iterator() {
398 return toOption().iterator();
399 }
400
401 private static final class Failure<A> extends Try<A> {
402 private static final long serialVersionUID = 735762069058538901L;
403
404 private final Exception e;
405
406 Failure(final Exception e) {
407 this.e = requireNonNull(e);
408 }
409
410 @Override public <B> Try<B> map(final Function<? super A, ? extends B> f) {
411 return Try.failure(e);
412 }
413
414 @Override public boolean isFailure() {
415 return true;
416 }
417
418 @Override public boolean isSuccess() {
419 return false;
420 }
421
422 @Override public <B> Try<B> flatMap(final Function<? super A, Try<B>> f) {
423 return Try.failure(e);
424 }
425
426 @Override public Try<A> recover(final Function<? super Exception, A> f) {
427 return Checked.now(() -> f.apply(e));
428 }
429
430 @SuppressWarnings("unchecked") @Override public <X extends Exception> Try<A> recover(final Class<X> exceptionType, final Function<? super X, A> f) {
431 return exceptionType.isAssignableFrom(e.getClass()) ? Checked.now(() -> f.apply((X) e)) : this;
432 }
433
434 @Override public Try<A> recoverWith(final Function<? super Exception, Try<A>> f) {
435 return f.apply(e);
436 }
437
438 @SuppressWarnings("unchecked") @Override public <X extends Exception> Try<A> recoverWith(Class<X> exceptionType, Function<? super X, Try<A>> f) {
439 return exceptionType.isAssignableFrom(e.getClass()) ? f.apply((X) e) : this;
440 }
441
442 @Override public A getOrElse(final Supplier<A> s) {
443 return s.get();
444 }
445
446 @Override public Try<A> orElse(Supplier<? extends Try<? extends A>> orElse) {
447 @SuppressWarnings("unchecked")
448 Try<A> result = (Try<A>) orElse.get();
449 return result;
450 }
451
452 @Override public Try<A> filterOrElse(Predicate<? super A> p, Supplier<Exception> orElseSupplier) {
453 return Try.failure(e);
454 }
455
456 @Override public <B> B fold(final Function<? super Exception, B> failureF, final Function<A, B> successF) {
457 return failureF.apply(e);
458 }
459
460 @Override public Either<Exception, A> toEither() {
461 return left(e);
462 }
463
464 @Override public Option<A> toOption() {
465 return none();
466 }
467
468 @Override public Optional<A> toOptional() {
469 return Optional.empty();
470 }
471
472 @Override public Stream<A> toStream() {
473 return Stream.empty();
474 }
475
476 @Override public void forEach(Consumer<? super A> action) {}
477
478 @Override public boolean equals(final Object o) {
479 if (this == o) {
480 return true;
481 }
482 if (o == null || getClass() != o.getClass()) {
483 return false;
484 }
485
486 final Failure<?> failure = (Failure<?>) o;
487
488 return e != null ? e.equals(failure.e) : failure.e == null;
489 }
490
491 @Override public int hashCode() {
492 return ~e.hashCode();
493 }
494
495 @Override public String toString() {
496 return "Try.Failure(" + e.toString() + ")";
497 }
498 }
499
500 private static final class Success<A> extends Try<A> {
501 private static final long serialVersionUID = -8360076933771852847L;
502
503 private final A value;
504
505 Success(final A value) {
506 this.value = requireNonNull(value);
507 }
508
509 @Override public <B> Try<B> map(final Function<? super A, ? extends B> f) {
510 return Checked.now(() -> f.apply(value));
511 }
512
513 @Override public boolean isFailure() {
514 return false;
515 }
516
517 @Override public boolean isSuccess() {
518 return true;
519 }
520
521 @Override public <B> Try<B> flatMap(final Function<? super A, Try<B>> f) {
522 return f.apply(value);
523 }
524
525 @Override public Try<A> recover(final Function<? super Exception, A> f) {
526 return this;
527 }
528
529 @Override public <X extends Exception> Try<A> recover(final Class<X> exceptionType, final Function<? super X, A> f) {
530 return this;
531 }
532
533 @Override public Try<A> recoverWith(final Function<? super Exception, Try<A>> f) {
534 return this;
535 }
536
537 @Override public <X extends Exception> Try<A> recoverWith(final Class<X> exceptionType, final Function<? super X, Try<A>> f) {
538 return this;
539 }
540
541 @Override public A getOrElse(final Supplier<A> s) {
542 return value;
543 }
544
545 @Override public Try<A> orElse(Supplier<? extends Try<? extends A>> orElse) {
546 return this;
547 }
548
549 @Override public Try<A> filterOrElse(Predicate<? super A> p, Supplier<Exception> orElseSupplier) {
550 return Checked.now(() -> {
551 if (p.test(value)) {
552 return value;
553 }
554 throw orElseSupplier.get();
555 });
556 }
557
558 @Override public <B> B fold(final Function<? super Exception, B> failureF, final Function<A, B> successF) {
559 return successF.apply(value);
560 }
561
562 @Override public Either<Exception, A> toEither() {
563 return right(value);
564 }
565
566 @Override public Option<A> toOption() {
567 return some(value);
568 }
569
570 @Override public Optional<A> toOptional() {
571 return Optional.of(value);
572 }
573
574 @Override public Stream<A> toStream() {
575 return Stream.of(value);
576 }
577
578 @Override public void forEach(Consumer<? super A> action) {
579 action.accept(value);
580 }
581
582 @Override public boolean equals(final Object o) {
583 if (this == o) {
584 return true;
585 }
586 if (o == null || getClass() != o.getClass()) {
587 return false;
588 }
589 final Success<?> success = (Success<?>) o;
590 return value != null ? value.equals(success.value) : success.value == null;
591 }
592
593 @Override public int hashCode() {
594 return value.hashCode();
595 }
596
597 @Override public String toString() {
598 return "Try.Success(" + value.toString() + ")";
599 }
600 }
601
602 private static final class Delayed<A> extends Try<A> implements Externalizable {
603 private static final long serialVersionUID = 2439842151512848666L;
604
605 private final AtomicReference<Function<Unit, Try<A>>> runReference;
606
607 static <A> Delayed<A> fromSupplier(final Supplier<Try<A>> delayed) {
608 Supplier<Try<A>> memorized = memoize(delayed);
609 return new Delayed<>(unit -> memorized.get());
610 }
611
612 public Delayed() {
613 this(unit -> {
614 throw new IllegalStateException("Try.Delayed() default constructor only required for Serialization. Do not invoke directly.");
615 });
616 }
617
618 private Delayed(final Function<Unit, Try<A>> run) {
619 this.runReference = new AtomicReference<>(run);
620 }
621
622 private Function<Unit, Try<A>> getRunner() {
623 return this.runReference.get();
624 }
625
626 private Try<A> eval() {
627 return this.getRunner().apply(Unit());
628 }
629
630 @Override public boolean isFailure() {
631 return eval().isFailure();
632 }
633
634 @Override public boolean isSuccess() {
635 return eval().isSuccess();
636 }
637
638 private <B> Try<B> composeDelayed(Function<Try<A>, Try<B>> f) {
639 return new Delayed<>(f.compose(this.getRunner()));
640 }
641
642 @Override public <B> Try<B> flatMap(Function<? super A, Try<B>> f) {
643 return composeDelayed(t -> t.flatMap(f));
644 }
645
646 @Override public <B> Try<B> map(Function<? super A, ? extends B> f) {
647 return composeDelayed(t -> t.map(f));
648 }
649
650 @Override public Try<A> recover(Function<? super Exception, A> f) {
651 return composeDelayed(t -> t.recover(f));
652 }
653
654 @Override public <X extends Exception> Try<A> recover(Class<X> exceptionType, Function<? super X, A> f) {
655 return composeDelayed(t -> t.recover(exceptionType, f));
656 }
657
658 @Override public Try<A> recoverWith(Function<? super Exception, Try<A>> f) {
659 return composeDelayed(t -> t.recoverWith(f));
660 }
661
662 @Override public <X extends Exception> Try<A> recoverWith(Class<X> exceptionType, Function<? super X, Try<A>> f) {
663 return composeDelayed(t -> t.recoverWith(exceptionType, f));
664 }
665
666 @Override public A getOrElse(Supplier<A> s) {
667 return eval().getOrElse(s);
668 }
669
670 @Override public Try<A> orElse(Supplier<? extends Try<? extends A>> orElse) {
671 return composeDelayed(t -> t.orElse(orElse));
672 }
673
674 @Override public Try<A> filterOrElse(Predicate<? super A> p, Supplier<Exception> orElseSupplier) {
675 return composeDelayed(t -> t.filterOrElse(p, orElseSupplier));
676 }
677
678 @Override public <B> B fold(Function<? super Exception, B> failureF, Function<A, B> successF) {
679 return eval().fold(failureF, successF);
680 }
681
682 @Override public Either<Exception, A> toEither() {
683 return eval().toEither();
684 }
685
686 @Override public Option<A> toOption() {
687 return eval().toOption();
688 }
689
690 @Override public Optional<A> toOptional() {
691 return eval().toOptional();
692 }
693
694 @Override public Stream<A> toStream() {
695 return eval().toStream();
696 }
697
698 @Override public void forEach(Consumer<? super A> action) {
699 eval().forEach(action);
700 }
701
702 @Override public void writeExternal(ObjectOutput out) throws IOException {
703
704
705
706 out.writeObject(eval());
707 }
708
709 @Override @SuppressWarnings("unchecked") public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
710 Try<A> result = (Try<A>) in.readObject();
711 this.runReference.set(unit -> result);
712 }
713 }
714 }