org.murygin.neo4j.CypherToJGraphT.java Source code

Java tutorial

Introduction

Here is the source code for org.murygin.neo4j.CypherToJGraphT.java

Source

/*******************************************************************************
 * Copyright (c) 2015 Daniel Murygin.
 *
 * This program is free software: you can redistribute it and/or 
 * modify it under the terms of the GNU Lesser General Public License 
 * as published by the Free Software Foundation, either version 3 
 * of the License, or (at your option) any later version.
 * This program is distributed in the hope that it will be useful,    
 * but WITHOUT ANY WARRANTY; without even the implied warranty 
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
 * See the GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program. 
 * If not, see <http://www.gnu.org/licenses/>.
 * 
 * Contributors:
 *     Daniel Murygin daniel.murygin@gmail.com - initial API and implementation
 ******************************************************************************/
package org.murygin.neo4j;

import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.jgrapht.DirectedGraph;
import org.jgrapht.graph.DirectedPseudograph;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Executes a Cypher on a Neo4j server and returns result as JGraphT graph object.
 * 
 * Getting started:
 * 
 * CypherToJGraphT graphLoader = new CypherToJGraphT();
 * graphLoader.setHost("NEO4J_HOST_NAME");
 * DirectedGraph graph = graphLoader.execute("MATCH n-[r]-() RETURN n,r");
 * 
 * Queries are executed by class {@link CypherToJson}.
 * 
 * See: http://neo4j.com/
 * See: http://neo4j.com/docs/stable/cypher-query-lang.html
 * See: http://jgrapht.org/
 * 
 * @author Daniel Murygin daniel.murygin@gmail.com
 */
public class CypherToJGraphT {

    final Logger LOG = LoggerFactory.getLogger(CypherToJGraphT.class);

    private String protocol = CypherToJson.DEFAULT_PROTOCOL;
    private String host = CypherToJson.DEFAULT_HOST;
    private String port = CypherToJson.DEFAULT_PORT;
    private String path = CypherToJson.DEFAULT_PATH;
    private String query = CypherToJson.DEFAULT_QUERY;

    private DirectedGraph<Node, Edge> graph;
    private Map<String, Node> nodeMap;

    public CypherToJGraphT() {
        super();
        graph = new DirectedPseudograph<Node, Edge>(Edge.class);
    }

    public static void main(String[] args) throws Exception {
        CypherToJGraphT executer = new CypherToJGraphT();
        executer.execute();
    }

    /**
     * Executes a Cypher query.
     * 
     * @param query a Cypher query
     * @return The result of the query as JGraphT graph
     */
    public DirectedGraph<Node, Edge> execute(String query) {
        setQuery(query);
        execute();
        return getGraph();
    }

    /**
     * Executes a Cypher query.
     * Call setQuery(..) before to set the query. 
     * Call getGraph() to return the resukt.
     */
    public void execute() {
        nodeMap = new Hashtable<String, Node>();
        CypherToJson executer = createCypherToJson();
        executer.execute();
        JSONObject json = executer.getJson();
        convertJsonToGraph(json);
        nodeMap.clear();
    }

    private void convertJsonToGraph(JSONObject json) {
        JsonResults jsonResults = new JsonResults(json);
        List<JSONObject> graphList = jsonResults.getGraphList();
        for (JSONObject graphJson : graphList) {
            JSONArray nodes = JsonResults.getJsonArray(graphJson, "nodes");
            addNotes(nodes);
            JSONArray relations = JsonResults.getJsonArray(graphJson, "relationships");
            addRelations(relations);
        }
    }

    private void addNotes(JSONArray nodes) {
        for (Object nodeJson : nodes) {
            Node node = addNode((JSONObject) nodeJson);
            if (node != null) {
                nodeMap.put(node.getId(), node);
            }
        }
    }

    private Node addNode(JSONObject nodeJson) {
        String id = (String) nodeJson.get("id");
        Node node = new Node(id);
        if (!this.graph.containsVertex(node)) {
            addLabels(node, nodeJson);
            addProperties(node, nodeJson);
            boolean added = this.graph.addVertex(node);
            logNode(node, added);
            return node;
        }
        return null;
    }

    private void addRelations(JSONArray relations) {
        for (Object relationObject : relations) {
            JSONObject relation = (JSONObject) relationObject;
            addRelation(relation);
        }
    }

    private void addRelation(JSONObject relation) {
        String sourceodeId = (String) relation.get("startNode");
        String targetNodeId = (String) relation.get("endNode");
        Node sourceNode = nodeMap.get(sourceodeId);
        Node targetNode = nodeMap.get(targetNodeId);
        if (sourceNode != null && targetNode != null) {
            String type = (String) relation.get("type");
            Edge edge = new Edge(sourceNode, targetNode, type);
            addProperties(edge, relation);
            boolean added = this.graph.addEdge(sourceNode, targetNode, edge);
            logEdge(edge, added);
        }
    }

    @SuppressWarnings("rawtypes")
    private void addProperties(IPropertyContainer node, JSONObject nodeJson) {
        JSONObject properties = JsonResults.getJson(nodeJson, "properties");
        Set keys = properties.keySet();
        for (Object keyObject : keys) {
            String key = (String) keyObject;
            String value = (String) properties.get(key);
            node.addProperty(key, value);
            if (LOG.isDebugEnabled()) {
                LOG.debug("Property added: " + key + ":" + value);
            }
        }
    }

    private void addLabels(Node node, JSONObject nodeJson) {
        JSONArray labels = JsonResults.getJsonArray(nodeJson, "labels");
        for (Object labelObject : labels) {
            String label = (String) labelObject;
            node.addLabel(label);
            if (LOG.isDebugEnabled()) {
                LOG.debug("Label added: " + label);
            }
        }
    }

    private CypherToJson createCypherToJson() {
        CypherToJson executer = new CypherToJson();
        executer.setHost(getHost());
        executer.setPath(getPath());
        executer.setPort(getPort());
        executer.setProtocol(getProtocol());
        executer.setQuery(getQuery());
        executer.setResultDataContents(CypherToJson.RESULT_DATA_CONTENT_GRAPH);
        return executer;
    }

    /**
     * @return The result of a query as JGraphT graph
     */
    public DirectedGraph<Node, Edge> getGraph() {
        return graph;
    }

    private void logNode(Node node, boolean added) {
        if (LOG.isInfoEnabled()) {
            if (added) {
                LOG.info("Node added: " + node);
            } else {
                LOG.debug("Node exists: " + node);
            }
        }
    }

    private void logEdge(Edge edge, boolean added) {
        if (LOG.isInfoEnabled()) {
            if (added) {
                LOG.info("Edge added: " + edge);
            } else {
                LOG.debug("Edge exists: " + edge);
            }
        }
    }

    public String getQuery() {
        return query;
    }

    public void setQuery(String query) {
        this.query = query;
    }

    public String getProtocol() {
        return protocol;
    }

    public void setProtocol(String protocol) {
        this.protocol = protocol;
    }

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public String getPort() {
        return port;
    }

    public void setPort(String port) {
        this.port = port;
    }

    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }
}