package cc.mallet.pipe;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import cc.mallet.pipe.iterator.EmptyInstanceIterator;
import cc.mallet.types.Instance;
/** A Pipe that works like a rule list. Evaluate predicate() on each Pipe in the array;
* the first one that returns true, call that one ("the called Pipe"), and ignore the
* remainder in the array. The called Pipe will then get control of the source
* InstanceIterator until it produces an Instance---in other words it will be able to call
* next() on the source Pipe as often as necessary to produce an Instance.
* You must be very careful that none of the iterators from Pipes in the rule list buffer
* any Instances---in other words they shouldn't call next() to pre-gather any Instances
* they they themselves don't consume and process immediately. Otherwise, Instances
* that should have been processed by some other constituent Pipe could get lost in
* this buffering process.
* @author Andrew McCallum <mccallum@cs.umass.edu> */
@ Deprecated
//Implementation not yet complete, and seems quite dangerous and error-prone.
public class BranchingPipe extends Pipe {
ArrayList<Pipe> pipes;
public BranchingPipe ()
{
this.pipes = new ArrayList<Pipe> ();
}
public BranchingPipe (Pipe[] pipes)
{
this.pipes = new ArrayList<Pipe> (pipes.length);
for (int i = 0; i < pipes.length; i++)
this.pipes.add (pipes[i]);
}
public BranchingPipe (Collection<Pipe> pipeList)
{
pipes = new ArrayList<Pipe> (pipeList);
}
private class PeekingInstanceIterator implements Iterator<Instance> {
Iterator<Instance> source;
Instance nextInstance = null;
public PeekingInstanceIterator (Iterator<Instance> source) {
this.source = source;
}
public boolean hasNext () { return source.hasNext(); }
public Instance peekNext () {
if (nextInstance == null && !hasNext())
return null;
else if (nextInstance == null)
nextInstance = next();
return nextInstance;
}
public Instance next () {
if (nextInstance != null) {
Instance tmp = nextInstance;
nextInstance = null;
return tmp;
} else {
return source.next();
}
}
public void remove () { throw new IllegalStateException ("This Iterator<Instance> does not support remove()."); }
}
private class GateKeepingInstanceIterator implements Iterator<Instance>
{
PeekingInstanceIterator source;
Pipe testingPipe;
public GateKeepingInstanceIterator (PeekingInstanceIterator source, Pipe testingPipe) {
this.source = source;
this.testingPipe = testingPipe;
}
public Instance next () {
// Make sure this is not an Instance we were supposed to skip.
assert (testingPipe.precondition(source.peekNext()));
return source.next();
}
public boolean hasNext () {
return source.hasNext() && testingPipe.precondition(source.peekNext());
}
public void remove () { throw new IllegalStateException ("This Iterator<Instance> does not support remove()."); }
}
private class BranchingInstanceIterator implements Iterator<Instance>
{
PeekingInstanceIterator source;
ArrayList<Iterator<Instance>> iterators;
public BranchingInstanceIterator (PeekingInstanceIterator source) {
this.source = new PeekingInstanceIterator (source);
this.iterators = new ArrayList<Iterator<Instance>>(pipes.size());
for (Pipe p : pipes)
iterators.add (new GateKeepingInstanceIterator (source, p));
}
public boolean hasNext () { return source.hasNext(); }
public Instance next() {
Instance input = source.peekNext();
for (int i = 0; i < pipes.size(); i++) {
if (pipes.get(i).precondition(input)) {
return iterators.get(i).next();
}
}
throw new IllegalStateException ("Next Instance satisfied none of the branches' preconditions.");
}
/** Return the @link{Pipe} that processes @link{Instance}s going through this iterator. */
public Pipe getPipe () { return null; }
public Iterator<Instance> getSourceIterator () { return source; }
public void remove () { throw new IllegalStateException ("This Iterator<Instance> does not support remove()."); }
}
public Iterator<Instance> newIteratorFrom (Iterator<Instance> source)
{
if (pipes.size() == 0)
return source;
Iterator<Instance> ret = pipes.get(0).newIteratorFrom(source);
for (int i = 1; i < pipes.size(); i++)
ret = pipes.get(i).newIteratorFrom(ret);
return ret;
}
private static void test () {
new BranchingPipe (new Pipe[] {
new CharSequence2TokenSequence("\\w*") {
public boolean skipIfFalse (Instance inst) { return ! (inst instanceof CharSequence); }
}
});
}
}