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 }