001/*
002 * Copyright (C) 2007 The Guava Authors
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package com.google.common.base;
018
019import static com.google.common.base.Preconditions.checkArgument;
020import static com.google.common.base.Preconditions.checkNotNull;
021
022import com.google.common.annotations.Beta;
023import com.google.common.annotations.GwtCompatible;
024
025import java.io.Serializable;
026import java.util.Map;
027
028import javax.annotation.CheckReturnValue;
029import javax.annotation.Nullable;
030
031/**
032 * Static utility methods pertaining to {@code Function} instances.
033 *
034 * <p>All methods return serializable functions as long as they're given serializable parameters.
035 *
036 * <p>See the Guava User Guide article on <a href=
037 * "https://github.com/google/guava/wiki/FunctionalExplained">the use of {@code
038 * Function}</a>.
039 *
040 * @author Mike Bostock
041 * @author Jared Levy
042 * @since 2.0
043 */
044@GwtCompatible
045@CheckReturnValue
046public final class Functions {
047  private Functions() {}
048
049  /**
050   * Returns a function that calls {@code toString()} on its argument. The function does not accept
051   * nulls; it will throw a {@link NullPointerException} when applied to {@code null}.
052   *
053   * <p><b>Warning:</b> The returned function may not be <i>consistent with equals</i> (as
054   * documented at {@link Function#apply}). For example, this function yields different results for
055   * the two equal instances {@code ImmutableSet.of(1, 2)} and {@code ImmutableSet.of(2, 1)}.
056   */
057  public static Function<Object, String> toStringFunction() {
058    return ToStringFunction.INSTANCE;
059  }
060
061  // enum singleton pattern
062  private enum ToStringFunction implements Function<Object, String> {
063    INSTANCE;
064
065    @Override
066    public String apply(Object o) {
067      checkNotNull(o); // eager for GWT.
068      return o.toString();
069    }
070
071    @Override
072    public String toString() {
073      return "Functions.toStringFunction()";
074    }
075  }
076
077  /**
078   * Returns the identity function.
079   */
080  // implementation is "fully variant"; E has become a "pass-through" type
081  @SuppressWarnings("unchecked")
082  public static <E> Function<E, E> identity() {
083    return (Function<E, E>) IdentityFunction.INSTANCE;
084  }
085
086  // enum singleton pattern
087  private enum IdentityFunction implements Function<Object, Object> {
088    INSTANCE;
089
090    @Override
091    @Nullable
092    public Object apply(@Nullable Object o) {
093      return o;
094    }
095
096    @Override
097    public String toString() {
098      return "Functions.identity()";
099    }
100  }
101
102  /**
103   * Returns a function which performs a map lookup. The returned function throws an {@link
104   * IllegalArgumentException} if given a key that does not exist in the map. See also {@link
105   * #forMap(Map, Object)}, which returns a default value in this case.
106   *
107   * <p>Note: if {@code map} is a {@link com.google.common.collect.BiMap BiMap} (or can be one), you
108   * can use {@link com.google.common.collect.Maps#asConverter Maps.asConverter} instead to get a
109   * function that also supports reverse conversion.
110   */
111  public static <K, V> Function<K, V> forMap(Map<K, V> map) {
112    return new FunctionForMapNoDefault<K, V>(map);
113  }
114
115  private static class FunctionForMapNoDefault<K, V> implements Function<K, V>, Serializable {
116    final Map<K, V> map;
117
118    FunctionForMapNoDefault(Map<K, V> map) {
119      this.map = checkNotNull(map);
120    }
121
122    @Override
123    public V apply(@Nullable K key) {
124      V result = map.get(key);
125      checkArgument(result != null || map.containsKey(key), "Key '%s' not present in map", key);
126      return result;
127    }
128
129    @Override
130    public boolean equals(@Nullable Object o) {
131      if (o instanceof FunctionForMapNoDefault) {
132        FunctionForMapNoDefault<?, ?> that = (FunctionForMapNoDefault<?, ?>) o;
133        return map.equals(that.map);
134      }
135      return false;
136    }
137
138    @Override
139    public int hashCode() {
140      return map.hashCode();
141    }
142
143    @Override
144    public String toString() {
145      return "Functions.forMap(" + map + ")";
146    }
147
148    private static final long serialVersionUID = 0;
149  }
150
151  /**
152   * Returns a function which performs a map lookup with a default value. The function created by
153   * this method returns {@code defaultValue} for all inputs that do not belong to the map's key
154   * set. See also {@link #forMap(Map)}, which throws an exception in this case.
155   *
156   * @param map source map that determines the function behavior
157   * @param defaultValue the value to return for inputs that aren't map keys
158   * @return function that returns {@code map.get(a)} when {@code a} is a key, or {@code
159   *         defaultValue} otherwise
160   */
161  public static <K, V> Function<K, V> forMap(Map<K, ? extends V> map, @Nullable V defaultValue) {
162    return new ForMapWithDefault<K, V>(map, defaultValue);
163  }
164
165  private static class ForMapWithDefault<K, V> implements Function<K, V>, Serializable {
166    final Map<K, ? extends V> map;
167    final V defaultValue;
168
169    ForMapWithDefault(Map<K, ? extends V> map, @Nullable V defaultValue) {
170      this.map = checkNotNull(map);
171      this.defaultValue = defaultValue;
172    }
173
174    @Override
175    public V apply(@Nullable K key) {
176      V result = map.get(key);
177      return (result != null || map.containsKey(key)) ? result : defaultValue;
178    }
179
180    @Override
181    public boolean equals(@Nullable Object o) {
182      if (o instanceof ForMapWithDefault) {
183        ForMapWithDefault<?, ?> that = (ForMapWithDefault<?, ?>) o;
184        return map.equals(that.map) && Objects.equal(defaultValue, that.defaultValue);
185      }
186      return false;
187    }
188
189    @Override
190    public int hashCode() {
191      return Objects.hashCode(map, defaultValue);
192    }
193
194    @Override
195    public String toString() {
196      // TODO(cpovirk): maybe remove "defaultValue=" to make this look like the method call does
197      return "Functions.forMap(" + map + ", defaultValue=" + defaultValue + ")";
198    }
199
200    private static final long serialVersionUID = 0;
201  }
202
203  /**
204   * Returns the composition of two functions. For {@code f: A->B} and {@code g: B->C}, composition
205   * is defined as the function h such that {@code h(a) == g(f(a))} for each {@code a}.
206   *
207   * @param g the second function to apply
208   * @param f the first function to apply
209   * @return the composition of {@code f} and {@code g}
210   * @see <a href="//en.wikipedia.org/wiki/Function_composition">function composition</a>
211   */
212  public static <A, B, C> Function<A, C> compose(Function<B, C> g, Function<A, ? extends B> f) {
213    return new FunctionComposition<A, B, C>(g, f);
214  }
215
216  private static class FunctionComposition<A, B, C> implements Function<A, C>, Serializable {
217    private final Function<B, C> g;
218    private final Function<A, ? extends B> f;
219
220    public FunctionComposition(Function<B, C> g, Function<A, ? extends B> f) {
221      this.g = checkNotNull(g);
222      this.f = checkNotNull(f);
223    }
224
225    @Override
226    public C apply(@Nullable A a) {
227      return g.apply(f.apply(a));
228    }
229
230    @Override
231    public boolean equals(@Nullable Object obj) {
232      if (obj instanceof FunctionComposition) {
233        FunctionComposition<?, ?, ?> that = (FunctionComposition<?, ?, ?>) obj;
234        return f.equals(that.f) && g.equals(that.g);
235      }
236      return false;
237    }
238
239    @Override
240    public int hashCode() {
241      return f.hashCode() ^ g.hashCode();
242    }
243
244    @Override
245    public String toString() {
246      // TODO(cpovirk): maybe make this look like the method call does ("Functions.compose(...)")
247      return g + "(" + f + ")";
248    }
249
250    private static final long serialVersionUID = 0;
251  }
252
253  /**
254   * Creates a function that returns the same boolean output as the given predicate for all inputs.
255   *
256   * <p>The returned function is <i>consistent with equals</i> (as documented at {@link
257   * Function#apply}) if and only if {@code predicate} is itself consistent with equals.
258   */
259  public static <T> Function<T, Boolean> forPredicate(Predicate<T> predicate) {
260    return new PredicateFunction<T>(predicate);
261  }
262
263  /** @see Functions#forPredicate */
264  private static class PredicateFunction<T> implements Function<T, Boolean>, Serializable {
265    private final Predicate<T> predicate;
266
267    private PredicateFunction(Predicate<T> predicate) {
268      this.predicate = checkNotNull(predicate);
269    }
270
271    @Override
272    public Boolean apply(@Nullable T t) {
273      return predicate.apply(t);
274    }
275
276    @Override
277    public boolean equals(@Nullable Object obj) {
278      if (obj instanceof PredicateFunction) {
279        PredicateFunction<?> that = (PredicateFunction<?>) obj;
280        return predicate.equals(that.predicate);
281      }
282      return false;
283    }
284
285    @Override
286    public int hashCode() {
287      return predicate.hashCode();
288    }
289
290    @Override
291    public String toString() {
292      return "Functions.forPredicate(" + predicate + ")";
293    }
294
295    private static final long serialVersionUID = 0;
296  }
297
298  /**
299   * Creates a function that returns {@code value} for any input.
300   *
301   * @param value the constant value for the function to return
302   * @return a function that always returns {@code value}
303   */
304  public static <E> Function<Object, E> constant(@Nullable E value) {
305    return new ConstantFunction<E>(value);
306  }
307
308  private static class ConstantFunction<E> implements Function<Object, E>, Serializable {
309    private final E value;
310
311    public ConstantFunction(@Nullable E value) {
312      this.value = value;
313    }
314
315    @Override
316    public E apply(@Nullable Object from) {
317      return value;
318    }
319
320    @Override
321    public boolean equals(@Nullable Object obj) {
322      if (obj instanceof ConstantFunction) {
323        ConstantFunction<?> that = (ConstantFunction<?>) obj;
324        return Objects.equal(value, that.value);
325      }
326      return false;
327    }
328
329    @Override
330    public int hashCode() {
331      return (value == null) ? 0 : value.hashCode();
332    }
333
334    @Override
335    public String toString() {
336      return "Functions.constant(" + value + ")";
337    }
338
339    private static final long serialVersionUID = 0;
340  }
341
342  /**
343   * Returns a function that always returns the result of invoking {@link Supplier#get} on {@code
344   * supplier}, regardless of its input.
345   *
346   * @since 10.0
347   */
348  @Beta
349  public static <T> Function<Object, T> forSupplier(Supplier<T> supplier) {
350    return new SupplierFunction<T>(supplier);
351  }
352
353  /** @see Functions#forSupplier*/
354  private static class SupplierFunction<T> implements Function<Object, T>, Serializable {
355
356    private final Supplier<T> supplier;
357
358    private SupplierFunction(Supplier<T> supplier) {
359      this.supplier = checkNotNull(supplier);
360    }
361
362    @Override
363    public T apply(@Nullable Object input) {
364      return supplier.get();
365    }
366
367    @Override
368    public boolean equals(@Nullable Object obj) {
369      if (obj instanceof SupplierFunction) {
370        SupplierFunction<?> that = (SupplierFunction<?>) obj;
371        return this.supplier.equals(that.supplier);
372      }
373      return false;
374    }
375
376    @Override
377    public int hashCode() {
378      return supplier.hashCode();
379    }
380
381    @Override
382    public String toString() {
383      return "Functions.forSupplier(" + supplier + ")";
384    }
385
386    private static final long serialVersionUID = 0;
387  }
388}