// Path: src/main/java/com/tinkerpop/pipes/Pipe.java
// public interface Pipe<S, E> extends Iterator<E>, Iterable<E> {
// 
//     public static final String NO_PATH_MESSAGE = "Path calculations are not enabled";
// 
//     /**
//      * Set an iterator of S objects to the head (start) of the pipe.
//      *
//      * @param starts the iterator of incoming objects
//      */
//     public void setStarts(Iterator<S> starts);
// 
//     /**
//      * Set an iterable of S objects to the head (start) of the pipe.
//      *
//      * @param starts the iterable of incoming objects
//      */
//     public void setStarts(Iterable<S> starts);
// 
//     /**
//      * Returns the transformation path to arrive at the current object of the pipe.
//      *
//      * @return a List of all of the objects traversed for the current iterator position of the pipe.
//      */
//     public List getCurrentPath();
// 
//     /**
//      * Calculating paths can be an expensive operation for some pipes.
//      * This method is used to activate or deactivate the calculation of paths.
//      * The default state of a newly constructed pipe should have its path calculations disabled.
//      * An implementation of this method should be recursive whereby the starts (if a Pipe) should have this method called on it.
//      *
//      * @param enable enable path calculations
//      */
//     public void enablePath(boolean enable);
// 
//     /**
//      * A pipe may maintain state. Reset is used to remove state.
//      * The general use case for reset() is to reuse a pipe in another computation without having to create a new Pipe object.
//      * An implementation of this method should be recursive whereby the starts (if a Pipe) should have this method called on it.
//      */
//     public void reset();
// }
// 
// Path: src/main/java/com/tinkerpop/pipes/PipeFunction.java
// public interface PipeFunction<A, B> {
// 
//     /**
//      * A function that takes an argument of type A and returns a result of type B.
//      *
//      * @param argument An argument of type A
//      * @return the result of computing the function on the argument
//      */
//     public B compute(A argument);
// }


import com.tinkerpop.pipes.Pipe;
import com.tinkerpop.pipes.PipeFunction;
import junit.framework.TestCase;
import java.util.Arrays;
import java.util.List;
        List<String> starts = Arrays.asList("marko", "josh", "peter", "marko", "marko");
        Pipe<String, String> pipe = new DuplicateFilterPipe<String>(new PipeFunction<String, Object>() {
            @Override
            public Object compute(String argument) {
                return argument.length();
            }
        });
        pipe.setStarts(starts.iterator());
        int counter = 0;
        int counter2 = 0;
        while (pipe.hasNext()) {
            String next = pipe.next();
            assertTrue(next.equals("josh") || next.equals("marko"));
            if (next.equals("marko") || next.equals("peter"))
                counter2++;
            counter++;
        }
        assertEquals(counter, 2);
        assertEquals(counter2, 1);


    }

    public void testReset() {
        List<String> starts = Arrays.asList("marko", "marko", "peter", "marko", "josh");
        Pipe<String, String> pipe = new DuplicateFilterPipe<String>();
        pipe.setStarts(starts.iterator());
        assertTrue(pipe.hasNext());
        assertEquals(pipe.next(), "marko");
        assertEquals(pipe.next(), "peter");
// Path: src/main/java/com/tinkerpop/pipes/Pipe.java
// public interface Pipe<S, E> extends Iterator<E>, Iterable<E> {
// 
//     public static final String NO_PATH_MESSAGE = "Path calculations are not enabled";
// 
//     /**
//      * Set an iterator of S objects to the head (start) of the pipe.
//      *
//      * @param starts the iterator of incoming objects
//      */
//     public void setStarts(Iterator<S> starts);
// 
//     /**
//      * Set an iterable of S objects to the head (start) of the pipe.
//      *
//      * @param starts the iterable of incoming objects
//      */
//     public void setStarts(Iterable<S> starts);
// 
//     /**
//      * Returns the transformation path to arrive at the current object of the pipe.
//      *
//      * @return a List of all of the objects traversed for the current iterator position of the pipe.
//      */
//     public List getCurrentPath();
// 
//     /**
//      * Calculating paths can be an expensive operation for some pipes.
//      * This method is used to activate or deactivate the calculation of paths.
//      * The default state of a newly constructed pipe should have its path calculations disabled.
//      * An implementation of this method should be recursive whereby the starts (if a Pipe) should have this method called on it.
//      *
//      * @param enable enable path calculations
//      */
//     public void enablePath(boolean enable);
// 
//     /**
//      * A pipe may maintain state. Reset is used to remove state.
//      * The general use case for reset() is to reuse a pipe in another computation without having to create a new Pipe object.
//      * An implementation of this method should be recursive whereby the starts (if a Pipe) should have this method called on it.
//      */
//     public void reset();
// }
// 
// Path: src/main/java/com/tinkerpop/pipes/PipeFunction.java
// public interface PipeFunction<A, B> {
// 
//     /**
//      * A function that takes an argument of type A and returns a result of type B.
//      *
//      * @param argument An argument of type A
//      * @return the result of computing the function on the argument
//      */
//     public B compute(A argument);
// }


// Path: src/test/java/com/tinkerpop/pipes/filter/DuplicateFilterPipeTest.java
import com.tinkerpop.pipes.Pipe;
import com.tinkerpop.pipes.PipeFunction;
import junit.framework.TestCase;
import java.util.Arrays;
import java.util.List;

        List<String> starts = Arrays.asList("marko", "josh", "peter", "marko", "marko");
        Pipe<String, String> pipe = new DuplicateFilterPipe<String>(new PipeFunction<String, Object>() {
            @Override
            public Object compute(String argument) {
                return argument.length();
            }
        });
        pipe.setStarts(starts.iterator());
        int counter = 0;
        int counter2 = 0;
        while (pipe.hasNext()) {
            String next = pipe.next();
            assertTrue(next.equals("josh") || next.equals("marko"));
            if (next.equals("marko") || next.equals("peter"))
                counter2++;
            counter++;
        }
        assertEquals(counter, 2);
        assertEquals(counter2, 1);


    }

    public void testReset() {
        List<String> starts = Arrays.asList("marko", "marko", "peter", "marko", "josh");
        Pipe<String, String> pipe = new DuplicateFilterPipe<String>();
        pipe.setStarts(starts.iterator());
        assertTrue(pipe.hasNext());
        assertEquals(pipe.next(), "marko");
        assertEquals(pipe.next(), "peter");
        pipe.reset();