All Downloads are FREE. Search and download functionalities are using the official Maven repository.

java.util.function.Functions Maven / Gradle / Ivy

/* Copyright (c) The m-m-m Team, Licensed under the Apache License, Version 2.0
 * http://www.apache.org/licenses/LICENSE-2.0 */
package java.util.function;

import java.lang.reflect.Constructor;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.Map;

/**
 * This is the back-port for the according class of Java 1.8+.
 * 
 * @author Joerg Hohwiller (hohwille at users.sourceforge.net)
 * @since 1.0.0
 */
public final class Functions {

  /**
   * Construction prohibited.
   */
  private Functions() {

  }

  /**
   * @param  is the generic type of the input and result of the function.
   * @return a function whose {@link Function#apply(Object) apply} method returns the provided input.
   */
  public static  Function identity() {

    return new Function() {

      @Override
      public T apply(T t) {

        return t;
      }
    };
  }

  /**
   * Returns a function which performs the first function followed by the second function.
   * 
   * @param  is the generic type for inputs to the first function.
   * @param  is the generic type for results from first function and inputs to the second function. May be
   *        the same type as {@code }.
   * @param  Type for results from the second function. May be the same type as * {@code }.
   * @param first Initial function from {@code } to {@code }.
   * @param second additional function from {@code } to {@code }.
   * @return a function which performs the first function followed by the second function.
   */
  public static  Function chain(final Function first,
      final Function second) {

    if ((first == null) || (second == null)) {
      throw new NullPointerException();
    }

    return new Function() {

      @Override
      public R apply(T t) {

        return second.apply(first.apply(t));
      }
    };
  }

  /**
   * Returns a constant output regardless of input.
   * 
   * @param  is the generic type of the (ignored) input to the function.
   * @param  is the generic type of the result.
   * 
   * @param constant The value to be returned by the {@link Function#apply(Object) apply} method.
   * @return a {@link Function} whose {@link Function#apply(Object) apply} method provides a constant result.
   */
  public static  Function constant(final R constant) {

    return new Function() {

      @Override
      public R apply(T t) {

        return constant;
      }
    };
  }

  /**
   * A function that substitutes a single input value with a specified replacement. Input values are compared
   * using {@code equals()}.
   * 
   * @param  The type of values.
   * @param subOut The input value to be substituted out.
   * @param subIn The replacement value for matching inputs.
   * @return a {@link Function} that substitutes a single input value with a specified replacement.
   */
  public static  Function substitute(final T subOut, final T subIn) {

    return new Function() {

      @Override
      public T apply(T t) {

        // return (a == b) || (a != null && a.equals(b));
        if ((subOut == t) || ((subOut != null) && (subOut.equals(t)))) {
          return subIn;
        }
        return t;
      }
    };
  }

  /**
   * Returns a new instance of {@code } constructed with provided {@code }.
   * 
   * @param  Type of output values from mapping
   * @param  Type of input values to mapping
   * @param clazzT The {@code Class} which defines objects of type {@code }
   * @param clazzR The {@code Class} which defines objects of type {@code }
   * @return a {@link Function} which creates instances of {@code } using {@code } as the constructor
   *         parameter.
   */
  public static  Function instantiate(Class clazzT, Class clazzR) {

    if ((clazzT == null) || (clazzR == null)) {
      throw new NullPointerException();
    }

    final Constructor constructor;
    try {
      constructor = clazzR.getConstructor(clazzT);
    } catch (NoSuchMethodException noConstructor) {
      throw new IllegalArgumentException("no constructor for " + clazzR.getSimpleName() + "(" + clazzT.getSimpleName()
          + ")", noConstructor);
    }

    return new Function() {

      /**
       * {@inheritDoc}
       */
      @Override
      public R apply(T t) {

        try {
          return constructor.newInstance(t);
        } catch (Exception ex) {
          throw new UndeclaredThrowableException(ex);
        }
      }
    };
  }

  /**
   * Returns a function which maps inputs according to the provided mapping. Attempting to apply a value not
   * from the given map will cause an {@code IllegalArgumentException} to be thrown. A copy is
   * not made of the map. Care should be taken to avoid changes to the map during operation
   * may produce results which violate the {@code apply} method contract.
   * 
   * @param  output type from mapping operation
   * @param  input type to mapping operation
   * @param map provides the mappings from {@code } to {@code }
   * @return the {@link Function} as described above.
   */
  public static  Function forMap(final Map map) {

    if (map == null) {
      throw new NullPointerException();
    }

    return new Function() {

      @Override
      public R apply(T t) {

        if (map.containsKey(t)) {
          return map.get(t);
        } else {
          throw new IllegalArgumentException("unmappable  : " + t);
        }
      }
    };
  }

  /**
   * Returns a function which maps inputs according to the provided mapping. The provided default value is
   * returned for all {@code } keys not found in the map. A copy is not made of the apply
   * and care should be taken to avoid changes to the apply during operation may produce results which violate
   * the {@code apply} method contract.
   * 
   * @param  input type to mapping function
   * @param  output type from mapping function
   * @param  output type from mapping function
   * @param mapping provides the mappings from {@code } to {@code }
   * @param defaultValue the value returned by {@code apply} method for {@code } values not contained in
   *        the provided map.
   * @return the {@link Function} as described above.
   */
  public static  Function forMap(final Map mapping, final RR defaultValue) {

    if (mapping == null) {
      throw new NullPointerException();
    }

    return new Function() {

      /**
       * {@inheritDoc}
       */
      @Override
      public R apply(T t) {

        R result = mapping.get(t);
        if ((result != null) || (mapping.containsKey(t))) {
          return result;
        } else {
          return defaultValue;
        }
      }
    };
  }

  /**
   * Map according to the provided predicate. Two output values are provided {@code forTrue} is returned if
   * the predicate returns {@code true} otherwise the {@code forFalse} value is returned.
   * 
   * @param  input type to mapping function
   * @param  output type from mapping function
   * @param predicate decides which value {@code apply} method should return
   * @param forTrue value to be returned for {@code true} predicate results
   * @param forFalse value to be returned for {@code false} predicate results
   * @return a Function whose {@code apply} method provides results according to the provided predicate.
   */
  public static  Function forPredicate(final Predicate predicate, final R forTrue,
      final R forFalse) {

    if (predicate == null) {
      throw new NullPointerException();
    }

    return new Function() {

      @Override
      public R apply(T t) {

        return predicate.test(t) ? forTrue : forFalse;
      }
    };
  }
}