/* 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.predicates; 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 Predicate. * Predicates are highly related to * {@link xxl.core.functions.Function functions}. Like functions, predicates * provide a set of <code>invoke</code> methods that can be used to evaluate * the predicate. For providing predicates with and without parameters, this * class contains invoke methods with zero, one and two arguments and with a * typed list of arguments. The <code>invoke</code> methods call themselves in * a recursive manner. That means when using the default implementation the * <code>invoke</code> method with zero, one or two arguments calls the * <code>invoke</code> method with a typed list containing the arguments * and the other way round (see appropriate invoke methods). For this reason, * an <code>invoke</code> method with the desired signature has to be overridden * in order to declare a predicate as an object of class Predicate. * * <p>But in contrast with functions, predicates do not return the result of * their evaluation as an object (that must be cast to a <code>Boolean</code> * object for getting the correct result), but as a primitive * <code>boolean</code> value.</p> * * <p>A first example shows how to declare a tautology, i.e. a predicate that * always returns <code>true</code>: * <code><pre> * Predicate<Object> tautology = new Predicate<Object>() { * public boolean invoke(List<? extends Object> arguments) { * return true; * } * }; * </pre></code> * In this example, the <code>invoke</code> method with a list of objects as * argument has been overwritten. Thanks to the recursive default * implementation of the <code>invoke</code> methods, every <code>invoke</code> * method calls the overwritten method and the overwritten method itself breaks * the recursion.</p> * * <p>A second example shows how to declare a predicate implementing the * logical statement '<code>n is even</code>': * <code><pre> * Predicate<Integer> even = new Predicate<Integer>() { * public boolean invoke(Integer n) { * return n % 2 == 0; * } * }; * </pre></code> * In this example, the <code>invoke</code> method with one argument has been * overwritten. This method guarantees the specification of the parameter * <code>n</code> that is needed for the evaluation of the predicate. Thanks to * the recursive default implementation it is all the same whether the user * calls <code>even.invoke(n)</code> or * <code>even.invoke(Arrays.asList(n))</code>. Note that default * implementations of this class are still available. Therefore a call to * <code>even.invoke()</code> will cause an infinite recursive loop.</p> * * @param <P> the type of the predicate's parameters. */ public abstract class AbstractPredicate<P> implements Predicate<P>, Serializable { /** * Returns the result of the predicate as a primitive boolean value. This * method determines <code>arguments.size()</code> and calls the * appropriate <code>invoke</code> method (see below). The other * <code>invoke</code> methods call this method. This means, that the user * either has to override this method or at least one (!) of the other * <code>invoke</code> methods. The following listing shows the exact * implementation of this method: * <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("boolean invoke(List<? extends P> arguments) has to be overridden! The number of arguments was " + arguments.size() + "."); * } * </pre></code> * * @param arguments the arguments to the predicate. * @return the result of the predicate as a primitive boolean value. * @throws IllegalStateException if an object array with length≥3 is given * and the corresponding <code>invoke</code> method * (<code>boolean invoke (List<? extends P>)</code>) has not * been overridden. */ public boolean 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("boolean invoke(List<? extends P> arguments) has to be overridden! The number of arguments was "+arguments.size()+"."); } } /** * Returns the result of the predicate as a primitive boolean value. This * method calls the <code>invoke</code> method working on lists with an * empty list (see below). This means, that the user has to override this * method to create a predicate without any argument. The following listing * shows the exact implementation of this method: * <code><pre> * return invoke(new ArrayList<P>(0)); * </pre></code> * * @return the result of the predicate as a primitive boolean value. */ public boolean invoke() { return invoke(new ArrayList<P>(0)); } /** * Returns the result of the predicate as a primitive boolean value. This * method calls the <code>invoke</code> method working on lists with a list * containing the given argument (see below). This means, that the user has * to override this method to create a predicate with one argument. The * following listing shows the exact implementation of this method: * <code><pre> * return invoke(Arrays.asList(argument)); * </pre></code> * * @param argument the argument to the predicate. * @return the result of the predicate as a primitive boolean value. */ public boolean invoke(P argument) { return invoke(Arrays.asList(argument)); } /** * Returns the result of the predicate as a primitive boolean value. This * method calls the <code>invoke</code> method working on lists with a list * containing the given arguments (see below). This means, that the user * has to override this method to create a predicate with two arguments. * The following listing shows the exact implementation of this method: * <code><pre> * return invoke(Arrays.asList(argument0, argument1)); * </pre></code> * * @param argument0 the first argument to the predicate. * @param argument1 the second argument to the predicate. * @return the result of the predicate as a primitive boolean value. */ public boolean invoke(P argument0, P argument1) { return invoke(Arrays.asList(argument0, argument1)); } }