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