Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.vertexium.cypher.executor.CreateClauseExecutor Maven / Gradle / Ivy
package org.vertexium.cypher.executor;
import org.vertexium.*;
import org.vertexium.cypher.VertexiumCypherQueryContext;
import org.vertexium.cypher.VertexiumCypherScope;
import org.vertexium.cypher.ast.model.*;
import org.vertexium.mutation.ElementMutation;
import org.vertexium.mutation.ExistingElementMutation;
import org.vertexium.util.VertexiumLogger;
import org.vertexium.util.VertexiumLoggerFactory;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class CreateClauseExecutor {
private static final VertexiumLogger LOGGER = VertexiumLoggerFactory.getLogger(CreateClauseExecutor.class);
private final ExpressionExecutor expressionExecutor;
public CreateClauseExecutor(ExpressionExecutor expressionExecutor) {
this.expressionExecutor = expressionExecutor;
}
public VertexiumCypherScope execute(VertexiumCypherQueryContext ctx, CypherCreateClause clause, VertexiumCypherScope scope) {
LOGGER.debug("execute: %s", clause);
scope.run(); // materialize existing scope to prevent new items being returned as if they matched the previous step
Stream results = scope.stream()
.map(item -> executeCreate(ctx, clause, item));
return VertexiumCypherScope.newItemsScope(results, scope);
}
private VertexiumCypherScope.Item executeCreate(
VertexiumCypherQueryContext ctx,
CypherCreateClause createClause,
VertexiumCypherScope.Item item
) {
LinkedHashMap map = new LinkedHashMap<>();
for (CypherPatternPart cypherPatternPart : createClause.getPatternParts()) {
LinkedHashMap patternPartResult = executePatternPart(
ctx,
cypherPatternPart,
VertexiumCypherScope.newMapItem(map, item)
);
map.putAll(patternPartResult);
}
return VertexiumCypherScope.newMapItem(map, item);
}
public LinkedHashMap executePatternPart(
VertexiumCypherQueryContext ctx,
CypherPatternPart cypherPatternPart,
VertexiumCypherScope.Item item
) {
LinkedHashMap elements = new LinkedHashMap<>();
Vertex lastVertex = null;
CypherRelationshipPattern lastRelationshipPattern = null;
for (CypherElementPattern cypherElementPattern : cypherPatternPart.getElementPatterns()) {
if (cypherElementPattern instanceof CypherNodePattern) {
Vertex vertex = null;
String elementName = cypherElementPattern.getName();
if (elementName != null) {
vertex = lookupExistingElement(elementName, elements, Vertex.class, item);
}
if (vertex == null) {
vertex = executeCreateVertex(ctx, (CypherNodePattern) cypherElementPattern, item);
if (elementName != null) {
elements.put(elementName, vertex);
}
} else {
executeUpdateVertex(ctx, (CypherNodePattern) cypherElementPattern, vertex, item);
}
if (lastVertex != null && lastRelationshipPattern != null) {
Edge edge = null;
String edgeName = lastRelationshipPattern.getName();
if (edgeName != null) {
edge = lookupExistingElement(edgeName, elements, Edge.class, item);
}
if (edge == null) {
edge = executeCreateEdge(ctx, lastRelationshipPattern, lastVertex, vertex, item);
if (edgeName != null) {
elements.put(edgeName, edge);
}
}
}
lastVertex = vertex;
} else if (cypherElementPattern instanceof CypherRelationshipPattern) {
lastRelationshipPattern = (CypherRelationshipPattern) cypherElementPattern;
} else {
throw new VertexiumException("Unexpected element pattern: " + cypherElementPattern.getClass().getName());
}
}
return elements;
}
private T lookupExistingElement(
String name,
Map elements,
Class resultType,
ExpressionScope scope
) {
Element element;
if (scope == null) {
return null;
}
element = elements.get(name);
if (element == null) {
Object obj = scope.getByName(name);
if (obj instanceof Stream) {
Stream> stream = (Stream>) obj;
obj = stream.collect(Collectors.toList());
}
if (obj instanceof List) {
List list = (List) obj;
if (list.size() == 0) {
return null;
}
if (list.size() == 1) {
obj = list.get(0);
}
}
if (obj != null && !(obj instanceof Element)) {
throw new VertexiumException("Expected Element with name \"" + name + "\", found \"" + obj.getClass().getName() + "\"");
}
element = (Element) obj;
}
if (element == null) {
return null;
}
return resultType.cast(element);
}
private Edge executeCreateEdge(
VertexiumCypherQueryContext ctx,
CypherRelationshipPattern relationshipPattern,
Vertex leftVertex,
Vertex rightVertex,
VertexiumCypherScope.Item item
) {
CypherDirection direction = relationshipPattern.getDirection();
Vertex outVertex;
Vertex inVertex;
if (direction == CypherDirection.OUT) {
outVertex = leftVertex;
inVertex = rightVertex;
} else if (direction == CypherDirection.IN) {
outVertex = rightVertex;
inVertex = leftVertex;
} else {
throw new VertexiumException("unexpected direction: " + direction);
}
String edgeId = ctx.calculateEdgeId(relationshipPattern, item);
String label = ctx.calculateEdgeLabel(relationshipPattern, outVertex, inVertex, item);
label = ctx.normalizeLabelName(label);
Visibility visibility = ctx.calculateEdgeVisibility(relationshipPattern, outVertex, inVertex, item);
EdgeBuilder m = ctx.getGraph().prepareEdge(edgeId, outVertex, inVertex, label, visibility);
setPropertiesOnElement(ctx, m, relationshipPattern, item);
return ctx.saveEdge(m);
}
private Vertex executeCreateVertex(
VertexiumCypherQueryContext ctx,
CypherNodePattern nodePattern,
VertexiumCypherScope.Item item
) {
String vertexId = ctx.calculateVertexId(nodePattern, item);
Visibility vertexVisibility = ctx.calculateVertexVisibility(nodePattern, item);
VertexBuilder m = ctx.getGraph().prepareVertex(vertexId, vertexVisibility);
updateVertex(ctx, m, nodePattern, item);
return ctx.saveVertex(m);
}
private void executeUpdateVertex(
VertexiumCypherQueryContext ctx,
CypherNodePattern nodePattern,
Vertex vertex,
VertexiumCypherScope.Item item
) {
ExistingElementMutation m = vertex.prepareMutation();
updateVertex(ctx, m, nodePattern, item);
ctx.saveVertex(m);
}
private void updateVertex(
VertexiumCypherQueryContext ctx,
ElementMutation m,
CypherNodePattern nodePattern,
VertexiumCypherScope.Item item
) {
for (CypherLabelName label : nodePattern.getLabelNames()) {
String labelName = ctx.normalizeLabelName(label.getValue());
ctx.setLabelProperty(m, labelName);
}
setPropertiesOnElement(ctx, m, nodePattern, item);
}
private void setPropertiesOnElement(
VertexiumCypherQueryContext ctx,
ElementMutation m,
CypherElementPattern elementPattern,
VertexiumCypherScope.Item item
) {
for (Map.Entry property : elementPattern.getPropertiesMap().entrySet()) {
String propertyName = ctx.normalizePropertyName(property.getKey());
CypherAstBase propertyValue = property.getValue();
Object value = toObject(ctx, propertyValue, item);
if (value != null) {
ctx.setProperty(m, propertyName, value);
}
}
}
private Object toObject(VertexiumCypherQueryContext ctx, CypherAstBase expression, VertexiumCypherScope.Item item) {
return expressionExecutor.executeExpression(ctx, expression, item);
}
}