org.apache.streams.neo4j.CypherQueryGraphHelper.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.streams.neo4j.CypherQueryGraphHelper.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.apache.streams.neo4j;

import org.apache.streams.graph.QueryGraphHelper;
import org.apache.streams.jackson.StreamsJacksonMapper;
import org.apache.streams.pojo.json.Activity;
import org.apache.streams.pojo.json.ActivityObject;
import org.apache.streams.util.PropertyUtil;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;

import org.apache.commons.lang3.StringEscapeUtils;
import org.javatuples.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.stringtemplate.v4.ST;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * Supporting class for interacting with neo4j via rest API
 */
public class CypherQueryGraphHelper implements QueryGraphHelper, Serializable {

    private static final ObjectMapper MAPPER = StreamsJacksonMapper.getInstance();

    private static final Logger LOGGER = LoggerFactory.getLogger(CypherQueryGraphHelper.class);

    public static final String getVertexLongIdStatementTemplate = "MATCH (v) WHERE ID(v) = <id> RETURN v";
    public static final String getVertexStringIdStatementTemplate = "MATCH (v {id: '<id>'} ) RETURN v";
    public static final String getVerticesLabelIdStatementTemplate = "MATCH (v:<type>) RETURN v";

    public final static String createVertexStatementTemplate = "MATCH (x {id: '<id>'}) "
            + "CREATE UNIQUE (v:`<type>` { props }) " + "ON CREATE SET v <labels> " + "RETURN v";

    public final static String mergeVertexStatementTemplate = "MERGE (v:`<type>` {id: '<id>'}) "
            + "ON CREATE SET v <labels>, v = { props }, v.`@timestamp` = timestamp() "
            + "ON MATCH SET v <labels>, v = { props }, v.`@timestamp` = timestamp() " + "RETURN v";

    public final static String createEdgeStatementTemplate = "MATCH (s:`<s_type>` {id: '<s_id>'}),(d:`<d_type>` {id: '<d_id>'}) "
            + "CREATE UNIQUE (s)-[r:`<r_type>` <r_props>]->(d) " + "RETURN r";

    public Pair<String, Map<String, Object>> getVertexRequest(String streamsId) {

        ST getVertex = new ST(getVertexStringIdStatementTemplate);
        getVertex.add("id", streamsId);

        Pair<String, Map<String, Object>> queryPlusParameters = new Pair(getVertex.render(), null);

        LOGGER.debug("getVertexRequest", queryPlusParameters.toString());

        return queryPlusParameters;
    }

    /**
     * getVertexRequest.
     * @param vertexId numericId
     * @return pair (streamsId, parameterMap)
     */
    public Pair<String, Map<String, Object>> getVertexRequest(Long vertexId) {

        ST getVertex = new ST(getVertexLongIdStatementTemplate);
        getVertex.add("id", vertexId);

        Pair<String, Map<String, Object>> queryPlusParameters = new Pair(getVertex.render(), null);

        LOGGER.debug("getVertexRequest", queryPlusParameters.toString());

        return queryPlusParameters;

    }

    /**
     * createVertexRequest.
     * @param activityObject activityObject
     * @return pair (query, parameterMap)
     */
    public Pair<String, Map<String, Object>> createVertexRequest(ActivityObject activityObject) {

        Objects.requireNonNull(activityObject.getObjectType());

        List<String> labels = getLabels(activityObject);

        ST createVertex = new ST(createVertexStatementTemplate);
        createVertex.add("id", activityObject.getId());
        createVertex.add("type", activityObject.getObjectType());

        if (labels.size() > 0) {
            createVertex.add("labels", String.join(" ", labels));
        }

        String query = createVertex.render();

        ObjectNode object = MAPPER.convertValue(activityObject, ObjectNode.class);
        Map<String, Object> props = PropertyUtil.flattenToMap(object, '.');

        Pair<String, Map<String, Object>> queryPlusParameters = new Pair(createVertex.render(), props);

        LOGGER.debug("createVertexRequest: ({},{})", query, props);

        return queryPlusParameters;
    }

    /**
     * getVerticesRequest gets all vertices with a label.
     * @param labelId labelId
     * @return pair (query, parameterMap)
     */
    public Pair<String, Map<String, Object>> getVerticesRequest(String labelId) {
        ST getVertex = new ST(getVerticesLabelIdStatementTemplate);
        getVertex.add("type", labelId);

        Pair<String, Map<String, Object>> queryPlusParameters = new Pair(getVertex.render(), null);

        LOGGER.debug("getVertexRequest", queryPlusParameters.toString());

        return queryPlusParameters;
    }

    /**
     * mergeVertexRequest.
     * @param activityObject activityObject
     * @return pair (query, parameterMap)
     */
    public Pair<String, Map<String, Object>> mergeVertexRequest(ActivityObject activityObject) {

        Objects.requireNonNull(activityObject.getObjectType());

        Pair queryPlusParameters = new Pair(null, new HashMap<>());

        List<String> labels = getLabels(activityObject);

        ST mergeVertex = new ST(mergeVertexStatementTemplate);
        mergeVertex.add("id", activityObject.getId());
        mergeVertex.add("type", activityObject.getObjectType());
        if (labels.size() > 0) {
            mergeVertex.add("labels", String.join(" ", labels));
        }
        String query = mergeVertex.render();

        ObjectNode object = MAPPER.convertValue(activityObject, ObjectNode.class);
        Map<String, Object> props = PropertyUtil.flattenToMap(object, '.');

        LOGGER.debug("mergeVertexRequest: ({},{})", query, props);

        queryPlusParameters = queryPlusParameters.setAt0(query);
        queryPlusParameters = queryPlusParameters.setAt1(props);

        return queryPlusParameters;
    }

    /**
     * createActorObjectEdge.
     * @param activity activity
     * @return pair (query, parameterMap)
     */
    public Pair<String, Map<String, Object>> createActorObjectEdge(Activity activity) {

        Pair queryPlusParameters = new Pair(null, new HashMap<>());

        ObjectNode object = MAPPER.convertValue(activity, ObjectNode.class);
        Map<String, Object> props = PropertyUtil.flattenToMap(object, '.');

        ST mergeEdge = new ST(createEdgeStatementTemplate);
        mergeEdge.add("s_id", activity.getActor().getId());
        mergeEdge.add("s_type", activity.getActor().getObjectType());
        mergeEdge.add("d_id", activity.getObject().getId());
        mergeEdge.add("d_type", activity.getObject().getObjectType());
        mergeEdge.add("r_id", activity.getId());
        mergeEdge.add("r_type", activity.getVerb());
        mergeEdge.add("r_props", getActorObjectEdgePropertyCreater(props));

        String statement = mergeEdge.render();
        queryPlusParameters = queryPlusParameters.setAt0(statement);
        queryPlusParameters = queryPlusParameters.setAt1(props);

        LOGGER.debug("createActorObjectEdge: ({},{})", statement, props);

        return queryPlusParameters;
    }

    /**
     * createActorTargetEdge.
     * @param activity activity
     * @return pair (query, parameterMap)
     */
    public Pair<String, Map<String, Object>> createActorTargetEdge(Activity activity) {

        Pair queryPlusParameters = new Pair(null, new HashMap<>());

        ObjectNode object = MAPPER.convertValue(activity, ObjectNode.class);
        Map<String, Object> props = PropertyUtil.flattenToMap(object, '.');

        ST mergeEdge = new ST(createEdgeStatementTemplate);
        mergeEdge.add("s_id", activity.getActor().getId());
        mergeEdge.add("s_type", activity.getActor().getObjectType());
        mergeEdge.add("d_id", activity.getTarget().getId());
        mergeEdge.add("d_type", activity.getTarget().getObjectType());
        mergeEdge.add("r_id", activity.getId());
        mergeEdge.add("r_type", activity.getVerb());
        mergeEdge.add("r_props", getActorTargetEdgePropertyCreater(props));

        String statement = mergeEdge.render();
        queryPlusParameters = queryPlusParameters.setAt0(statement);
        queryPlusParameters = queryPlusParameters.setAt1(props);

        LOGGER.debug("createActorObjectEdge: ({},{})", statement, props);

        return queryPlusParameters;
    }

    /**
     * getPropertyValueSetter.
     * @param map paramMap
     * @return PropertyValueSetter string
     */
    public static String getPropertyValueSetter(Map<String, Object> map, String symbol) {
        StringBuilder builder = new StringBuilder();
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            if (entry.getValue() instanceof String) {
                String propVal = (String) (entry.getValue());
                builder.append("," + symbol + ".`" + entry.getKey() + "` = '"
                        + StringEscapeUtils.escapeJava(propVal) + "'");
            }
        }
        return builder.toString();
    }

    /**
     * getPropertyParamSetter.
     * @param map paramMap
     * @return PropertyParamSetter string
     */
    public static String getPropertyParamSetter(Map<String, Object> map, String symbol) {
        StringBuilder builder = new StringBuilder();
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            if (entry.getValue() instanceof String) {
                String propVal = (String) (entry.getValue());
                builder.append("," + symbol + ".`" + entry.getKey() + "` = '"
                        + StringEscapeUtils.escapeJava(propVal) + "'");
            }
        }
        return builder.toString();
    }

    /**
     * getPropertyCreater.
     * @param map paramMap
     * @return PropertyCreater string
     */
    public static String getPropertyCreater(Map<String, Object> map) {
        StringBuilder builder = new StringBuilder();
        builder.append("{ ");
        List<String> parts = new ArrayList<>();
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            if (entry.getValue() instanceof String) {
                String propVal = (String) (entry.getValue());
                parts.add("`" + entry.getKey() + "`:'" + StringEscapeUtils.escapeJava(propVal) + "'");
            }
        }
        builder.append(String.join(" ", parts));
        builder.append(" }");
        return builder.toString();
    }

    private String getActorObjectEdgePropertyCreater(Map<String, Object> map) {
        StringBuilder builder = new StringBuilder();
        builder.append("{ ");
        List<String> parts = new ArrayList<>();
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            if (entry.getValue() instanceof String) {
                String propVal = (String) (entry.getValue());
                if (!entry.getKey().contains(".")) {
                    parts.add("`" + entry.getKey() + "`: '" + StringEscapeUtils.escapeJava(propVal) + "'");
                }
            }
        }
        builder.append(String.join(", ", parts));
        builder.append(" }");
        return builder.toString();
    }

    private String getActorTargetEdgePropertyCreater(Map<String, Object> map) {
        StringBuilder builder = new StringBuilder();
        builder.append("{ ");
        List<String> parts = new ArrayList<>();
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            if (entry.getValue() instanceof String) {
                String propVal = (String) (entry.getValue());
                if (!entry.getKey().contains(".")) {
                    parts.add("`" + entry.getKey() + "`: '" + StringEscapeUtils.escapeJava(propVal) + "'");
                } else if (entry.getKey().startsWith("object.") && !entry.getKey().contains(".id")) {
                    parts.add("`" + entry.getKey().substring("object.".length()) + "`: '"
                            + StringEscapeUtils.escapeJava(propVal) + "'");
                }
            }
        }
        builder.append(String.join(", ", parts));
        builder.append(" }");
        return builder.toString();
    }

    /**
     * getLabels.
     * @param activityObject activityObject
     * @return PropertyCreater string
     */
    public static List<String> getLabels(ActivityObject activityObject) {
        List<String> labels = Collections.singletonList(":streams");
        if (activityObject.getAdditionalProperties().containsKey("labels")) {
            List<String> extraLabels = (List<String>) activityObject.getAdditionalProperties().get("labels");
            for (String extraLabel : extraLabels) {
                labels.add(":" + extraLabel);
            }
        }
        return labels;
    }

}