package com.bigdata.btree.filter;
import java.util.Iterator;
import java.util.NoSuchElementException;
import com.bigdata.btree.IIndex;
import com.bigdata.btree.IRangeQuery;
import com.bigdata.btree.ITuple;
import com.bigdata.btree.ITupleIterator;
import cutthecrap.utils.striterators.FilterBase;
/**
* Visits all elements visited by the source iterator and removes those
* matching the filter.
* <p>
* Note: If you want to only visit those elements that are being removed,
* then apply a {@link TupleFilter} first and then stack the {@link TupleRemover}
* on top and make {@link #remove(Object)} always return <code>true</code>.
* Note that you MUST also specify {@link IRangeQuery#CURSOR} if the index
* is a local B+Tree since traversal with concurrent modification is
* otherwise not supported.
*
* @author <a href="mailto:thompsonbry@users.sourceforge.net">Bryan Thompson</a>
* @version $Id$
* @param <E>
*/
abstract public class TupleRemover<E> extends FilterBase implements ITupleFilter<E> {
/**
*
*/
private static final long serialVersionUID = 1L;
@SuppressWarnings("unchecked")
@Override
public ITupleIterator<E> filterOnce(final Iterator src, Object context) {
return new TupleRemover.Removerator<E>((ITupleIterator<E>) src,
context, this);
}
/**
* <code>true</code> iff the tuple should be removed from the source
* {@link IIndex}.
*
* @param e
* The tuple.
*/
abstract protected boolean remove(ITuple<E> e);
/**
* Implementation class.
*
* @author <a href="mailto:thompsonbry@users.sourceforge.net">Bryan
* Thompson</a>
* @version $Id$
* @param <E>
*/
private static class Removerator<E> implements ITupleIterator<E> {
/**
* The source iterator.
*/
private final ITupleIterator<E> src;
/**
* The context object (ignored).
*/
private final Object ctx;
/**
* The filter to be applied.
*/
private final TupleRemover<E> filter;
/**
* @param src
* @param filter
*/
public Removerator(final ITupleIterator<E> src, final Object context,
final TupleRemover<E> filter) {
this.src = src;
this.ctx = context;
this.filter = filter;
}
public boolean hasNext() {
return src.hasNext();
}
public ITuple<E> next() {
if (!hasNext())
throw new NoSuchElementException();
// the next value to be returned.
final ITuple<E> e = src.next();
if (filter.remove(e)) {
// Remove the visited element.
src.remove();
}
return e;
}
/**
* Note: Visited tuples which satisfy
* {@link TupleRemover#remove(Object)} will already have been removed
* from the source iterator. Attempting to remove them again using this
* method may cause an {@link IllegalStateException} to be thrown by the
* source iterator.
*/
public void remove() {
src.remove();
}
}
}