All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.vertexium.cypher.executor.SetClauseExecutor Maven / Gradle / Ivy

There is a newer version: 4.10.0
Show newest version
package org.vertexium.cypher.executor;

import org.vertexium.Element;
import org.vertexium.Property;
import org.vertexium.Vertex;
import org.vertexium.cypher.VertexiumCypherQueryContext;
import org.vertexium.cypher.VertexiumCypherScope;
import org.vertexium.cypher.ast.model.*;
import org.vertexium.cypher.exceptions.VertexiumCypherNotImplemented;
import org.vertexium.cypher.exceptions.VertexiumCypherTypeErrorException;
import org.vertexium.mutation.ExistingElementMutation;
import org.vertexium.util.VertexiumLogger;
import org.vertexium.util.VertexiumLoggerFactory;

import java.util.List;
import java.util.Map;

public class SetClauseExecutor {
    private static final VertexiumLogger LOGGER = VertexiumLoggerFactory.getLogger(SetClauseExecutor.class);

    public VertexiumCypherScope execute(VertexiumCypherQueryContext ctx, CypherSetClause clause, VertexiumCypherScope scope) {
        LOGGER.debug("execute: %s", clause);
        scope.stream()
                .forEach(item -> execute(ctx, clause, item));
        return scope;
    }

    public void execute(VertexiumCypherQueryContext ctx, CypherSetClause clause, VertexiumCypherScope.Item item) {
        clause.getSetItems().forEach(setItem -> {
            if (setItem instanceof CypherSetNodeLabels) {
                executeSetNodeLabels(ctx, (CypherSetNodeLabels) setItem, item);
            } else if (setItem instanceof CypherSetProperty) {
                executeSetProperty(ctx, (CypherSetProperty) setItem, item);
            } else if (setItem instanceof CypherSetVariable) {
                executeSetVariable(ctx, (CypherSetVariable) setItem, item);
            } else {
                throw new VertexiumCypherTypeErrorException(
                        setItem,
                        CypherSetNodeLabels.class,
                        CypherSetProperty.class,
                        CypherSetVariable.class
                );
            }
        });
    }

    private void executeSetVariable(
            VertexiumCypherQueryContext ctx,
            CypherSetVariable setItem,
            VertexiumCypherScope.Item item
    ) {
        Object left = ctx.getExpressionExecutor().executeExpression(ctx, setItem.getLeft(), item);
        VertexiumCypherTypeErrorException.assertType(left, Element.class, null);
        if (left == null) {
            return;
        }

        Object values = ctx.getExpressionExecutor().executeExpression(ctx, setItem.getRight(), item);
        CypherSetItem.Op op = setItem.getOp();

        if (values instanceof List && ((List) values).size() == 1) {
            values = ((List) values).get(0);
        }
        VertexiumCypherTypeErrorException.assertType(values, Map.class, Element.class);

        if (values instanceof Element) {
            values = ctx.getElementPropertiesAsMap((Element) values);
        }

        Element element = (Element) left;
        //noinspection unchecked
        Map valuesMap = (Map) values;

        ExistingElementMutation m = element.prepareMutation();

        if (op == CypherSetItem.Op.EQUAL) {
            for (Property property : element.getProperties()) {
                if (ctx.isLabelProperty(property)) {
                    continue;
                }
                if (!valuesMap.containsKey(property.getName())) {
                    ctx.removeProperty(m, property.getName());
                }
            }
        }

        for (Map.Entry valuesMapEntry : valuesMap.entrySet()) {
            String propertyName = valuesMapEntry.getKey();
            Object value = valuesMapEntry.getValue();
            if (value instanceof CypherLiteral) {
                value = ((CypherLiteral) value).getValue();
            }
            if (value == null) {
                ctx.removeProperty(m, propertyName);
            } else {
                ctx.setProperty(m, propertyName, value);
            }
        }

        ctx.saveElement(m);
    }

    private void executeSetProperty(
            VertexiumCypherQueryContext ctx,
            CypherSetProperty setItem,
            VertexiumCypherScope.Item item
    ) {
        Object left = ctx.getExpressionExecutor().executeExpression(ctx, setItem.getLeft().getAtom(), item);
        VertexiumCypherTypeErrorException.assertType(left, Element.class, null);
        if (left == null) {
            return;
        }

        String propertyName = setItem.getLeft().getProperty();
        Object value = ctx.getExpressionExecutor().executeExpression(ctx, setItem.getRight(), item);

        Element element = (Element) left;
        ExistingElementMutation m = element.prepareMutation();
        switch (setItem.getOp()) {
            case EQUAL:
                if (value == null) {
                    ctx.removeProperty(m, propertyName);
                } else {
                    ctx.setProperty(m, propertyName, value);
                }
                break;
            default:
                throw new VertexiumCypherNotImplemented("" + setItem);
        }
        ctx.saveElement(m);
    }

    private void executeSetNodeLabels(
            VertexiumCypherQueryContext ctx,
            CypherSetNodeLabels setItem,
            VertexiumCypherScope.Item item
    ) {
        Object left = ctx.getExpressionExecutor().executeExpression(ctx, setItem.getLeft(), item);
        VertexiumCypherTypeErrorException.assertType(left, Vertex.class, null);
        if (left == null) {
            return;
        }

        Vertex vertex = (Vertex) left;
        ExistingElementMutation m = vertex.prepareMutation();
        for (CypherLabelName labelName : setItem.getRight()) {
            ctx.setLabelProperty(m, labelName.getValue());
        }
        ctx.saveVertex(m);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy