package org.vertexium.query; import com.google.common.collect.Lists; import org.vertexium.*; import org.vertexium.util.SelectManyIterable; import java.util.*; public class CompositeGraphQuery implements Query { private final Graph graph; private final List<Query> queries; public CompositeGraphQuery(Graph graph, Query... queries) { this(graph, Arrays.asList(queries)); } public CompositeGraphQuery(Graph graph, Collection<Query> queries) { this.graph = graph; this.queries = new ArrayList<>(queries); } @Override public QueryResultsIterable<Vertex> vertices() { return vertices(getGraph().getDefaultFetchHints()); } private Graph getGraph() { return this.graph; } @Override public QueryResultsIterable<Vertex> vertices(final EnumSet<FetchHint> fetchHints) { final Set<String> seenIds = new HashSet<>(); return new QueryResultsSelectManyIterable<Vertex>(this.queries) { @Override public Iterable<Vertex> getIterable(Query query) { return query.vertices(fetchHints); } @Override protected boolean isIncluded(Vertex vertex) { if (seenIds.contains(vertex.getId())) { return false; } seenIds.add(vertex.getId()); return super.isIncluded(vertex); } }; } @Override public QueryResultsIterable<String> vertexIds() { return new DefaultGraphQueryIdIterable<>(vertices(FetchHint.NONE)); } @Override public QueryResultsIterable<Edge> edges() { return edges(getGraph().getDefaultFetchHints()); } @Override public QueryResultsIterable<Edge> edges(final EnumSet<FetchHint> fetchHints) { final Set<String> seenIds = new HashSet<>(); return new QueryResultsSelectManyIterable<Edge>(this.queries) { @Override public Iterable<Edge> getIterable(Query query) { return query.edges(fetchHints); } @Override protected boolean isIncluded(Edge edge) { if (seenIds.contains(edge.getId())) { return false; } seenIds.add(edge.getId()); return super.isIncluded(edge); } }; } @Override public QueryResultsIterable<String> edgeIds() { return new DefaultGraphQueryIdIterable<>(edges(FetchHint.NONE)); } @Override @Deprecated public QueryResultsIterable<Edge> edges(final String label) { hasEdgeLabel(label); return edges(getGraph().getDefaultFetchHints()); } @Override @Deprecated public QueryResultsIterable<Edge> edges(final String label, final EnumSet<FetchHint> fetchHints) { hasEdgeLabel(label); return edges(fetchHints); } @Override public QueryResultsIterable<Element> elements() { return elements(getGraph().getDefaultFetchHints()); } @Override public QueryResultsIterable<Element> elements(final EnumSet<FetchHint> fetchHints) { final Set<String> seenIds = new HashSet<>(); return new QueryResultsSelectManyIterable<Element>(this.queries) { @Override public Iterable<Element> getIterable(Query query) { return query.elements(fetchHints); } @Override protected boolean isIncluded(Element element) { if (seenIds.contains(element.getId())) { return false; } seenIds.add(element.getId()); return super.isIncluded(element); } }; } @Override public QueryResultsIterable<String> elementIds() { return new DefaultGraphQueryIdIterable<>(elements(FetchHint.NONE)); } @Override public QueryResultsIterable<ExtendedDataRow> extendedDataRows() { return extendedDataRows(getGraph().getDefaultFetchHints()); } @Override public QueryResultsIterable<ExtendedDataRow> extendedDataRows(EnumSet<FetchHint> fetchHints) { final Set<ExtendedDataRowId> seenIds = new HashSet<>(); return new QueryResultsSelectManyIterable<ExtendedDataRow>(this.queries) { @Override public Iterable<ExtendedDataRow> getIterable(Query query) { return query.extendedDataRows(fetchHints); } @Override protected boolean isIncluded(ExtendedDataRow extendedDataRows) { if (seenIds.contains(extendedDataRows.getId())) { return false; } seenIds.add(extendedDataRows.getId()); return super.isIncluded(extendedDataRows); } }; } @Override public QueryResultsIterable<ExtendedDataRowId> extendedDataRowIds() { return new DefaultGraphQueryIdIterable<>(extendedDataRows(FetchHint.NONE)); } @Override public QueryResultsIterable<? extends VertexiumObject> search(EnumSet<VertexiumObjectType> objectTypes, EnumSet<FetchHint> fetchHints) { final Set<Object> seenIds = new HashSet<>(); return new QueryResultsSelectManyIterable<VertexiumObject>(this.queries) { @Override public Iterable<? extends VertexiumObject> getIterable(Query query) { return query.search(objectTypes, fetchHints); } @Override protected boolean isIncluded(VertexiumObject vertexiumObject) { if (seenIds.contains(vertexiumObject.getId())) { return false; } seenIds.add(vertexiumObject.getId()); return super.isIncluded(vertexiumObject); } }; } @Override public QueryResultsIterable<? extends VertexiumObject> search() { return search(VertexiumObjectType.ALL, getGraph().getDefaultFetchHints()); } @Override public <T> Query range(String propertyName, T startValue, T endValue) { for (Query query : queries) { query.range(propertyName, startValue, endValue); } return this; } @Override public <T> Query range(String propertyName, T startValue, boolean inclusiveStartValue, T endValue, boolean inclusiveEndValue) { for (Query query : queries) { query.range(propertyName, startValue, inclusiveStartValue, endValue, inclusiveEndValue); } return this; } @Override public Query hasEdgeLabel(String... edgeLabels) { for (Query query : queries) { query.hasEdgeLabel(edgeLabels); } return this; } @Override public Query hasEdgeLabel(Collection<String> edgeLabels) { for (Query query : queries) { query.hasEdgeLabel(edgeLabels); } return this; } @Override public Query hasExtendedData(ElementType elementType, String elementId) { return hasExtendedData(elementType, elementId, null); } @Override public Query hasExtendedData(String tableName) { return hasExtendedData(null, null, tableName); } @Override public Query hasExtendedData(ElementType elementType, String elementId, String tableName) { for (Query query : queries) { query.hasExtendedData(elementType, elementId, tableName); } return this; } @Override public Query hasExtendedData(Iterable<HasExtendedDataFilter> filters) { filters = Lists.newArrayList(filters); for (Query query : queries) { query.hasExtendedData(filters); } return this; } @Override public <T> Query has(String propertyName, T value) { for (Query query : queries) { query.has(propertyName, value); } return this; } @Override public <T> Query hasNot(String propertyName, T value) { for (Query query : queries) { query.hasNot(propertyName, value); } return this; } @Override public <T> Query has(String propertyName, Predicate predicate, T value) { for (Query query : queries) { query.has(propertyName, predicate, value); } return this; } @Override public Query has(String propertyName) { for (Query query : queries) { query.has(propertyName); } return this; } @Override public Query hasNot(String propertyName) { for (Query query : queries) { query.hasNot(propertyName); } return this; } @Override public Query skip(int count) { for (Query query : queries) { query.skip(count); } return this; } @Override public Query limit(Integer count) { for (Query query : queries) { query.limit(count); } return this; } @Override public Query limit(Long count) { for (Query query : queries) { query.limit(count); } return this; } @Override public Query sort(String propertyName, SortDirection direction) { for (Query query : queries) { query.sort(propertyName, direction); } return this; } @Override public boolean isAggregationSupported(Aggregation aggregation) { for (Query query : queries) { if (!query.isAggregationSupported(aggregation)) { return false; } } return true; } @Override public Query addAggregation(Aggregation aggregation) { for (Query query : queries) { if (!query.isAggregationSupported(aggregation)) { throw new VertexiumException(query.getClass().getName() + " does not support aggregation of type " + aggregation.getClass().getName()); } } for (Query query : queries) { query.addAggregation(aggregation); } return this; } @Override public Iterable<Aggregation> getAggregations() { return new SelectManyIterable<Query, Aggregation>(queries) { @Override protected Iterable<? extends Aggregation> getIterable(Query query) { return query.getAggregations(); } }; } }