package com.tinkerpop.pipes;

import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.ArrayList;

/**
 * An AbstractPipe provides most of the functionality that is repeated in every instance of a Pipe.
 * Any subclass of AbstractPipe should simply implement processNextStart(). The standard model is
 * <pre>
 * protected E processNextStart() throws NoSuchElementException {
 * S s = this.starts.next();
 * E e = // do something with the S to yield an E
 * return e;
 * }
 * </pre>
 * If the current incoming S is not to be emitted and there are no other S objects to process and emit, then throw a NoSuchElementException.
 *
 * @author Marko A. Rodriguez (http://markorodriguez.com)
 */
public abstract class AbstractPipe<S, E> implements Pipe<S, E> {

    protected Iterator<S> starts;
    private E nextEnd;
    private E currentEnd;
    private boolean available = false;
    protected boolean ensurePipeStarts = true;

    public void setStarts(final Pipe<?, S> starts) {
        this.starts = starts;
    }

    public void setStarts(final Iterator<S> starts) {
        if (ensurePipeStarts) {
            IdentityPipe<S> pipe = new IdentityPipe<S>();
            pipe.setStarts(starts);
            this.starts = pipe;
        } else {
            this.starts = starts;
        }
    }

    public void setStarts(final Iterable<S> starts) {
        this.setStarts(starts.iterator());
    }

    public ArrayList path() {
        if (this.starts instanceof Path) {
            Path path = (Path)this.starts;
            ArrayList pathElements = path.path();
            if (pathElements.get(pathElements.size() - 1) != this.currentEnd) {
              pathElements.add(this.currentEnd);
            }
            return pathElements;
        } else {
            ArrayList pathElements = new ArrayList();
            pathElements.add(this.currentEnd);
            return pathElements;
        }
    }

    public void remove() {
        throw new UnsupportedOperationException();
    }

    public E next() {
        this.currentEnd = null;
        if (this.available) {
            this.available = false;
            this.currentEnd = this.nextEnd;
            return this.nextEnd;
        } else {
            this.currentEnd = this.processNextStart();
            return this.currentEnd;
        }
    }

    public boolean hasNext() {
        if (this.available)
            return true;
        else {
            try {
                this.nextEnd = this.processNextStart();
                this.available = true;
                return true;
            } catch (NoSuchElementException e) {
                this.available = false;
                return false;
            }
        }
    }

    public Iterator<E> iterator() {
        return this;
    }

    protected abstract E processNextStart() throws NoSuchElementException;

}


@@ -1599,19 +1599,26 @@
        i
-f (
+nt size = 
 pathElem
@@ -1626,12 +1626,45 @@
 nts.
-get(
+size();%0A            if (size == 0 %7C%7C 
 path
@@ -1672,22 +1672,24 @@
 lements.
+get(
 size
-()
  - 1) !=
@@ -1704,24 +1704,26 @@
 rrentEnd) %7B%0A
+  
             

Fix index error.