//////////////////////////////////////////////////////////////////////////////////////////
//
// Implementation of a simple graph client for the ArangoDB.
//
// Copyright triAGENS GmbH Cologne.
//
//////////////////////////////////////////////////////////////////////////////////////////
package com.arangodb.blueprints.client;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import com.arangodb.CursorResult;
import com.arangodb.util.AqlQueryOptions;
/**
* The ArangoDB base query class
*
* @author Achim Brandt (http://www.triagens.de)
* @author Johannes Gocke (http://www.triagens.de)
* @author Guido Schwab (http://www.triagens.de)
* @author Jan Steemann (http://www.triagens.de)
*/
public class ArangoDBBaseQuery {
/**
* the ArangoDB graph
*/
protected ArangoDBSimpleGraph graph;
/**
* the ArangoDB client
*/
protected ArangoDBSimpleGraphClient client;
/**
* query type
*/
protected QueryType queryType;
protected ArangoDBSimpleVertex startVertex;
protected ArangoDBPropertyFilter propertyFilter;
protected List<String> labelsFilter;
protected Direction direction;
protected Long limit;
protected boolean count;
/**
* Direction
*
*/
public enum Direction {
// direction into a element
IN,
// direction out of a element
OUT,
// direction in and out of a element
ALL
};
public enum QueryType {
GRAPH_VERTICES,
GRAPH_EDGES,
GRAPH_NEIGHBORS
}
/**
* Constructor
*
* @param graph
* the graph of the query
* @param client
* the request client of the query
* @param queryType
* a query type
* @throws ArangoDBException
*/
public ArangoDBBaseQuery(ArangoDBSimpleGraph graph, ArangoDBSimpleGraphClient client, QueryType queryType)
throws ArangoDBException {
this.graph = graph;
this.client = client;
this.queryType = queryType;
}
/**
* Executes the query and returns a result cursor
*
* @return CursorResult<Map> the result cursor
*
* @throws ArangoDBException
* if the query could not be executed
*/
@SuppressWarnings("rawtypes")
public CursorResult<Map> getCursorResult() throws ArangoDBException {
Map<String, Object> options = new HashMap<String, Object>();
options.put("includeData", true);
options.put("direction", getDirectionString());
Map<String, Object> bindVars = new HashMap<String, Object>();
bindVars.put("graphName", graph.getName());
bindVars.put("options", options);
bindVars.put("vertexExample", getVertexExample());
StringBuilder sb = new StringBuilder();
String prefix = "i.";
String returnExp = " return i";
switch (queryType) {
case GRAPH_VERTICES:
sb.append("for i in GRAPH_VERTICES(@graphName , @vertexExample, @options)");
break;
case GRAPH_EDGES:
sb.append("for i in GRAPH_EDGES(@graphName , @vertexExample, @options)");
break;
case GRAPH_NEIGHBORS:
default:
sb.append("for i in GRAPH_EDGES(@graphName , @vertexExample, @options)");
returnExp = " return DOCUMENT(" + getDocumentByDirection() + ")";
break;
}
List<String> andFilter = new ArrayList<String>();
if (propertyFilter == null) {
propertyFilter = new ArangoDBPropertyFilter();
}
propertyFilter.addProperties(prefix, andFilter, bindVars);
if (CollectionUtils.isNotEmpty(labelsFilter)) {
List<String> orFilter = new ArrayList<String>();
int tmpCount = 0;
for (String label : labelsFilter) {
orFilter.add(prefix + "label == @label" + tmpCount);
bindVars.put("label" + tmpCount++, label);
}
if (CollectionUtils.isNotEmpty(orFilter)) {
andFilter.add("(" + StringUtils.join(orFilter, " OR ") + ")");
}
}
if (CollectionUtils.isNotEmpty(andFilter)) {
sb.append(" FILTER ");
sb.append(StringUtils.join(andFilter, " AND "));
}
if (limit != null) {
sb.append(" LIMIT " + limit.toString());
}
sb.append(returnExp);
String query = sb.toString();
AqlQueryOptions aqlQueryOptions = new AqlQueryOptions();
aqlQueryOptions.setBatchSize(client.getConfiguration().getBatchSize());
aqlQueryOptions.setCount(count);
return client.executeAqlQuery(query, bindVars, aqlQueryOptions);
}
private Object getVertexExample() {
if (startVertex != null) {
return startVertex.getDocumentId();
} else {
return new HashMap<String, String>();
}
}
private String getDirectionString() {
if (direction != null) {
if (direction == Direction.IN) {
return "inbound";
} else if (direction == Direction.OUT) {
return "outbound";
}
}
return "any";
}
private String getDocumentByDirection() {
if (direction != null) {
if (direction == Direction.IN) {
return "i._from";
} else if (direction == Direction.OUT) {
return "i._to";
}
}
return "i._to == @vertexExample ? i._from : i._to";
}
public ArangoDBSimpleVertex getStartVertex() {
return startVertex;
}
public ArangoDBBaseQuery setStartVertex(ArangoDBSimpleVertex startVertex) {
this.startVertex = startVertex;
return this;
}
public ArangoDBPropertyFilter getPropertyFilter() {
return propertyFilter;
}
public ArangoDBBaseQuery setPropertyFilter(ArangoDBPropertyFilter propertyFilter) {
this.propertyFilter = propertyFilter;
return this;
}
public List<String> getLabelsFilter() {
return labelsFilter;
}
public ArangoDBBaseQuery setLabelsFilter(List<String> labelsFilter) {
this.labelsFilter = labelsFilter;
return this;
}
public Direction getDirection() {
return direction;
}
public ArangoDBBaseQuery setDirection(Direction direction) {
this.direction = direction;
return this;
}
public Long getLimit() {
return limit;
}
public ArangoDBBaseQuery setLimit(Long limit) {
this.limit = limit;
return this;
}
public boolean isCount() {
return count;
}
public ArangoDBBaseQuery setCount(boolean count) {
this.count = count;
return this;
}
}