/* 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.util.List; import xxl.core.cursors.Subquery; /** * This class provides a prototypical implementation of the all-predicate. When * the <code>invoke</code> method of this class is called, the given arguments * will be applied to the subquery and it will be checked if all of the objects * the subquery delivers satisfy the check condition. * * <p>For example, consider the implementation of the query: * <pre> * SELECT (Integer2) * FROM Cursor 2 * WHERE ALL Integer2 > (SELECT Integer1 * FROM Cursor 1) * </pre> * by using an <code>AllPredicate</code> instance * <code><pre> * System.out.println("Cursor 1: integers 11 to 15"); * Cursor<Integer> cursor1 = Cursors.wrap(new Enumerator(11,16)); * * System.out.println("Cursor 2: integers 9 to 19"); * Cursor<Integer> cursor2 = Cursors.wrap(new Enumerator(9,20)); * * Predicate<Integer> pred = new Less<Integer>(new ComparableComparator<Integer>()); * * Subquery<Integer> sub = new Subquery<Integer>(cursor1, null, null); * * Predicate<Integer> all0 = new AllPredicate<Integer>(sub, pred, Arrays.asList(1)); * * Filter<Integer> cursor = new Filter<Integer>(cursor2, all0); * * System.out.println("Cursor: result"); * * Cursors.println(cursor); * </pre></code> * * @param <P> the type of the predicate's parameters. */ public class AllPredicate<P> extends AbstractPredicate<P> { /** * The subquery used in the all-predicate. */ protected Subquery<P> subquery; /** * The check condition of the all-predicate. */ protected BindingPredicate<P> checkCondition; /** * The indices to the positions where the free variable emerges in the * check condition. */ protected List<Integer> checkBindIndices; /** * Creates a new all-predicate. When the <code>invoke</code> method is * called, the given arguments will be applied to the subquery and it will * be checked if all of the objects the subquery delivers satisfy the check * condition. * * @param subquery the subquery used in the all-predicate. * @param checkCondition the check condition of the all-predicate. * @param checkBindIndices the Indices to the positions where the free * variable emerges in the check condition. */ public AllPredicate(Subquery<P> subquery, Predicate<? super P> checkCondition, List<Integer> checkBindIndices) { this.subquery = subquery; this.checkCondition = new BindingPredicate<P>(checkCondition); this.checkBindIndices = checkBindIndices; } /** * Set the subquery of the all-predicate. * * @param subquery the subquery used in the all-predicate. */ public void setSubquery(Subquery<P> subquery) { this.subquery = subquery; } /** * Set the check condition of the all-predicate. * * @param checkCondition the check condition of the all-predicate. * @param checkBindIndices the Indices to the positions where the free * variable emerges in the check condition. */ public void setCheckCondition(Predicate<? super P> checkCondition, List<Integer> checkBindIndices) { this.checkCondition = new BindingPredicate<P>(checkCondition); this.checkBindIndices = checkBindIndices; } /** * When the <code>invoke</code> method is called, the given arguments will * be applied to the subquery and it will be checked if all of the objects * the subquery delivers satisfy the check condition. * * @param arguments the arguments to be applied to the underlying * predicate. * @return the result of the underlying predicate's <code>invoke</code> * method that is called with applied arguments. */ @Override public boolean invoke(List<? extends P> arguments) { boolean result = true; if (arguments == null) return invoke((P)null); subquery.bind(arguments); subquery.reset(); checkCondition.setBinds(checkBindIndices, arguments); if (!subquery.hasNext()) return false; while (subquery.hasNext() && result) if (!checkCondition.invoke(subquery.next())) result = false; while (subquery.hasNext()) subquery.next(); return result; } }