package com.tinkerpop.pipes.transform; import com.tinkerpop.pipes.Pipe; import com.tinkerpop.pipes.util.AbstractMetaPipe; import com.tinkerpop.pipes.util.MetaPipe; import com.tinkerpop.pipes.util.PipeHelper; import com.tinkerpop.pipes.util.iterators.SingleExpandableIterator; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; /** * @author Marko A. Rodriguez (http://markorodriguez.com) */ public class MemoizePipe<S, E> extends AbstractMetaPipe<S, E> implements MetaPipe, TransformPipe<S, E> { protected Pipe<S, E> pipe; protected Map<S, List<E>> map; protected Iterator<E> currentIterator = PipeHelper.emptyIterator(); protected final SingleExpandableIterator<S> expando = new SingleExpandableIterator<S>(); public MemoizePipe(final Pipe<S, E> pipe) { this(pipe, new HashMap<S, List<E>>()); } public MemoizePipe(final Pipe<S, E> pipe, final Map<S, List<E>> map) { this.pipe = pipe; this.pipe.setStarts(this.expando); this.map = map; } public E processNextStart() { while (true) { if (this.currentIterator.hasNext()) return this.currentIterator.next(); else { this.getOrCreate(this.starts.next()); } } } private void getOrCreate(final S s) { if (this.map.containsKey(s)) { this.currentIterator = this.map.get(s).iterator(); } else { this.expando.add(s); final List<E> results = new ArrayList<E>(); PipeHelper.fillCollection(this.pipe, results); this.map.put(s, results); this.currentIterator = results.iterator(); } } public List<Pipe> getPipes() { return (List) Arrays.asList(pipe); } public void reset() { this.currentIterator = PipeHelper.emptyIterator(); try { this.map = this.map.getClass().getConstructor().newInstance(); } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } super.reset(); } public String toString() { return PipeHelper.makePipeString(this, this.pipe); } }