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