1 package io.atlassian.fugue.extensions.step;
2
3 import io.atlassian.fugue.Try;
4 import io.atlassian.fugue.extensions.functions.Function5;
5 import io.atlassian.fugue.extensions.functions.Predicate5;
6
7 import java.util.function.Function;
8 import java.util.function.Supplier;
9
10 /**
11 * The fifth step of the {@link Try} type.
12 * <p>
13 * This class is not intended to be contructed manually, and should only be used
14 * as part of a {@link Steps} chain, started by {@link Steps#begin(Try)}
15 *
16 * @param <A> The type of the first defined value
17 * @param <B> The type of the second defined value
18 * @param <C> The type of the third defined value
19 * @param <D> The type of the fourth defined value
20 * @param <E> The type of the fifth defined value
21 * @see Steps for usage examples
22 * @see Try
23 * @since 4.7.0
24 */
25 public final class TryStep5<A, B, C, D, E> {
26 private final Try<A> try1;
27 private final Try<B> try2;
28 private final Try<C> try3;
29 private final Try<D> try4;
30 private final Try<E> try5;
31
32 TryStep5(Try<A> try1, Try<B> try2, Try<C> try3, Try<D> try4, Try<E> try5) {
33 this.try1 = try1;
34 this.try2 = try2;
35 this.try3 = try3;
36 this.try4 = try4;
37 this.try5 = try5;
38 }
39
40 /**
41 * Apply the provided function with the previous Step results.
42 * <p>
43 * Internally this will perform a {@link Try#flatMap(Function)} and the result
44 * will become the next step value.
45 *
46 * @param functor The functor to be applied as a flatMap with the previous
47 * steps
48 * @param <F> The type of the next step result
49 * @return The next step class
50 */
51 public <F> TryStep6<A, B, C, D, E, F> then(Function5<? super A, ? super B, ? super C, ? super D, ? super E, Try<F>> functor) {
52 Try<F> try6 = try1.flatMap(value1 -> try2.flatMap(value2 -> try3.flatMap(value3 -> try4.flatMap(value4 -> try5.flatMap(value5 -> functor.apply(
53 value1, value2, value3, value4, value5))))));
54 return new TryStep6<>(try1, try2, try3, try4, try5, try6);
55 }
56
57 /**
58 * Apply the provided supplier with the previous Step results.
59 * <p>
60 * Internally this will perform a {@link Try#flatMap(Function)} and the
61 * supplier will become the next step value.
62 * <p>
63 * This is different to {@link #then(Function5)} in that the previous step
64 * results are not provided for the new step evaluation.
65 *
66 * @param supplier The supplier to provide the result of the flatMap with the
67 * previous step.
68 * @param <F> The type of the next step result
69 * @return The next step class
70 */
71 public <F> TryStep6<A, B, C, D, E, F> then(Supplier<Try<F>> supplier) {
72 Try<F> try6 = try1
73 .flatMap(value1 -> try2.flatMap(value2 -> try3.flatMap(value3 -> try4.flatMap(value4 -> try5.flatMap(value5 -> supplier.get())))));
74 return new TryStep6<>(try1, try2, try3, try4, try5, try6);
75 }
76
77 /**
78 * Apply the provided predicate with the previous step results.
79 * <p>
80 * If the predicate is not satisfied then the unsatisfiedSupplier is used to
81 * populate the failure value that will prevent any further steps evaluation.
82 *
83 * @param predicate The check that must be satisfied by contained values
84 * @param unsatisfiedSupplier Provide the value to populate the failure if not
85 * satisfied
86 * @return This step class with either the same last step value, or changed to
87 * a failure
88 */
89 public TryStep5<A, B, C, D, E> filter(Predicate5<? super A, ? super B, ? super C, ? super D, ? super E> predicate,
90 Supplier<Exception> unsatisfiedSupplier) {
91 Try<E> filterTry5 = try1.flatMap(value1 -> try2.flatMap(value2 -> try3.flatMap(value3 -> try4.flatMap(value4 -> try5.filterOrElse(
92 value5 -> predicate.test(value1, value2, value3, value4, value5), unsatisfiedSupplier)))));
93 return new TryStep5<>(try1, try2, try3, try4, filterTry5);
94 }
95
96 /**
97 * Terminating step expression, that will provide the previous steps to this
98 * function and return the result as a <code>Success</code>
99 *
100 * @param functor The yield function to map on previous values
101 * @param <Z> The type for the returned result
102 * @return A Try containing this result as success or failure
103 */
104 public <Z> Try<Z> yield(Function5<? super A, ? super B, ? super C, ? super D, ? super E, Z> functor) {
105 return try1.flatMap(value1 -> try2.flatMap(value2 -> try3.flatMap(value3 -> try4.flatMap(value4 -> try5.map(value5 -> functor.apply(value1,
106 value2, value3, value4, value5))))));
107 }
108 }