package com.tinkerpop.blueprints.util; import com.tinkerpop.blueprints.Predicate; import com.tinkerpop.blueprints.Direction; import com.tinkerpop.blueprints.Edge; import com.tinkerpop.blueprints.Element; import com.tinkerpop.blueprints.Vertex; import com.tinkerpop.blueprints.VertexQuery; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; /** * For those graph engines that do not support the low-level querying of the edges of a vertex, then DefaultVertexQuery can be used. * DefaultVertexQuery assumes, at minimum, that Vertex.getOutEdges() and Vertex.getInEdges() is implemented by the respective Vertex. * * @author Marko A. Rodriguez (http://markorodriguez.com) */ public class DefaultVertexQuery extends DefaultQuery implements VertexQuery { protected final Vertex vertex; public DefaultVertexQuery(final Vertex vertex) { this.vertex = vertex; } public VertexQuery has(final String key) { super.has(key); return this; } public VertexQuery hasNot(final String key) { super.hasNot(key); return this; } public VertexQuery has(final String key, final Object value) { super.has(key, value); return this; } public VertexQuery hasNot(final String key, final Object value) { super.hasNot(key, value); return this; } public VertexQuery has(final String key, final Predicate predicate, final Object value) { super.has(key, predicate, value); return this; } public <T extends Comparable<T>> VertexQuery has(final String key, final T value, final Compare compare) { super.has(key, compare, value); return this; } public <T extends Comparable<?>> VertexQuery interval(final String key, final T startValue, final T endValue) { super.interval(key, startValue, endValue); return this; } public VertexQuery limit(final int limit) { super.limit(limit); return this; } public VertexQuery direction(final Direction direction) { this.direction = direction; return this; } public VertexQuery labels(final String... labels) { this.labels = labels; return this; } public Iterable<Edge> edges() { return new DefaultVertexQueryIterable<Edge>(false); } public Iterable<Vertex> vertices() { return new DefaultVertexQueryIterable<Vertex>(true); } public long count() { long count = 0; for (final Edge edge : this.edges()) { count++; } return count; } public Object vertexIds() { final List<Object> list = new ArrayList<Object>(); for (final Vertex vertex : this.vertices()) { list.add(vertex.getId()); } return list; } private class DefaultVertexQueryIterable<T extends Element> implements Iterable<T> { private Iterable<Edge> iterable; private boolean forVertex; public DefaultVertexQueryIterable(final boolean forVertex) { this.forVertex = forVertex; this.iterable = vertex.getEdges(direction, labels); } public Iterator<T> iterator() { return new Iterator<T>() { Edge nextEdge = null; final Iterator<Edge> itty = iterable.iterator(); long count = 0; public boolean hasNext() { if (null != this.nextEdge) { return true; } else { return this.loadNext(); } } public T next() { while (true) { if (this.nextEdge != null) { final Edge temp = this.nextEdge; this.nextEdge = null; if (forVertex) { if (direction == Direction.OUT) return (T) temp.getVertex(Direction.IN); else if (direction == Direction.IN) return (T) temp.getVertex(Direction.OUT); else { if (temp.getVertex(Direction.OUT).equals(vertex)) { return (T) temp.getVertex(Direction.IN); } else { return (T) temp.getVertex(Direction.OUT); } } } else { return (T) temp; } } if (!this.loadNext()) throw new NoSuchElementException(); } } public void remove() { throw new UnsupportedOperationException(); } private boolean loadNext() { this.nextEdge = null; if (this.count > limit) return false; while (this.itty.hasNext()) { final Edge edge = this.itty.next(); boolean filter = false; for (final HasContainer hasContainer : hasContainers) { if (!hasContainer.isLegal(edge)) { filter = true; break; } } if (!filter) { if (++this.count <= limit) { this.nextEdge = edge; return true; } } } return false; } }; } } }