/* XXL: The eXtensible and fleXible Library for data processing Copyright (C) 2000-2011 Prof. Dr. Bernhard Seeger Head of the Database Research Group Department of Mathematics and Computer Science University of Marburg Germany This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; If not, see <http://www.gnu.org/licenses/>. http://code.google.com/p/xxl/ */ package xxl.core.functions; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * This class provides an abstract implementation of the interface Function. * In order to declare a function as an object of class AbstractFunction, the * invoke method has to be overridden. This method accepts both separate input * parameters and a typed list holding them. The output of invoke is an object * of the given return type. Simplified versions of invoke exists suitable for * functions with none, one or two input parameters. It is important to mention * that in general only one of the invoke methods has to be overridden. The * invocation of a function is then triggered by simply calling invoke. * * <p>In combination with the powerful mechanism of anonymous classes, it is * also possible to build higher-order functions which is known from functional * programming (e. g. Haskel). The method * {@link Functions#compose(Function, Function...) compose} shows how to * declare a function <tt>h</tt> which consists of * <tt>g o (f<sub>1</sub>,...,f<sub>n</sub>)</tt> where <tt>g</tt> is a * function with <tt>n</tt> arguments and * <tt>f<sub>1</sub>,...,f<sub>n</sub></tt> are functions with an equal number * of arguments. Note that compose provides the declaration of the function and * does not execute the function.</p> * * <p>Consider for example (see also the main-method) that you are interested * in building the function <tt>tan</tt> which can be build by composing * <tt>division</tt> and <tt>(sin, cos)</tt>. Function * <tt>div</tt>, <tt>sin</tt>, <tt>cos</tt>; * <code><pre> * // Initialization of your functional objects * ... * // Declaration of a new function * Function<Double, Double> tan = Functions.compose(div, sin, cos); * ... * // Execution of the new function * tan.invoke(x); * </pre></code> * * @param <P> the type of the function's parameters. * @param <R> the return type of the function. * @deprecated replaced by {@link Functional} */ @SuppressWarnings("serial") @Deprecated public abstract class AbstractFunction<P, R> implements Function<P, R>, Serializable { /** * Returns the result of the function as an object of the return type. This * method determines <code>arguments.size()</code> and calls the * appropriate invoke method (see below). The other invoke methods call * this method. This means, that the user either has to override this * method or one (!) of the other invoke methods. If <code>null</code> is * given as argument <code>invoke((P)null)</code> will be returned meaning * <code>invoke(P)</code> is needed to be overridden.</p> * * <p>Implementation: * <code><pre> * if (arguments == null) * return invoke((P)null); * switch (arguments.size()) { * case 0: * return invoke(); * case 1: * return invoke(arguments.get(0)); * case 2: * return invoke(arguments.get(0), arguments.get(1)); * default: * throw new IllegalStateException("R invoke(List<? super P>) has to be overridden! The number of arguments was " + arguments.size() + "."); * } * </pre></code></p> * * @param arguments a list of the arguments to the function. * @throws IllegalStateException if a list of arguments is given that contains 3 * or more arguments and the corresponding method * <code>R invoke(List<? extends P>)</code> has not been * overridden. * @return the function value is returned. */ public R invoke(List<? extends P> arguments) throws IllegalStateException { if (arguments == null) return invoke((P)null); switch (arguments.size()) { case 0: return invoke(); case 1: return invoke(arguments.get(0)); case 2: return invoke(arguments.get(0), arguments.get(1)); default: throw new IllegalStateException("R invoke(List<? super P>) has to be overridden! The number of arguments was " + arguments.size() + "."); } } /** * Returns the result of the function as an object of the result type. * * <p>Implementation: * <code><pre> * return invoke(new ArrayList<P>(0)); * </pre></code></p> * * @return the function value is returned. */ public R invoke() { return invoke(new ArrayList<P>(0)); } /** * Returns the result of the function as an object of the result type. * * <p>Implementation: * <code><pre> * return invoke(Arrays.asList(argument)); * </pre></code></p> * * @param argument the argument to the function. * @return the function value is returned. */ public R invoke(P argument) { return invoke(Arrays.asList(argument)); } /** * Returns the result of the function as an object of the result type. * * <p>Implementation: * <code><pre> * return invoke(Arrays.asList(argument0, argument1)); * </pre></code></p> * * @param argument0 the first argument to the function * @param argument1 the second argument to the function * @return the function value is returned */ public R invoke(P argument0, P argument1) { return invoke(Arrays.asList(argument0, argument1)); } }