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 com.google.common.annotations.GwtIncompatible;
023import com.google.common.annotations.J2ktIncompatible;
024import java.io.Serializable;
025import java.util.Map;
026import org.jspecify.annotations.Nullable;
027
028/**
029 * Static utility methods pertaining to {@code com.google.common.base.Function} instances; see that
030 * class for information about migrating to {@code java.util.function}.
031 *
032 * <p>All methods return serializable functions as long as they're given serializable parameters.
033 *
034 * <p>See the Guava User Guide article on <a
035 * href="https://github.com/google/guava/wiki/FunctionalExplained">the use of {@code Function}</a>.
036 *
037 * @author Mike Bostock
038 * @author Jared Levy
039 * @since 2.0
040 */
041@GwtCompatible
042public final class Functions {
043  private Functions() {}
044
045  /**
046   * A function equivalent to the method reference {@code Object::toString}, for users not yet using
047   * Java 8. The function simply invokes {@code toString} on its argument and returns the result. It
048   * throws a {@link NullPointerException} on null input.
049   *
050   * <p><b>Warning:</b> The returned function may not be <i>consistent with equals</i> (as
051   * documented at {@link Function#apply}). For example, this function yields different results for
052   * the two equal instances {@code ImmutableSet.of(1, 2)} and {@code ImmutableSet.of(2, 1)}.
053   *
054   * <p><b>Warning:</b> as with all function types in this package, avoid depending on the specific
055   * {@code equals}, {@code hashCode} or {@code toString} behavior of the returned function. A
056   * future migration to {@code java.util.function} will not preserve this behavior.
057   *
058   * <p><b>Java 8+ users:</b> use the method reference {@code Object::toString} instead. In the
059   * future, when this class requires Java 8, this method will be deprecated. See {@link Function}
060   * for more important information about the Java 8+ transition.
061   */
062  public static Function<Object, String> toStringFunction() {
063    return ToStringFunction.INSTANCE;
064  }
065
066  // enum singleton pattern
067  private enum ToStringFunction implements Function<Object, String> {
068    INSTANCE;
069
070    @Override
071    public String apply(Object o) {
072      checkNotNull(o); // eager for GWT.
073      return o.toString();
074    }
075
076    @Override
077    public String toString() {
078      return "Functions.toStringFunction()";
079    }
080  }
081
082  /**
083   * Returns the identity function.
084   *
085   * <p><b>Discouraged:</b> Prefer using a lambda like {@code v -> v}, which is shorter and often
086   * more readable.
087   */
088  // implementation is "fully variant"; E has become a "pass-through" type
089  @SuppressWarnings("unchecked")
090  public static <E extends @Nullable Object> Function<E, E> identity() {
091    return (Function<E, E>) IdentityFunction.INSTANCE;
092  }
093
094  // enum singleton pattern
095  private enum IdentityFunction implements Function<@Nullable Object, @Nullable Object> {
096    INSTANCE;
097
098    @Override
099    public @Nullable Object apply(@Nullable 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(@Nullable 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    @GwtIncompatible @J2ktIncompatible 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(@Nullable 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    @GwtIncompatible @J2ktIncompatible 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(@Nullable 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    @GwtIncompatible @J2ktIncompatible 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  /**
299   * @see Functions#forPredicate
300   */
301  private static class PredicateFunction<T extends @Nullable Object>
302      implements Function<T, Boolean>, Serializable {
303    private final Predicate<T> predicate;
304
305    private PredicateFunction(Predicate<T> predicate) {
306      this.predicate = checkNotNull(predicate);
307    }
308
309    @Override
310    public Boolean apply(@ParametricNullness T t) {
311      return predicate.apply(t);
312    }
313
314    @Override
315    public boolean equals(@Nullable Object obj) {
316      if (obj instanceof PredicateFunction) {
317        PredicateFunction<?> that = (PredicateFunction<?>) obj;
318        return predicate.equals(that.predicate);
319      }
320      return false;
321    }
322
323    @Override
324    public int hashCode() {
325      return predicate.hashCode();
326    }
327
328    @Override
329    public String toString() {
330      return "Functions.forPredicate(" + predicate + ")";
331    }
332
333    @GwtIncompatible @J2ktIncompatible private static final long serialVersionUID = 0;
334  }
335
336  /**
337   * Returns a function that ignores its input and always returns {@code value}.
338   *
339   * <p><b>Java 8+ users:</b> use the lambda expression {@code o -> value} instead.
340   *
341   * @param value the constant value for the function to return
342   * @return a function that always returns {@code value}
343   */
344  public static <E extends @Nullable Object> Function<@Nullable Object, E> constant(
345      @ParametricNullness E value) {
346    return new ConstantFunction<>(value);
347  }
348
349  private static class ConstantFunction<E extends @Nullable Object>
350      implements Function<@Nullable Object, E>, Serializable {
351    @ParametricNullness private final E value;
352
353    public ConstantFunction(@ParametricNullness E value) {
354      this.value = value;
355    }
356
357    @Override
358    @ParametricNullness
359    public E apply(@Nullable Object from) {
360      return value;
361    }
362
363    @Override
364    public boolean equals(@Nullable Object obj) {
365      if (obj instanceof ConstantFunction) {
366        ConstantFunction<?> that = (ConstantFunction<?>) obj;
367        return Objects.equal(value, that.value);
368      }
369      return false;
370    }
371
372    @Override
373    public int hashCode() {
374      return (value == null) ? 0 : value.hashCode();
375    }
376
377    @Override
378    public String toString() {
379      return "Functions.constant(" + value + ")";
380    }
381
382    @GwtIncompatible @J2ktIncompatible private static final long serialVersionUID = 0;
383  }
384
385  /**
386   * Returns a function that ignores its input and returns the result of {@code supplier.get()}.
387   *
388   * <p><b>Java 8+ users:</b> use the lambda expression {@code o -> supplier.get()} instead.
389   *
390   * @since 10.0
391   */
392  public static <F extends @Nullable Object, T extends @Nullable Object> Function<F, T> forSupplier(
393      Supplier<T> supplier) {
394    return new SupplierFunction<>(supplier);
395  }
396
397  /**
398   * @see Functions#forSupplier
399   */
400  private static class SupplierFunction<F extends @Nullable Object, T extends @Nullable Object>
401      implements Function<F, T>, Serializable {
402
403    private final Supplier<T> supplier;
404
405    private SupplierFunction(Supplier<T> supplier) {
406      this.supplier = checkNotNull(supplier);
407    }
408
409    @Override
410    @ParametricNullness
411    public T apply(@ParametricNullness F input) {
412      return supplier.get();
413    }
414
415    @Override
416    public boolean equals(@Nullable Object obj) {
417      if (obj instanceof SupplierFunction) {
418        SupplierFunction<?, ?> that = (SupplierFunction<?, ?>) obj;
419        return this.supplier.equals(that.supplier);
420      }
421      return false;
422    }
423
424    @Override
425    public int hashCode() {
426      return supplier.hashCode();
427    }
428
429    @Override
430    public String toString() {
431      return "Functions.forSupplier(" + supplier + ")";
432    }
433
434    @GwtIncompatible @J2ktIncompatible private static final long serialVersionUID = 0;
435  }
436}