View Javadoc

1   /*
2      Copyright 2011 Atlassian
3   
4      Licensed under the Apache License, Version 2.0 (the "License");
5      you may not use this file except in compliance with the License.
6      You may obtain a copy of the License at
7   
8          http://www.apache.org/licenses/LICENSE-2.0
9   
10     Unless required by applicable law or agreed to in writing, software
11     distributed under the License is distributed on an "AS IS" BASIS,
12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13     See the License for the specific language governing permissions and
14     limitations under the License.
15   */
16  package io.atlassian.fugue;
17  
18  import java.lang.ref.WeakReference;
19  import java.util.Objects;
20  import java.util.function.Function;
21  import java.util.function.Supplier;
22  
23  /**
24   * Provide utility functions for the class of functions that supply a return
25   * value when invoked.
26   *
27   * @since 1.0
28   */
29  public class Suppliers {
30    /**
31     * Creates a {@link java.util.function.Supplier} of a constant value.
32     *
33     * @param <A> the type
34     * @param a the constant value to supply
35     * @return a supplier that always supplies {@code instance}.
36     */
37    public static <A> Supplier<A> ofInstance(final A a) {
38      return () -> a;
39    }
40  
41    /**
42     * Create a new {@link java.util.function.Supplier} by transforming the result
43     * calling the first {@link java.util.function.Supplier}
44     *
45     * @param transform function to transform the result of a
46     * {@link java.util.function.Supplier} of A's to B's
47     * @param first a {@link java.util.function.Supplier} of A's
48     * @param <A> return type of the {@link java.util.function.Supplier} to
49     * transform
50     * @param <B> return type of the new {@link java.util.function.Supplier}
51     * @return a new {@link java.util.function.Supplier} returning B's
52     */
53    public static <A, B> Supplier<B> compose(final Function<? super A, B> transform, final Supplier<A> first) {
54      return () -> transform.apply(first.get());
55    }
56  
57    /**
58     * Performs function application within a supplier (applicative functor
59     * pattern).
60     *
61     * @param sa supplier
62     * @param sf The Supplier function to apply.
63     * @return A new Supplier after applying the given Supplier function to the
64     * first argument.
65     * @since 4.0
66     */
67    public static <A, B> Supplier<B> ap(final Supplier<A> sa, final Supplier<Function<A, B>> sf) {
68      return () -> sf.get().apply(sa.get());
69    }
70  
71    /**
72     * Supplies true.
73     *
74     * @return a supplier that always supplies {@code true}.
75     */
76    public static Supplier<Boolean> alwaysTrue() {
77      return () -> true;
78    }
79  
80    /**
81     * Supplies false.
82     *
83     * @return a supplier that always supplies {@code false}.
84     */
85    public static Supplier<Boolean> alwaysFalse() {
86      return () -> false;
87    }
88  
89    /**
90     * Always returns null. Not a very good idea.
91     *
92     * @param <A> the type
93     * @return a supplier that always supplies {@code null}.
94     */
95    public static <A> Supplier<A> alwaysNull() {
96      return () -> null;
97    }
98  
99    /**
100    * Turns an Option into a supplier, but throws an exception if undefined. Not
101    * a very good idea.
102    *
103    * @param <A> the type
104    * @param option the option to attempt to get values from
105    * @return a {@link java.util.function.Supplier} that always calls
106    * {@link io.atlassian.fugue.Option#get()}, which throws an Exception if the
107    * option is None
108    * @since 2.0
109    */
110   public static <A> Supplier<A> fromOption(final Option<A> option) {
111     return option::get;
112   }
113 
114   /**
115    * Constantly applies the input value to the supplied function, and returns
116    * the result.
117    *
118    * @param <A> the input type
119    * @param <B> the result type
120    * @param f the function
121    * @param a the value
122    * @return a {@link java.util.function.Supplier} that always calls
123    * {@link java.util.function.Function#apply(Object)}
124    * @since 2.2
125    */
126   public static <A, B> Supplier<B> fromFunction(final Function<? super A, ? extends B> f, final A a) {
127     return () -> f.apply(a);
128   }
129 
130   /**
131    * A supplier that memoize the value return by another
132    * {@link java.util.function.Supplier}, whose
133    * {@link java.util.function.Supplier#get()} method is guaranteed to be call
134    * at most once. The returned {@link java.util.function.Supplier} is
135    * thread-safe
136    *
137    * @param <A> the type
138    * @param supplier the supplier to memoize
139    * @return the memoizing supplier
140    */
141   public static <A> Supplier<A> memoize(final Supplier<A> supplier) {
142     return supplier instanceof MemoizingSupplier ? supplier : new MemoizingSupplier<>(Objects.requireNonNull(supplier));
143   }
144 
145   /**
146    * A supplier that weakly memoize the value return by another
147    * {@link java.util.function.Supplier} , The returned
148    * {@link java.util.function.Supplier} is thread-safe
149    *
150    * @param <A> the type
151    * @param supplier the supplier to memoize
152    * @return the weakly memoizing supplier
153    */
154   public static <A> Supplier<A> weakMemoize(final Supplier<A> supplier) {
155     return supplier instanceof WeakMemoizingSupplier || supplier instanceof MemoizingSupplier ? supplier : new WeakMemoizingSupplier<>(
156       Objects.requireNonNull(supplier));
157   }
158 
159   private static final class MemoizingSupplier<A> implements Supplier<A> {
160 
161     private volatile Supplier<A> delegate;
162 
163     private A a;
164 
165     MemoizingSupplier(final Supplier<A> delegate) {
166       this.delegate = delegate;
167     }
168 
169     @Override public A get() {
170       // double Checked Locking
171       if (delegate != null) {
172         synchronized (this) {
173           if (delegate != null) {
174             final A res;
175             this.a = res = delegate.get();
176             delegate = null;
177             return res;
178           }
179         }
180       }
181       return a;
182     }
183   }
184 
185   private static final class WeakMemoizingSupplier<A> implements Supplier<A> {
186 
187     private final Supplier<A> delegate;
188 
189     // Contains a the value from delegate.
190     private volatile WeakReference<A> value;
191 
192     WeakMemoizingSupplier(final Supplier<A> delegate) {
193       this.delegate = delegate;
194     }
195 
196     @Override public A get() {
197       A a = value == null ? null : value.get();
198       // double Checked Locking
199       if (a == null) {
200         synchronized (this) {
201           a = value == null ? null : value.get();
202           if (a == null) {
203             a = delegate.get();
204             value = new WeakReference<A>(a);
205           }
206         }
207       }
208       return a;
209     }
210   }
211 }