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

org.opencastproject.util.data.functions.Functions Maven / Gradle / Ivy

There is a newer version: 16.7
Show newest version
/*
 * Licensed to The Apereo Foundation under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 *
 * The Apereo Foundation licenses this file to you under the Educational
 * Community License, Version 2.0 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a copy of the License
 * at:
 *
 *   http://opensource.org/licenses/ecl2.txt
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
 * License for the specific language governing permissions and limitations under
 * the License.
 *
 */


package org.opencastproject.util.data.functions;

import static org.opencastproject.util.data.Either.left;
import static org.opencastproject.util.data.Either.right;

import org.opencastproject.util.data.Effect;
import org.opencastproject.util.data.Effect0;
import org.opencastproject.util.data.Either;
import org.opencastproject.util.data.Function;
import org.opencastproject.util.data.Function0;
import org.opencastproject.util.data.Function2;
import org.opencastproject.util.data.Predicate;

/** General purpose functions, especially function transformations. */
public final class Functions {
  private Functions() {
  }

  /** Function composition: f . g = f(g(x)) = o(f, g) */
  public static  Function o(final Function f,
          final Function g) {
    return new Function() {
      @Override
      public C apply(A a) {
        return f.apply(g.apply(a));
      }
    };
  }

  /** Function composition: f . g = f(g) = o(f, g) */
  public static  Function0 o(final Function f, final Function0 g) {
    return new Function0() {
      @Override
      public B apply() {
        return f.apply(g.apply());
      }
    };
  }

  /** Left to right composition: f then g = g(f(x)) */
  public static  Function then(final Function f,
          final Function g) {
    return new Function() {
      @Override
      public C apply(A a) {
        return g.apply(f.apply(a));
      }
    };
  }

  /** Left to right composition: f then g = g(f) */
  public static  Function0 then(final Function0 f, final Function g) {
    return new Function0() {
      @Override
      public B apply() {
        return g.apply(f.apply());
      }
    };
  }

  /** Apply f and ignore its result, then apply g. */
  public static  Function0 then(final Function0 f, final Function0 g) {
    return new Function0() {
      @Override
      public B apply() {
        f.apply();
        return g.apply();
      }
    };
  }

  /**
   * Create a new function from f decorated with an exception transformer. Any exception that occurs during
   * application of f is passed to transformer whose return value is then being thrown.
   */
  public static  Function rethrow(final Function f,
          final Function transformer) {
    return new Function() {
      @Override
      public B apply(A a) {
        try {
          return f.apply(a);
        } catch (Exception e) {
          return chuck(transformer.apply(e));
        }
      }
    };
  }

  /**
   * Create a new function from f decorated with an exception handler. Any exception that occurs during
   * application of f is passed to handler whose return value is then being returned.
   */
  public static  Function handle(final Function f,
          final Function handler) {
    return new Function() {
      @Override
      public B apply(A a) {
        try {
          return f.apply(a);
        } catch (Exception e) {
          return handler.apply(e);
        }
      }
    };
  }

  /**
   * Create a new function from f decorated with an exception handler. The new function either returns the
   * value of f or in case of an exception being thrown on the application of f the return
   * value of handler.
   */
  public static  Function> either(final Function f,
          final Function handler) {
    return new Function>() {
      @Override
      public Either apply(A a) {
        try {
          B b = f.apply(a);
          return right(b);
        } catch (Exception e) {
          C c = handler.apply(e);
          return left(c);
        }
      }
    };
  }

  /** Curry a function of arity 2. */
  // todo rename since its actually partial application
  public static  Function curry(final Function2 f, final A a) {
    return new Function() {
      @Override
      public C apply(B b) {
        return f.apply(a, b);
      }
    };
  }

  /** Curry a function of arity 2. (a, b) -gt; c =gt; a -gt; b -gt; c */
  public static  Function> curry(final Function2 f) {
    return new Function>() {
      @Override
      public Function apply(final A a) {
        return new Function() {
          @Override
          public C apply(B b) {
            return f.apply(a, b);
          }
        };
      }
    };
  }

  /** Uncurry to a function of arity 2. a -gt; b -gt; c =gt; (a, b) -gt; c */
  public static  Function2 uncurry(final Function> f) {
    return new Function2() {
      @Override
      public C apply(A a, B b) {
        return f.apply(a).apply(b);
      }
    };
  }

  /** Curry a function of arity 1. */
  public static  Function0 curry(final Function f, final A a) {
    return new Function0() {
      @Override
      public B apply() {
        return f.apply(a);
      }
    };
  }

  /** Curry a function of arity 1. */
  public static  Function> curry(final Function f) {
    return new Function>() {
      @Override
      public Function0 apply(final A a) {
        return new Function0() {
          @Override
          public B apply() {
            return f.apply(a);
          }
        };
      }
    };
  }

  /** Flip arguments of a function of arity 2. */
  public static  Function2 flip(final Function2 f) {
    return new Function2() {
      @Override
      public C apply(B b, A a) {
        return f.apply(a, b);
      }
    };
  }

  /** Turn a function into an effect by discarding its result. */
  public static  Effect toEffect(final Function f) {
    return new Effect() {
      @Override
      protected void run(A a) {
        f.apply(a);
      }
    };
  }

  public static  Predicate toPredicate(final Function f) {
    return new Predicate() {
      @Override
      public Boolean apply(A a) {
        return f.apply(a);
      }
    };
  }

  /** Noop effect. */
  public static final Effect0 noop = new Effect0() {
    @Override
    protected void run() {
    }
  };

  /** Identity function. */
  public static  Function identity() {
    return new Function() {
      @Override
      public A apply(A a) {
        return a;
      }
    };
  }

  /**
   * Identity function. The type is based on the type of the example object to save some nasty typing, e.g.
   * Function.<Integer>identity() vs. identity(0)
   *
   * Please note that this constructor is only due to Java's insufficient type inference.
   */
  public static  Function identity(A example) {
    return identity();
  }

  /**
   * Identity function.
   *
   * @param clazz
   *          to describe the functions's type
   */
  public static  Function identity(Class clazz) {
    return identity();
  }

  /** Create an effect that runs its argument. */
  public static final Effect run = new Effect() {
    @Override
    protected void run(Effect0 e) {
      e.apply();
    }
  };

  /** Pure functions are covariant in their result type. */
  public static  Function co(Function f) {
    return (Function) f;
  }

  /** Pure functions are contravariant in their argument type. */
  public static  Function contra(Function f) {
    return (Function) f;
  }

  /** Pure functions are covariant in their result type and contravariant in their argument type. */
  public static  Function variant(Function f) {
    return (Function) f;
  }

  private static  A castGeneric(Throwable t) throws T {
    // The cast to T does not happen here but _after_ returning from the method at _assignment_ time
    // But since there is no variable assignment. The Throwable is just thrown.
    throw (T) t;
  }

  /**
   * Throw a checked exception like a RuntimeException removing any needs to declare a throws clause.
   *
   * This technique has been described by James Iry at
   * http://james-iry.blogspot.de/2010/08/on-removing-java-checked-exceptions-by.html
   */
  public static  A chuck(Throwable t) {
    return Functions. castGeneric(t);
  }

  /** Convert function f into a guava function. */
  public static  com.google.common.base.Function toGuava(final Function f) {
    return new com.google.common.base.Function() {
      @Override
      public B apply(A a) {
        return f.apply(a);
      }
    };
  }

}