package simpledb;
import java.util.*;

/** 
 * Filter is an operator that implements a relational select.
 */
public class Filter implements DbIterator {
    private Predicate pred;
    private DbIterator child;
    
    /** 
     * Constructor accepts a predicate to apply and a child
     * operator to read tuples to filter from.
     *
     * @param p The predicate to filter tuples with
     * @param child The child operator
     */
    public Filter(Predicate p, DbIterator child) {
        this.pred = p;
        this.child = child;
    }

    public TupleDesc getTupleDesc() {
        return child.getTupleDesc();
    }

    public void open() 
	throws DbException, NoSuchElementException, TransactionAbortedException {
        child.open();
    }

    public void close() {
        child.close();
    }

    public void rewind() throws DbException, TransactionAbortedException {
        child.rewind();
    }

    /** 
     * DbIterator.getNext implementation.
     * Iterates over tuples from the child operator, applying the predicate
     * to them and returning those that pass the predicate (i.e. for which
     * the Predicate.filter() returns true.)
     *
     * @return The next tuple that passes the filter
     * @throws NoSuchElementException if there are no more tuples to filter
     * @see Predicate#filter
     */
    public Tuple getNext() 
	throws NoSuchElementException, TransactionAbortedException,
               DbException {
        // Get tuples from the child until we find one that satisfies
        // the predicate. If the child runs out of tuples, it will
        // throw a NoSuchElementException, which we pass on to the
        // caller.
        while (true) {
            Tuple t;
            
            try {
                t = child.getNext();
            } catch (NoSuchElementException e) {
                throw e;
            }

            if (pred.filter(t)) {
                return t;
            }
        }
    }
}
