Creating a Pipe

okram edited this page Mar 2, 2013 · 4 revisions

The pipes that come prepackaged with Pipes are not sufficient for every use case. In many situations, it will be necessary to create a pipe that will solve a particular mapping from an input to an output. An easy way to accomplish this is via the respective XXXFunctionPipe and PipeFunction implementation. However, it is possible to write a specific pipe without using XXXFunctionPipe-based pipes.

Transform-Based Pipe with AbstractPipe

Pipes make it easy to create new pipes with the AbstractPipe class. In AbstractPipe, there is a single method that needs to be implemented: AbstractPipe.processNextStart(). The example below demonstrates the internals of a simple pipe that maps a string to the number of characters contained in that string.

public class WordLengthPipe extends AbstractPipe<String, Integer> implements TransformPipe<String,Integer> {
  public Integer processNextStart() {
    String start = this.starts.next();
    return start.length();
  }
}

Filter-Based Pipe with AbstractPipe

The general pattern for filter-based pipes is explained with an example.

public class WordFilterPipe extends AbstractPipe<String,String> implements FilterPipe<String> {
  public String processNextStarts() {
    while(true) {
       String start = this.starts.next();
       if(start.length() > 4)
          return start;
    }
  }
}

A FilterPipe will usually make use of a while(true) loop that will continually pull in new objects. If the current object meets some criteria, it will be emitted, else, the while(true) will loop again and pull in a new object. There is no need to worry about handling NoSuchElementExceptions. If this.starts.next() throws a NoSuchElementException then this will be handled appropriately by AbstractPipe.

SideEffect-Based Pipe with AbstractPipe

Below is an example of a side-effect based pipe using AbstractPipe.

public class WordPrintPipe extends AbstractPipe<String,String> implements SideEffectPipe<String,Object> {
  public String processNextStarts() {
     String start = this.starts.next();
     System.out.println(start);
     return start; 
  }

  public Object getSideEffect() {
     return null;
  }
}

Given that the side-effect is simply a println to the System.out, there is no Object side-effect that can be later retrieved. As such, the SideEffectPipe.getSideEffect() method simply returns null.