package com.tinkerpop.pipes.transform;
import com.tinkerpop.blueprints.Direction;
import com.tinkerpop.blueprints.Element;
import com.tinkerpop.blueprints.Vertex;
import com.tinkerpop.blueprints.VertexQuery;
import com.tinkerpop.pipes.util.FastNoSuchElementException;
import com.tinkerpop.pipes.util.PipeHelper;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
/**
* VertexQueryPipe makes use of the Vertex.query() method in Blueprints which allows for intelligent edge look ups from the underlying graph.
*
* @author Marko A. Rodriguez (http://markorodriguez.com)
*/
public class VertexQueryPipe<E extends Element> extends QueryPipe<Vertex, E> {
private Direction direction = Direction.BOTH;
private String[] labels;
private int branchFactor;
/**
* Construct a new VertexQuery pipe that wraps an underlying Blueprints VertexQuery object.
* Given the optional nature of many of the parameters, note the "wildcard" settings for each parameter.
*
* @param resultingElementClass this must be either Vertex.class or Edge.class (anything else will throw an IllegalArgumentException)
* @param direction this must be a legal direction representing the direction of the edge.
* @param hasContainers this must be a collection of 'has'-filters (i.e. property filters). Provide an empty list if no such filters are to be applied.
* @param intervalContainers this must be a collection of 'interval'-filters (i.e. property filters within a range). Provide an empty list if no such filters are to be applied.
* @param branchFactor the branch factor for a particular vertex (determines the limit() of the VertexQuery)
* @param lowRange this must be a long value representing the low range of elements to emit
* @param highRange this must be a long value representing the high range of elements to emit
* @param labels this is a list of Strings representing the edge label filters to apply. Do not provide any Strings if no such filtering is desired.
*/
public VertexQueryPipe(final Class<E> resultingElementClass, final Direction direction, final List<HasContainer> hasContainers, final List<IntervalContainer> intervalContainers, final int branchFactor, final int lowRange, final int highRange, final String... labels) {
this.setResultingElementClass(resultingElementClass);
this.direction = direction;
if (null != hasContainers) {
for (final HasContainer container : hasContainers) {
super.addHasContainer(container);
}
}
if (null != intervalContainers) {
for (final IntervalContainer container : intervalContainers) {
super.addIntervalContainer(container);
}
}
this.branchFactor = branchFactor;
super.setLowRange(lowRange);
super.setHighRange(highRange);
this.labels = labels;
}
public void setDirection(final Direction direction) {
this.direction = direction;
}
public void setLabels(final String... labels) {
this.labels = labels;
}
public void setBranchFactor(final int branchFactor) {
this.branchFactor = branchFactor;
}
public String toString() {
return (this.branchFactor == Integer.MAX_VALUE) ?
PipeHelper.makePipeString(this, this.direction.name().toLowerCase(), Arrays.asList(this.labels), super.toString()) :
PipeHelper.makePipeString(this, this.direction.name().toLowerCase(), "branch:" + branchFactor, Arrays.asList(this.labels), super.toString());
}
public E processNextStart() {
while (true) {
if (this.count >= this.highRange) {
throw FastNoSuchElementException.instance();
} else if (this.currentIterator.hasNext()) {
this.count++;
final E e = currentIterator.next();
if (this.count > this.lowRange)
return e;
} else {
final Vertex vertex = this.starts.next();
VertexQuery query = vertex.query();
query = query.direction(this.direction);
if (this.labels.length > 0)
query = query.labels(this.labels);
if (null != this.hasContainers) {
for (final HasContainer hasContainer : this.hasContainers) {
query = query.has(hasContainer.key, hasContainer.predicate, hasContainer.value);
}
}
if (null != this.intervalContainers) {
for (final IntervalContainer intervalContainer : this.intervalContainers) {
query = query.interval(intervalContainer.key, intervalContainer.startValue, intervalContainer.endValue);
}
}
if (this.branchFactor == Integer.MAX_VALUE) {
if (this.highRange != Integer.MAX_VALUE) {
int temp = this.highRange - this.count;
query = temp > 0 ? query.limit(temp) : query;
}
} else {
if (this.highRange == Integer.MAX_VALUE) {
query = query.limit(this.branchFactor);
} else {
int temp = this.highRange - this.count;
query = query.limit(temp < this.branchFactor ? temp : this.branchFactor);
}
}
this.currentIterator = this.elementClass.equals(Vertex.class) ?
(Iterator<E>) query.vertices().iterator() :
(Iterator<E>) query.edges().iterator();
}
}
}
}