package org.vertexium.cypher;
import org.vertexium.*;
import org.vertexium.cypher.ast.model.CypherNodePattern;
import org.vertexium.cypher.ast.model.CypherRelationshipPattern;
import org.vertexium.cypher.executor.*;
import org.vertexium.cypher.functions.CypherFunction;
import org.vertexium.cypher.functions.aggregate.*;
import org.vertexium.cypher.functions.list.*;
import org.vertexium.cypher.functions.math.*;
import org.vertexium.cypher.functions.predicate.*;
import org.vertexium.cypher.functions.scalar.*;
import org.vertexium.cypher.functions.spatial.DistanceFunction;
import org.vertexium.cypher.functions.spatial.PointFunction;
import org.vertexium.cypher.functions.string.*;
import org.vertexium.mutation.ElementMutation;
import org.vertexium.mutation.ExistingElementMutation;
import java.util.*;
import java.util.stream.Collectors;
import static org.vertexium.util.StreamUtils.stream;
public abstract class VertexiumCypherQueryContext {
private final Graph graph;
private final Map<String, Object> parameters = new HashMap<>();
private final Map<String, CypherFunction> functions = new HashMap<>();
private final Authorizations authorizations;
private final ExpressionExecutor expressionExecutor;
private final CreateClauseExecutor createClauseExecutor;
private final ReturnClauseExecutor returnClauseExecutor;
private final MatchClauseExecutor matchClauseExecutor;
private final UnwindClauseExecutor unwindClauseExecutor;
private final WithClauseExecutor withClauseExecutor;
private final MergeClauseExecutor mergeClauseExecutor;
private final DeleteClauseExecutor deleteClauseExecutor;
private final SetClauseExecutor setClauseExecutor;
private final RemoveClauseExecutor removeClauseExecutor;
private final CypherResultWriter resultWriter;
public VertexiumCypherQueryContext(Graph graph, Authorizations authorizations) {
this.graph = graph;
this.authorizations = authorizations;
// aggregate
addFunction("avg", new AverageFunction());
addFunction("collect", new CollectFunction());
addFunction("count", new CountFunction());
addFunction("max", new MaxFunction());
addFunction("min", new MinFunction());
addFunction("percentileCont", new PercentileContFunction());
addFunction("percentileDisc", new PercentileDiscFunction());
addFunction("stDev", new StandardDeviationFunction());
addFunction("stDevP", new StandardDeviationPopulationFunction());
addFunction("sum", new SumFunction());
// list
addFunction("extract", new ExtractFunction());
addFunction("filter", new FilterFunction());
addFunction("keys", new KeysFunction());
addFunction("labels", new LabelsFunction());
addFunction("nodes", new NodesFunction());
addFunction("range", new RangeFunction());
addFunction("reduce", new ReduceFunction());
addFunction("relationships", new RelationshipsFunction());
addFunction("tail", new TailFunction());
// math
addFunction("abs", new AbsFunction());
addFunction("ceil", new CeilFunction());
addFunction("floor", new FloorFunction());
addFunction("rand", new RandFunction());
addFunction("round", new RoundFunction());
addFunction("sign", new SignFunction());
addFunction("e", new EFunction());
addFunction("exp", new ExpFunction());
addFunction("log", new LogFunction());
addFunction("log10", new Log10Function());
addFunction("sqrt", new SquareRootFunction());
addFunction("acos", new ACosFunction());
addFunction("asin", new ASinFunction());
addFunction("atan", new ATanFunction());
addFunction("atan2", new ATan2Function());
addFunction("cos", new CosFunction());
addFunction("cot", new CotFunction());
addFunction("degrees", new DegreesFunction());
addFunction("haversin", new HaversinFunction());
addFunction("pi", new PiFunction());
addFunction("radians", new RadiansFunction());
addFunction("sin", new SinFunction());
addFunction("tan", new TanFunction());
// predicate
addFunction("all", new AllFunction());
addFunction("any", new AnyFunction());
addFunction("exists", new ExistsFunction());
addFunction("none", new NoneFunction());
addFunction("single", new SingleFunction());
// scalar
addFunction("coalesce", new CoalesceFunction());
addFunction("endNode", new EndNodeFunction());
addFunction("head", new HeadFunction());
addFunction("id", new IdFunction());
addFunction("last", new LastFunction());
addFunction("length", new LengthFunction());
addFunction("properties", new PropertiesFunction());
addFunction("size", new SizeFunction());
addFunction("startNode", new StartNodeFunction());
addFunction("timestamp", new TimestampFunction());
addFunction("toBoolean", new ToBooleanFunction());
addFunction("toFloat", new ToFloatFunction());
addFunction("toInteger", new ToIntegerFunction());
addFunction("type", new TypeFunction());
// spatial
addFunction("distance", new DistanceFunction());
addFunction("point", new PointFunction());
// string
addFunction("left", new LeftFunction());
addFunction("lTrim", new LTrimFunction());
addFunction("replace", new ReplaceFunction());
addFunction("reverse", new ReverseFunction());
addFunction("right", new RightFunction());
addFunction("rTrim", new RTrimFunction());
addFunction("split", new SplitFunction());
addFunction("substring", new SubstringFunction());
addFunction("toLower", new ToLowerFunction());
addFunction("lower", new ToLowerFunction());
addFunction("toString", new ToStringFunction());
addFunction("toUpper", new ToUpperFunction());
addFunction("upper", new ToUpperFunction());
addFunction("trim", new TrimFunction());
this.resultWriter = new CypherResultWriter();
this.expressionExecutor = new ExpressionExecutor();
this.createClauseExecutor = new CreateClauseExecutor(expressionExecutor);
this.returnClauseExecutor = new ReturnClauseExecutor(expressionExecutor);
this.matchClauseExecutor = new MatchClauseExecutor();
this.unwindClauseExecutor = new UnwindClauseExecutor(expressionExecutor);
this.withClauseExecutor = new WithClauseExecutor();
this.mergeClauseExecutor = new MergeClauseExecutor();
this.deleteClauseExecutor = new DeleteClauseExecutor(expressionExecutor);
this.setClauseExecutor = new SetClauseExecutor();
this.removeClauseExecutor = new RemoveClauseExecutor();
}
public Graph getGraph() {
return graph;
}
public abstract Visibility calculateVertexVisibility(CypherNodePattern nodePattern, ExpressionScope scope);
public Authorizations getAuthorizations() {
return authorizations;
}
public abstract String getLabelPropertyName();
public abstract <T extends Element> void setLabelProperty(ElementMutation<T> m, String label);
public abstract void removeLabel(ExistingElementMutation<Vertex> vertex, String label);
public abstract <T extends Element> void setProperty(ElementMutation<T> m, String propertyName, Object value);
public abstract void removeProperty(ElementMutation<Element> m, String propertyName);
public abstract String calculateEdgeLabel(
CypherRelationshipPattern relationshipPattern,
Vertex outVertex,
Vertex inVertex,
ExpressionScope scope
);
public abstract Visibility calculateEdgeVisibility(
CypherRelationshipPattern relationshipPattern,
Vertex outVertex,
Vertex inVertex,
ExpressionScope scope
);
public abstract boolean isLabelProperty(Property property);
public abstract Set<String> getVertexLabels(Vertex vertex);
public void setParameter(String name, Object value) {
parameters.put(name, value);
}
public CypherFunction getFunction(String functionName) {
return functions.get(functionName.toLowerCase());
}
public void deleteEdge(Edge edge) {
getGraph().deleteEdge(edge, getAuthorizations());
}
public void deleteVertex(Vertex vertex) {
getGraph().deleteVertex(vertex, getAuthorizations());
}
public Edge saveEdge(ElementMutation<Edge> m) {
return m.save(getAuthorizations());
}
public Vertex saveVertex(ElementMutation<Vertex> m) {
return m.save(getAuthorizations());
}
@SuppressWarnings("unchecked")
public <T extends Element> void saveElement(ExistingElementMutation<T> m) {
if (m.getElement() instanceof Edge) {
saveEdge((ElementMutation<Edge>) m);
} else if (m.getElement() instanceof Vertex) {
saveVertex((ElementMutation<Vertex>) m);
} else {
throw new VertexiumException("unexpected element type: " + m.getElement().getClass().getName());
}
}
public ExpressionExecutor getExpressionExecutor() {
return expressionExecutor;
}
public CreateClauseExecutor getCreateClauseExecutor() {
return createClauseExecutor;
}
public ReturnClauseExecutor getReturnClauseExecutor() {
return returnClauseExecutor;
}
public MatchClauseExecutor getMatchClauseExecutor() {
return matchClauseExecutor;
}
public UnwindClauseExecutor getUnwindClauseExecutor() {
return unwindClauseExecutor;
}
public WithClauseExecutor getWithClauseExecutor() {
return withClauseExecutor;
}
public MergeClauseExecutor getMergeClauseExecutor() {
return mergeClauseExecutor;
}
public DeleteClauseExecutor getDeleteClauseExecutor() {
return deleteClauseExecutor;
}
public SetClauseExecutor getSetClauseExecutor() {
return setClauseExecutor;
}
public RemoveClauseExecutor getRemoveClauseExecutor() {
return removeClauseExecutor;
}
public CypherResultWriter getResultWriter() {
return resultWriter;
}
public Map<String, Object> getParameters() {
return parameters;
}
public Map<String, CypherFunction> getFunctions() {
return functions;
}
public void addFunction(String name, CypherFunction fn) {
this.functions.put(name.toLowerCase(), fn);
}
public Set<String> getKeys(Element element) {
Set<String> results = new HashSet<>();
for (Property property : element.getProperties()) {
if (!isLabelProperty(property)) {
results.add(property.getName());
}
}
return results;
}
public Map<String, Object> getElementPropertiesAsMap(Element element) {
return stream(element.getProperties())
.filter(p -> !isLabelProperty(p))
.collect(Collectors.toMap(Property::getName, Property::getValue));
}
public EnumSet<FetchHint> getFetchHints() {
return FetchHint.ALL;
}
public abstract int getMaxUnboundedRange();
public String calculateVertexId(CypherNodePattern nodePattern, ExpressionScope scope) {
return null;
}
public String calculateEdgeId(CypherRelationshipPattern relationshipPattern, ExpressionScope scope) {
return null;
}
public String normalizeLabelName(String labelName) {
return labelName;
}
public String normalizePropertyName(String propertyName) {
return propertyName;
}
}