/* 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.util.List;
import xxl.core.predicates.Predicate;
/**
* A (recursive) functional for-loop.
*
* @param <P> the type of the function's parameters.
* @param <R> the return type of the function.
*/
public class For<P, R> extends DecoratorFunction<P, R> {
/**
* This class provides a Function that expects an Integer-Object as its
* input and returns the increment. This means, if
* <code>new Integer(n)</code> is the input-argument
* <code>new Integer(n+1)</code> is returned.
*/
@SuppressWarnings("serial")
public static class IntegerIncrement extends AbstractFunction<Integer, Integer> {
/**
* This instance can be used for getting a default instance of
* IntegerIncrement. It is similar to the <i>Singleton Design
* Pattern</i> (for further details see Creational Patterns, Prototype
* in <i>Design Patterns: Elements of Reusable Object-Oriented
* Software</i> by Erich Gamma, Richard Helm, Ralph Johnson, and John
* Vlissides) except that there are no mechanisms to avoid the
* creation of other instances of IntegerIncrement.
*/
public static final IntegerIncrement DEFAULT_INSTANCE = new IntegerIncrement();
/**
* Returns the increment of the given Integer-Object.
*
* @param argument Integer-Object to increment.
* @return a new Integer-Object representing the increment of the given
* argument.
*/
@Override
public Integer invoke(Integer argument) {
return argument + 1;
}
}
/**
* Constructs a new Object of this class.
*
* @param <T> the return type of the function <code>f1</code> and the
* parameter type of the function <code>newState</code>.
* @param predicate the Predicate that determines whether f1 is called
* recursively.
* @param f1 code to be executed if predicate returns true, general
* contract: has to return arguments for newState.
* @param f2 code to be executed if predicate returns false.
* @param newState computes new arguments for consequent call of f1.
*/
@SuppressWarnings("serial")
public <T> For(Predicate<? super P> predicate, final Function<? super P, ? extends T> f1, final Function<? super P, ? extends R> f2, final Function<? super T, ? extends P> newState) {
super(); //should be "super(new Iff..." (early bind of compiler prob)
function = new Iff<P, R>(
predicate,
new AbstractFunction<P, R>() {
@Override
public R invoke(List<? extends P> arguments) { //Function to be called if predicate returned true
return function.invoke( //recurse
newState.invoke( //compute newState, i.e. increment, use return value as argument for iff-Function
f1.invoke(arguments) //execute actual code and use return value as argument vor newState
)
);
}
},
f2 //Function to be called if predicate returned false
);
}
}