View Javadoc
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   * A <code>Try</code> represents a computation that may either throw an
33   * exception or return a value. A Try will either be {@link Try.Success Success}
34   * wrapping a value or {@link Try.Failure Failure} which wraps an exception.
35   * <p>
36   * This class is similar to {@link Either}, but is explicit about having a
37   * success and failure case. Unless method level javadoc says otherwise, methods
38   * will not automatically catch exceptions thrown by function arguments. In
39   * particular {@link #map(Function)} will not catch automatically catch thrown
40   * exceptions, instead you should use {@link Checked#lift} to to make the
41   * function explicitly return a Try and the use {@link #flatMap(Function)}.
42   * <p>
43   * Note that since 4.7.0, all API methods describe whether or not they will
44   * result in a {@link Try.Delayed Delayed} Try being evaluated. In addition to
45   * this, any action to {@link Serializable Serialize} a {@link Try.Delayed
46   * Delayed} Try will result in it being evaluated, and the underlying Try
47   * {@link Try.Success Success} or {@link Try.Failure Failure} result being
48   * serialized.
49   *
50   * @since 4.4.0
51   */
52  @SuppressWarnings("WeakerAccess") public abstract class Try<A> implements Serializable, Iterable<A> {
53    private static final long serialVersionUID = -999421999482330308L;
54  
55    /**
56     * Creates a new failure
57     *
58     * @param e an exception to wrap, must not be null.
59     * @param <A> the success type
60     * @return a new Failure wrapping e.
61     */
62    public static <A> Try<A> failure(final Exception e) {
63      return new Failure<>(e);
64    }
65  
66    /**
67     * Creates a new Success
68     *
69     * @param value a value to wrap, must not be null
70     * @param <A> the wrapped value type
71     * @return a new Success wrapping v
72     */
73    public static <A> Try<A> successful(final A value) {
74      return new Success<>(value);
75    }
76  
77    /**
78     * Creates a delayed Try, which will return either a Failure or a Success when
79     * evaluated. The supplier is called only once, no matter how many times the
80     * returned delayed Try is evaluated.
81     *
82     * @param supplier a supplier that returns a Try of A.
83     * @param <A> the wrapped value type
84     * @return a new Delayed Try wrapping the supplier.
85     */
86    public static <A> Try<A> delayed(final Supplier<Try<A>> supplier) {
87      return Delayed.fromSupplier(supplier);
88    }
89  
90    /**
91     * Returns a success wrapping all of the values if all of the arguments were a
92     * success, otherwise this returns the first failure
93     *
94     * @param trys an iterable of try values
95     * @param <A> The success type
96     * @return a success wrapping all of the values if all of the arguments were a
97     * success, otherwise this returns the first failure
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    * Returns a success wrapping all of the values if all of the arguments were a
105    * success, otherwise this returns the first failure
106    *
107    * @param trys an iterable of try values
108    * @param collector result collector
109    * @param <T> The success type
110    * @param <A> The intermediate accumulator type
111    * @param <R> The result type
112    * @return a success wrapping all of the values if all of the arguments were a
113    * success, otherwise this returns the first failure
114    * @since 4.6.0
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    * Reduces a nested Try by a single level
133    *
134    * @param t A nested Try
135    * @param <A> The success type
136    * @return The flattened try
137    */
138   public static <A> Try<A> flatten(Try<Try<A>> t) {
139     return t.flatMap(identity());
140   }
141 
142   /**
143    * Returns <code>true</code> if this failure, otherwise <code>false</code>
144    * <p>
145    * Note that for {@link Try#delayed(Supplier)} this <strong>is</strong> an
146    * evaluating operation.
147    *
148    * @return <code>true</code> if this failure, otherwise <code>false</code>
149    */
150   public abstract boolean isFailure();
151 
152   /**
153    * Returns <code>true</code> if this success, otherwise <code>false</code>
154    * <p>
155    * Note that for {@link Try#delayed(Supplier)} this <strong>is</strong> an
156    * evaluating operation.
157    *
158    * @return <code>true</code> if this success, otherwise <code>false</code>
159    */
160   public abstract boolean isSuccess();
161 
162   /**
163    * Binds the given function across the success value if it is one.
164    * <p>
165    * Note that for {@link Try#delayed(Supplier)} this is not an evaluating
166    * operation.
167    *
168    * @param <B> result type
169    * @param f the function to bind.
170    * @return A new Try value after binding with the function applied if this is
171    * a Success, otherwise returns this if this is a `Failure`.
172    */
173   public abstract <B> Try<B> flatMap(Function<? super A, Try<B>> f);
174 
175   /**
176    * Maps the given function to the value from this `Success` or returns this
177    * unchanged if a `Failure`.
178    * <p>
179    * Note that for {@link Try#delayed(Supplier)} this is not an evaluating
180    * operation.
181    *
182    * @param <B> result type
183    * @param f the function to apply
184    * @return `f` applied to the `Success`, otherwise returns this if this is a
185    * `Failure`.
186    */
187   public abstract <B> Try<B> map(Function<? super A, ? extends B> f);
188 
189   /**
190    * Applies the given function `f` if this is a `Failure` otherwise this
191    * unchanged if a 'Success'. This is like map for the failure.
192    * <p>
193    * Note that for {@link Try#delayed(Supplier)} this is not an evaluating
194    * operation.
195    *
196    * @param f the function to apply
197    * @return `f` applied to the `Failure`, otherwise returns this if this is a
198    * `Success`.
199    */
200   public abstract Try<A> recover(Function<? super Exception, A> f);
201 
202   /**
203    * Applies the given function `f` if this is a `Failure` with certain
204    * exception type otherwise leaves this unchanged. This is like map for
205    * exceptions types.
206    * <p>
207    * Note that for {@link Try#delayed(Supplier)} this is not an evaluating
208    * operation.
209    *
210    * @param exceptionType exception class
211    * @param f the function to apply
212    * @param <X> exception type
213    * @return `f` applied to the `Failure`, otherwise returns this if this is a
214    * `Success` or the exception does not match the exception type.
215    */
216   public abstract <X extends Exception> Try<A> recover(Class<X> exceptionType, Function<? super X, A> f);
217 
218   /**
219    * Binds the given function across the failure value if it is one, otherwise
220    * this unchanged if a 'Success'. This is like flatmap for the failure.
221    * <p>
222    * Note that for {@link Try#delayed(Supplier)} this is not an evaluating
223    * operation.
224    *
225    * @param f the function to bind.
226    * @return A new Try value after binding with the function applied if this is
227    * a `Failure`, otherwise returns this if this is a `Success`.
228    */
229   public abstract Try<A> recoverWith(Function<? super Exception, Try<A>> f);
230 
231   /**
232    * Binds the given function across certain exception type if it is one,
233    * otherwise this unchanged. This is like flatmap for exceptions types.
234    * <p>
235    * Note that for {@link Try#delayed(Supplier)} this is not an evaluating
236    * operation.
237    *
238    * @param exceptionType exception class
239    * @param f the function to apply
240    * @param <X> exception type
241    * @return A new Try value after binding with the function applied if this is
242    * a `Failure`, otherwise returns this if this is a `Success` or the exception
243    * does not match the exception type.
244    */
245   public abstract <X extends Exception> Try<A> recoverWith(Class<X> exceptionType, Function<? super X, Try<A>> f);
246 
247   /**
248    * Returns the contained value if this is a success otherwise call the
249    * supplier and return its value.
250    * <p>
251    * Note that for {@link Try#delayed(Supplier)} this <strong>is</strong> an
252    * evaluating operation.
253    *
254    * @param s called if this is a failure
255    * @return the wrapped value or the value from the {@code Supplier}
256    */
257   public abstract A getOrElse(Supplier<A> s);
258 
259   /**
260    * If this is a success, return the same success. Otherwise, return
261    * {@code orElse}.
262    * <p>
263    * Note that for {@link Try#delayed(Supplier)} this is not an evaluating
264    * operation.
265    *
266    * @param orElse try to return if this is failure
267    * @return this or {@code orElse}
268    * @since 4.7
269    */
270   public final Try<A> orElse(final Try<? extends A> orElse) {
271     return this.orElse(ofInstance(orElse));
272   }
273 
274   /**
275    * If this is a success, return the same success. Otherwise, return value
276    * supplied by {@code orElse}.
277    * <p>
278    * Note that for {@link Try#delayed(Supplier)} this is not an evaluating
279    * operation.
280    *
281    * @param orElse try to return if this is failure
282    * @return this or {@code orElse}
283    * @since 4.7
284    */
285   public abstract Try<A> orElse(final Supplier<? extends Try<? extends A>> orElse);
286 
287   /**
288    * Return a <code>Success</code> if this is a <code>Success</code> and the
289    * contained values satisfies the given predicate.
290    * <p>
291    * If this is a <code>Success</code> but the predicate is not satisfied,
292    * return a <code>Failure</code> with the value provided by the
293    * orElseSupplier.
294    * <p>
295    * Return a <code>Failure</code> if this a <code>Failure</code> with the
296    * contained value.
297    * <p>
298    * Note that for {@link Try#delayed(Supplier)} this is not an evaluating
299    * operation.
300    *
301    * @param p The predicate function to test on the right contained value.
302    * @param orElseSupplier The supplier to execute when is a success, and
303    * predicate is unsatisfied
304    * @return a new Try that will be either the existing success/failure or a
305    * failure with result of orElseSupplier
306    * @since 4.7.0
307    */
308   public abstract Try<A> filterOrElse(Predicate<? super A> p, Supplier<Exception> orElseSupplier);
309 
310   /**
311    * Applies the function to the wrapped value, applying failureF it this is a
312    * Failure and successF if this is a Success.
313    * <p>
314    * Note that for {@link Try#delayed(Supplier)} this <strong>is</strong> an
315    * evaluating operation.
316    *
317    * @param failureF the function to apply if this is a Failure
318    * @param successF the function to apply if this is a Success
319    * @param <B> the destination type
320    * @return the result of the applied function
321    */
322   public abstract <B> B fold(Function<? super Exception, B> failureF, Function<A, B> successF);
323 
324   /**
325    * Convert this Try to an {@link Either}, becoming a left if this is a failure
326    * and a right if this is a success.
327    * <p>
328    * Note that for {@link Try#delayed(Supplier)} this <strong>is</strong> an
329    * evaluating operation.
330    *
331    * @return this value wrapped in right if a success, and the exception wrapped
332    * in a left if a failure.
333    */
334   public abstract Either<Exception, A> toEither();
335 
336   /**
337    * Convert this Try to an Option. Returns <code>Some</code> with a value if it
338    * is a success, otherwise <code>None</code>.
339    * <p>
340    * Note that for {@link Try#delayed(Supplier)} this <strong>is</strong> an
341    * evaluating operation.
342    *
343    * @return The success's value in <code>Some</code> if it exists, otherwise
344    * <code>None</code>
345    */
346   public abstract Option<A> toOption();
347 
348   /**
349    * Create a {@link java.util.Optional} from this try.
350    * <p>
351    * Note that for {@link Try#delayed(Supplier)} this <strong>is</strong> an
352    * evaluating operation.
353    *
354    * @return {@link java.util.Optional#of(Object)} with the value if success,
355    * {@link java.util.Optional#empty()} if failure.
356    * @since 4.7
357    */
358   public abstract Optional<A> toOptional();
359 
360   /**
361    * Create a {@link java.util.stream.Stream} from this try.
362    * <p>
363    * Note that for {@link Try#delayed(Supplier)} this <strong>is</strong> an
364    * evaluating operation.
365    *
366    * @return {@link java.util.stream.Stream#of(Object)} with the value if
367    * success, {@link java.util.stream.Stream#empty()} if failure.
368    * @since 4.7
369    */
370   public abstract Stream<A> toStream();
371 
372   /**
373    * Perform the given {@link java.util.function.Consumer} (side-effect) for the
374    * success {@link #isSuccess() if success} value.
375    * <p>
376    * Note that for {@link Try#delayed(Supplier)} this <strong>is</strong> an
377    * evaluating operation.
378    *
379    * @param action the {@link java.util.function.Consumer} to apply on the
380    * success value
381    * @since 4.7
382    */
383   public abstract void forEach(Consumer<? super A> action);
384 
385   /**
386    * Return an iterator for this type. This will be an empty iterator for the
387    * failure {@link #isFailure()} case, and a iterator of a single value for the
388    * success {@link #isSuccess()} case.
389    * <p>
390    * Note that for {@link Try#delayed(Supplier)} this <strong>is</strong> an
391    * evaluating operation.
392    *
393    * @return an iterator over the contained value {@link #isSuccess() if
394    * success}, or an empty one otherwise.
395    * @since 4.7.1
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       // If you required serialization to return this through a remote call, it
704       // would seem expected for the expression to be evaluated.
705       // Therefore in order to serialize we need to evaluate the Delayed.
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 }