All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.tinkerpop.pipes.sideeffect.AggregatePipe Maven / Gradle / Ivy

Go to download

Pipes is a dataflow framework written in Java that enables the splitting, merging, filtering, and transformation of data from input to output. Computations are expressed using a combinator model and are evaluated in a memory-efficient, lazy fashion.

There is a newer version: 2.6.0
Show newest version
package com.tinkerpop.pipes.sideeffect;

import com.tinkerpop.pipes.AbstractPipe;
import com.tinkerpop.pipes.Pipe;
import com.tinkerpop.pipes.PipeFunction;
import com.tinkerpop.pipes.util.FastNoSuchElementException;
import com.tinkerpop.pipes.util.structures.ArrayQueue;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Queue;

/**
 * The AggregatePipe produces a side effect that is the provided Collection filled with the contents of all the objects that have passed through it.
 * Before the first object is emitted from the AggregatePipe, all of its incoming objects have been aggregated into the collection.
 * Finally, note that different Collections have different behaviors and write/read times.
 *
 * @author Marko A. Rodriguez (http://markorodriguez.com)
 */
public class AggregatePipe extends AbstractPipe implements SideEffectPipe.GreedySideEffectPipe {

    private Collection aggregate;
    private Queue currentObjectQueue = new ArrayQueue();
    private Queue currentPathQueue = new ArrayQueue();
    private List currentPath;
    private PipeFunction preAggregateFunction = null;

    public AggregatePipe(final Collection aggregate) {
        this.aggregate = aggregate;
    }

    /**
     * The provided PipeFunction will process the object prior to inserting it into the aggregate collection.
     *
     * @param aggregate            the aggregate collection
     * @param preAggregateFunction a function to process an object with prior to insertion into the collection
     */
    public AggregatePipe(final Collection aggregate, final PipeFunction preAggregateFunction) {
        this(aggregate);
        this.preAggregateFunction = preAggregateFunction;
    }

    public List getCurrentPath() {
        if (this.pathEnabled) {
            final List pathElements = new ArrayList(this.currentPath);
            final int size = pathElements.size();
            // do not repeat filters as they dup the object
            if (size == 0 || pathElements.get(size - 1) != this.currentEnd) {
                pathElements.add(this.currentEnd);
            }
            return pathElements;
        } else {
            throw new RuntimeException(Pipe.NO_PATH_MESSAGE);
        }
    }

    protected S processNextStart() {
        while (true) {
            if (this.currentObjectQueue.isEmpty()) {
                if (!this.starts.hasNext())
                    throw FastNoSuchElementException.instance();
                else {
                    this.currentObjectQueue.clear();
                    this.currentPathQueue.clear();

                    try {
                        while (true) {
                            final S s = this.starts.next();
                            if (this.preAggregateFunction != null)
                                this.aggregate.add(this.preAggregateFunction.compute(s));
                            else
                                this.aggregate.add(s);
                            this.currentObjectQueue.add(s);
                            if (this.pathEnabled)
                                this.currentPathQueue.add(this.getPathToHere());
                        }
                    } catch (final NoSuchElementException e) {
                    }
                }
            } else {
                if (this.pathEnabled)
                    this.currentPath = currentPathQueue.remove();
                return this.currentObjectQueue.remove();
            }
        }
    }

    public Collection getSideEffect() {
        return this.aggregate;
    }

    public void reset() {
        try {
            this.aggregate = this.aggregate.getClass().getConstructor().newInstance();
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
        this.currentPath = null;
        this.currentObjectQueue.clear();
        this.currentPathQueue.clear();
        super.reset();
    }
}