View Javadoc
1   package io.atlassian.fugue.extensions.step;
2   
3   import io.atlassian.fugue.extensions.functions.Function5;
4   import io.atlassian.fugue.extensions.functions.Predicate5;
5   
6   import java.util.Optional;
7   import java.util.function.Function;
8   import java.util.function.Supplier;
9   
10  /**
11   * The fifth step of the {@link Optional} 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(Optional)}
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 Optional
23   * @since 4.7.0
24   */
25  @SuppressWarnings("OptionalUsedAsFieldOrParameterType") public final class OptionalStep5<A, B, C, D, E> {
26    private final Optional<A> optional1;
27    private final Optional<B> optional2;
28    private final Optional<C> optional3;
29    private final Optional<D> optional4;
30    private final Optional<E> optional5;
31  
32    OptionalStep5(Optional<A> optional1, Optional<B> optional2, Optional<C> optional3, Optional<D> optional4, Optional<E> optional5) {
33      this.optional1 = optional1;
34      this.optional2 = optional2;
35      this.optional3 = optional3;
36      this.optional4 = optional4;
37      this.optional5 = optional5;
38    }
39  
40    /**
41     * Apply the provided function with the previous Step results.
42     * <p>
43     * Internally this will perform a {@link Optional#flatMap(Function)} and the
44     * result 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> OptionalStep6<A, B, C, D, E, F> then(Function5<? super A, ? super B, ? super C, ? super D, ? super E, Optional<F>> functor) {
52      Optional<F> optional6 = optional1.flatMap(value1 -> optional2.flatMap(value2 -> optional3.flatMap(value3 -> optional4.flatMap(value4 -> optional5
53        .flatMap(value5 -> functor.apply(value1, value2, value3, value4, value5))))));
54      return new OptionalStep6<>(optional1, optional2, optional3, optional4, optional5, optional6);
55    }
56  
57    /**
58     * Apply the provided supplier with the previous Step results.
59     * <p>
60     * Internally this will perform a {@link Optional#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> OptionalStep6<A, B, C, D, E, F> then(Supplier<Optional<F>> supplier) {
72      Optional<F> optional6 = optional1.flatMap(value1 -> optional2.flatMap(value2 -> optional3.flatMap(value3 -> optional4.flatMap(value4 -> optional5
73        .flatMap(value5 -> supplier.get())))));
74      return new OptionalStep6<>(optional1, optional2, optional3, optional4, optional5, optional6);
75    }
76  
77    /**
78     * Apply the provided predicate with the previous step results.
79     *
80     * @param predicate The check that must be satisfied by contained values
81     * @return This step class with either the same last step value, or changed to
82     * empty
83     */
84    public OptionalStep5<A, B, C, D, E> filter(Predicate5<? super A, ? super B, ? super C, ? super D, ? super E> predicate) {
85      Optional<E> filterOptional5 = optional1.flatMap(value1 -> optional2.flatMap(value2 -> optional3.flatMap(value3 -> optional4
86        .flatMap(value4 -> optional5.filter(value5 -> predicate.test(value1, value2, value3, value4, value5))))));
87      return new OptionalStep5<>(optional1, optional2, optional3, optional4, filterOptional5);
88    }
89  
90    /**
91     * Terminating step expression, that will provide the previous steps to this
92     * function and return the result as a <code>of</code>
93     *
94     * @param functor The yield function to map on previous values
95     * @param <Z> The type for the returned result
96     * @return An Optional containing this result or empty
97     */
98    public <Z> Optional<Z> yield(Function5<? super A, ? super B, ? super C, ? super D, ? super E, Z> functor) {
99      return optional1.flatMap(value1 -> optional2.flatMap(value2 -> optional3.flatMap(value3 -> optional4.flatMap(value4 -> optional5
100       .map(value5 -> functor.apply(value1, value2, value3, value4, value5))))));
101   }
102 }