diff --git a/conf/zeppelin-site.xml.template b/conf/zeppelin-site.xml.template
index abaff304b2d..1465102b62a 100755
--- a/conf/zeppelin-site.xml.template
+++ b/conf/zeppelin-site.xml.template
@@ -208,7 +208,7 @@
zeppelin.interpreters
- org.apache.zeppelin.spark.SparkInterpreter,org.apache.zeppelin.spark.PySparkInterpreter,org.apache.zeppelin.rinterpreter.RRepl,org.apache.zeppelin.rinterpreter.KnitR,org.apache.zeppelin.spark.SparkRInterpreter,org.apache.zeppelin.spark.SparkSqlInterpreter,org.apache.zeppelin.spark.DepInterpreter,org.apache.zeppelin.markdown.Markdown,org.apache.zeppelin.angular.AngularInterpreter,org.apache.zeppelin.shell.ShellInterpreter,org.apache.zeppelin.file.HDFSFileInterpreter,org.apache.zeppelin.flink.FlinkInterpreter,,org.apache.zeppelin.python.PythonInterpreter,org.apache.zeppelin.python.PythonInterpreterPandasSql,org.apache.zeppelin.python.PythonCondaInterpreter,org.apache.zeppelin.python.PythonDockerInterpreter,org.apache.zeppelin.lens.LensInterpreter,org.apache.zeppelin.ignite.IgniteInterpreter,org.apache.zeppelin.ignite.IgniteSqlInterpreter,org.apache.zeppelin.cassandra.CassandraInterpreter,org.apache.zeppelin.geode.GeodeOqlInterpreter,org.apache.zeppelin.jdbc.JDBCInterpreter,org.apache.zeppelin.kylin.KylinInterpreter,org.apache.zeppelin.elasticsearch.ElasticsearchInterpreter,org.apache.zeppelin.scalding.ScaldingInterpreter,org.apache.zeppelin.alluxio.AlluxioInterpreter,org.apache.zeppelin.hbase.HbaseInterpreter,org.apache.zeppelin.livy.LivySparkInterpreter,org.apache.zeppelin.livy.LivyPySparkInterpreter,org.apache.zeppelin.livy.LivyPySpark3Interpreter,org.apache.zeppelin.livy.LivySparkRInterpreter,org.apache.zeppelin.livy.LivySparkSQLInterpreter,org.apache.zeppelin.bigquery.BigQueryInterpreter,org.apache.zeppelin.beam.BeamInterpreter,org.apache.zeppelin.pig.PigInterpreter,org.apache.zeppelin.pig.PigQueryInterpreter,org.apache.zeppelin.scio.ScioInterpreter
+ org.apache.zeppelin.spark.SparkInterpreter,org.apache.zeppelin.spark.PySparkInterpreter,org.apache.zeppelin.rinterpreter.RRepl,org.apache.zeppelin.rinterpreter.KnitR,org.apache.zeppelin.spark.SparkRInterpreter,org.apache.zeppelin.spark.SparkSqlInterpreter,org.apache.zeppelin.spark.DepInterpreter,org.apache.zeppelin.markdown.Markdown,org.apache.zeppelin.angular.AngularInterpreter,org.apache.zeppelin.shell.ShellInterpreter,org.apache.zeppelin.file.HDFSFileInterpreter,org.apache.zeppelin.flink.FlinkInterpreter,,org.apache.zeppelin.python.PythonInterpreter,org.apache.zeppelin.python.PythonInterpreterPandasSql,org.apache.zeppelin.python.PythonCondaInterpreter,org.apache.zeppelin.python.PythonDockerInterpreter,org.apache.zeppelin.lens.LensInterpreter,org.apache.zeppelin.ignite.IgniteInterpreter,org.apache.zeppelin.ignite.IgniteSqlInterpreter,org.apache.zeppelin.cassandra.CassandraInterpreter,org.apache.zeppelin.geode.GeodeOqlInterpreter,org.apache.zeppelin.jdbc.JDBCInterpreter,org.apache.zeppelin.kylin.KylinInterpreter,org.apache.zeppelin.elasticsearch.ElasticsearchInterpreter,org.apache.zeppelin.scalding.ScaldingInterpreter,org.apache.zeppelin.alluxio.AlluxioInterpreter,org.apache.zeppelin.hbase.HbaseInterpreter,org.apache.zeppelin.livy.LivySparkInterpreter,org.apache.zeppelin.livy.LivyPySparkInterpreter,org.apache.zeppelin.livy.LivyPySpark3Interpreter,org.apache.zeppelin.livy.LivySparkRInterpreter,org.apache.zeppelin.livy.LivySparkSQLInterpreter,org.apache.zeppelin.bigquery.BigQueryInterpreter,org.apache.zeppelin.beam.BeamInterpreter,org.apache.zeppelin.pig.PigInterpreter,org.apache.zeppelin.pig.PigQueryInterpreter,org.apache.zeppelin.scio.ScioInterpreter,org.apache.zeppelin.graph.neo4j.Neo4jCypherInterpreter
Comma separated interpreter configurations. First interpreter become a default
@@ -319,3 +319,4 @@
+
diff --git a/docs/_includes/themes/zeppelin/_navigation.html b/docs/_includes/themes/zeppelin/_navigation.html
index b13ef68542d..02d679f8484 100644
--- a/docs/_includes/themes/zeppelin/_navigation.html
+++ b/docs/_includes/themes/zeppelin/_navigation.html
@@ -66,6 +66,7 @@
Lens
Livy
Markdown
+ Neo4j
Pig
Python
Postgresql, HAWQ
diff --git a/docs/assets/themes/zeppelin/img/docs-img/neo4j-chart-result.png b/docs/assets/themes/zeppelin/img/docs-img/neo4j-chart-result.png
new file mode 100644
index 00000000000..d9dd8219191
Binary files /dev/null and b/docs/assets/themes/zeppelin/img/docs-img/neo4j-chart-result.png differ
diff --git a/docs/assets/themes/zeppelin/img/docs-img/neo4j-network-result.png b/docs/assets/themes/zeppelin/img/docs-img/neo4j-network-result.png
new file mode 100644
index 00000000000..2313d7698a6
Binary files /dev/null and b/docs/assets/themes/zeppelin/img/docs-img/neo4j-network-result.png differ
diff --git a/docs/assets/themes/zeppelin/img/docs-img/neo4j-tabular-result.png b/docs/assets/themes/zeppelin/img/docs-img/neo4j-tabular-result.png
new file mode 100644
index 00000000000..247740bfdb4
Binary files /dev/null and b/docs/assets/themes/zeppelin/img/docs-img/neo4j-tabular-result.png differ
diff --git a/docs/assets/themes/zeppelin/img/docs-img/neo4j-zeppelin-form-select.png b/docs/assets/themes/zeppelin/img/docs-img/neo4j-zeppelin-form-select.png
new file mode 100644
index 00000000000..4b3893bb66f
Binary files /dev/null and b/docs/assets/themes/zeppelin/img/docs-img/neo4j-zeppelin-form-select.png differ
diff --git a/docs/assets/themes/zeppelin/img/docs-img/neo4j-zeppelin-form-text-input.png b/docs/assets/themes/zeppelin/img/docs-img/neo4j-zeppelin-form-text-input.png
new file mode 100644
index 00000000000..55976603640
Binary files /dev/null and b/docs/assets/themes/zeppelin/img/docs-img/neo4j-zeppelin-form-text-input.png differ
diff --git a/docs/assets/themes/zeppelin/img/docs-img/zeppelin-network-display-customization.png b/docs/assets/themes/zeppelin/img/docs-img/zeppelin-network-display-customization.png
new file mode 100644
index 00000000000..e7aab5c7655
Binary files /dev/null and b/docs/assets/themes/zeppelin/img/docs-img/zeppelin-network-display-customization.png differ
diff --git a/docs/assets/themes/zeppelin/img/docs-img/zeppelin-switch-chart-network.png b/docs/assets/themes/zeppelin/img/docs-img/zeppelin-switch-chart-network.png
new file mode 100644
index 00000000000..c439dbf4c46
Binary files /dev/null and b/docs/assets/themes/zeppelin/img/docs-img/zeppelin-switch-chart-network.png differ
diff --git a/docs/assets/themes/zeppelin/img/screenshots/display_network.png b/docs/assets/themes/zeppelin/img/screenshots/display_network.png
new file mode 100644
index 00000000000..5804a97f126
Binary files /dev/null and b/docs/assets/themes/zeppelin/img/screenshots/display_network.png differ
diff --git a/docs/assets/themes/zeppelin/img/screenshots/display_network1.png b/docs/assets/themes/zeppelin/img/screenshots/display_network1.png
new file mode 100644
index 00000000000..50e021fd637
Binary files /dev/null and b/docs/assets/themes/zeppelin/img/screenshots/display_network1.png differ
diff --git a/docs/assets/themes/zeppelin/img/screenshots/display_network2.png b/docs/assets/themes/zeppelin/img/screenshots/display_network2.png
new file mode 100644
index 00000000000..92e5c869c55
Binary files /dev/null and b/docs/assets/themes/zeppelin/img/screenshots/display_network2.png differ
diff --git a/docs/displaysystem/basicdisplaysystem.md b/docs/displaysystem/basicdisplaysystem.md
index 7c4243208e4..7762dc1f9ab 100644
--- a/docs/displaysystem/basicdisplaysystem.md
+++ b/docs/displaysystem/basicdisplaysystem.md
@@ -60,4 +60,98 @@ If table contents start with `%html`, it is interpreted as an HTML.
+## Network
+
+Zeppelin can render a network following this sample json structure:
+
+```json
+{"nodes" : [{"id" : 1}, {"id" : 2}], "edges" : [{"source" : 2, "target" : 1, "id" : 1 }]}
+```
+
+You can leverage this visualization by using the `%network` directive
+
+
+
+
+
+The network visualization can also leverage the Property Graph with a json structure like this:
+
+```json
+{
+ "nodes": [
+ {
+ "id": 1,
+ "label": "User",
+ "data": {"fullname": "Andrea Santurbano"}
+ },
+ {
+ "id": 2,
+ "label": "User",
+ "data": {"fullname": "Moon soo Lee"}
+ }
+ ],
+ "edges": [
+ {
+ "source": 2,
+ "target": 1,
+ "id": 1,
+ "label": "HELPS",
+ "data": {
+ "project" : "Zeppelin",
+ "githubUrl": "https://github.com/apache/zeppelin/pull/1582"
+ }
+ }
+ ]
+}
+```
+
+
+
+## Network
+
+Zeppelin can render a network following this sample json structure:
+
+```json
+{"nodes" : [{"id" : 1}, {"id" : 2}], "edges" : [{"source" : 2, "target" : 1, "id" : 1 }]}
+```
+
+You can leverage this visualization by using the `%network` directive
+
+
+
+
+
+The network visualization can also leverage the Property Graph with a json structure like this:
+
+```json
+{
+ "nodes": [
+ {
+ "id": 1,
+ "label": "User",
+ "data": {"fullname": "Andrea Santurbano"}
+ },
+ {
+ "id": 2,
+ "label": "User",
+ "data": {"fullname": "Moon soo Lee"}
+ }
+ ],
+ "edges": [
+ {
+ "source": 2,
+ "target": 1,
+ "id": 1,
+ "label": "HELPS",
+ "data": {
+ "project" : "Zeppelin",
+ "githubUrl": "https://github.com/apache/zeppelin/pull/1582"
+ }
+ }
+ ]
+}
+```
+
+
+
> **Note :** Display system is backend independent.
diff --git a/docs/interpreter/neo4j.md b/docs/interpreter/neo4j.md
new file mode 100644
index 00000000000..adb5dca308b
--- /dev/null
+++ b/docs/interpreter/neo4j.md
@@ -0,0 +1,108 @@
+---
+layout: page
+title: "Neo4j Interpreter for Apache Zeppelin"
+description: "Neo4j is a highly scalable, native graph database purpose-built to leverage not only data but also its relationships."
+group: interpreter
+---
+
+{% include JB/setup %}
+
+# Neo4j Interpreter for Apache Zeppelin
+
+
+
+## Overview
+[Neo4j](https://neo4j.com/) is a highly scalable, native graph database purpose-built to leverage not only data but also its relationships.
+Neo4j's native graph storage and processing engine deliver constant, real-time performance, helping enterprises build intelligent applications to meet today’s evolving data challenges.
+
+
+
+ | Name |
+ Class |
+ Description |
+
+
+ | %neo4j |
+ Neo4jCypherInterpreter |
+ Enable the Neo4j intepreter |
+
+
+
+## Configuration
+The Neo4j interpreter can be configured with properties provided by Zeppelin.
+
+
+ | Property |
+ Default |
+ Description |
+
+
+ | neo4j.url |
+ bolt://localhost:7687 |
+ The Neo4j's BOLT url. |
+
+
+ | neo4j.user |
+ neo4j |
+ The Neo4j user name. |
+
+
+ | neo4j.password |
+ neo4j |
+ The Neo4j user password. |
+
+
+ | neo4j.max.concurrency |
+ 50 |
+ Max concurrency call to Neo4j server. |
+
+
+
+## Enabling the Neo4j Interpreter
+In a notebook, to enable the **Neo4j** interpreter, click the **Gear** icon and select **neo4j**.
+
+## Using the Neo4j Interpreter
+In a paragraph, use `%neo4j` to select the Neo4j interpreter and then write your cypher query.
+
+```cypher
+MATCH (u:User)-[p:POSTS]->(t:Tweet) RETURN u, p, t;
+```
+
+The default visualization show the query result as a table. In the tabular result if nodes and relationships are return from the query, they will show together as rows
+
+
+If the query result has almost a node the **Network** button will be enabled so you can switch to the graph visualization
+
+
+
+
+You can still use the other visualization charts provided by zeppelin
+
+
+Leveraging the **settings** button you can customize your graph visualization, a list of nodes will be displayed and by click on each one you can set the property which will be used as node label.
+
+
+### Apply Zeppelin Dynamic Forms
+You can leverage [Zeppelin Dynamic Form](../manual/dynamicform.html) inside your queries. You can use both the `text input` and `select form` parameterization features.
+
+```cypher
+match (n:User{screen_name: '${user_name}'})-[r]-(m:Tweet) return n, r, m limit 10
+```
+
+
+```cypher
+match (n:User{screen_name: '${user_name=santand84,santand84|individue|maurofer79}'})-[r]-(m:Tweet) return n, r, m limit 10
+```
+
diff --git a/neo4j/pom.xml b/neo4j/pom.xml
new file mode 100644
index 00000000000..c97ecefd580
--- /dev/null
+++ b/neo4j/pom.xml
@@ -0,0 +1,137 @@
+
+
+
+
+ 4.0.0
+
+
+ zeppelin
+ org.apache.zeppelin
+ 0.8.0-SNAPSHOT
+ ..
+
+
+ org.apache.zeppelin
+ zeppelin-neo4j
+ jar
+ 0.8.0-SNAPSHOT
+ Zeppelin: Neo4j interpreter
+
+
+ 1.0.4
+ 3.0.4
+ 3.0.4
+
+
+
+
+ ${project.groupId}
+ zeppelin-interpreter
+ ${project.version}
+ provided
+
+
+
+ org.neo4j.driver
+ neo4j-java-driver
+ ${neo4j.driver.version}
+
+
+
+ org.slf4j
+ slf4j-api
+
+
+
+ org.slf4j
+ slf4j-log4j12
+
+
+
+ junit
+ junit
+ test
+
+
+
+ org.neo4j.test
+ neo4j-harness
+ ${neo4j.version}
+ test
+
+
+
+
+
+
+ maven-enforcer-plugin
+ 1.3.1
+
+
+ enforce
+ none
+
+
+
+
+
+ maven-dependency-plugin
+ 2.8
+
+
+ copy-dependencies
+ package
+
+ copy-dependencies
+
+
+ ${project.build.directory}/../../interpreter/neo4j
+ false
+ false
+ true
+ runtime
+
+
+
+ copy-artifact
+ package
+
+ copy
+
+
+ ${project.build.directory}/../../interpreter/neo4j
+ false
+ false
+ true
+ runtime
+
+
+ ${project.groupId}
+ ${project.artifactId}
+ ${project.version}
+ ${project.packaging}
+
+
+
+
+
+
+
+
+
+
diff --git a/neo4j/src/main/java/org/apache/zeppelin/graph/neo4j/Neo4jCypherInterpreter.java b/neo4j/src/main/java/org/apache/zeppelin/graph/neo4j/Neo4jCypherInterpreter.java
new file mode 100644
index 00000000000..efbb42bcb38
--- /dev/null
+++ b/neo4j/src/main/java/org/apache/zeppelin/graph/neo4j/Neo4jCypherInterpreter.java
@@ -0,0 +1,295 @@
+/*
+ * 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 with
+ * the License. You may obtain a copy of the License at
+ *
+ * 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.zeppelin.graph.neo4j;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.zeppelin.graph.neo4j.utils.Neo4jConversionUtils;
+import org.apache.zeppelin.interpreter.Interpreter;
+import org.apache.zeppelin.interpreter.InterpreterContext;
+import org.apache.zeppelin.interpreter.InterpreterResult;
+import org.apache.zeppelin.interpreter.InterpreterResult.Code;
+import org.apache.zeppelin.interpreter.graph.GraphResult;
+import org.apache.zeppelin.interpreter.graph.GraphUtils;
+import org.apache.zeppelin.interpreter.graph.Relationship.Type;
+import org.apache.zeppelin.resource.Resource;
+import org.apache.zeppelin.resource.ResourcePool;
+import org.apache.zeppelin.scheduler.Scheduler;
+import org.apache.zeppelin.scheduler.SchedulerFactory;
+import org.neo4j.driver.internal.InternalNode;
+import org.neo4j.driver.internal.InternalPath;
+import org.neo4j.driver.internal.InternalRelationship;
+import org.neo4j.driver.internal.util.Iterables;
+import org.neo4j.driver.internal.value.ListValue;
+import org.neo4j.driver.internal.value.NodeValue;
+import org.neo4j.driver.internal.value.PathValue;
+import org.neo4j.driver.internal.value.RelationshipValue;
+import org.neo4j.driver.v1.AuthTokens;
+import org.neo4j.driver.v1.Config;
+import org.neo4j.driver.v1.Driver;
+import org.neo4j.driver.v1.GraphDatabase;
+import org.neo4j.driver.v1.Record;
+import org.neo4j.driver.v1.Session;
+import org.neo4j.driver.v1.StatementResult;
+import org.neo4j.driver.v1.types.Node;
+import org.neo4j.driver.v1.types.Relationship;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Neo4j interpreter for Zeppelin.
+ */
+public class Neo4jCypherInterpreter extends Interpreter {
+ static final Logger LOGGER = LoggerFactory.getLogger(Neo4jCypherInterpreter.class);
+
+ public static final String NEO4J_SERVER_URL = "neo4j.url";
+ public static final String NEO4J_SERVER_USER = "neo4j.user";
+ public static final String NEO4J_SERVER_PASSWORD = "neo4j.password";
+ public static final String NEO4J_MAX_CONCURRENCY = "neo4j.max.concurrency";
+
+ private static final String TABLE = "%table";
+ private static final String NEW_LINE = "\n";
+ private static final String TAB = "\t";
+
+ private static final Pattern PROPERTY_PATTERN = Pattern.compile("\\{\\w+\\}");
+ private static final String REPLACE_CURLY_BRACKETS = "\\{|\\}";
+
+ private Driver driver = null;
+
+ private Map labels;
+
+ private Set types;
+
+ public Neo4jCypherInterpreter(Properties properties) {
+ super(properties);
+ }
+
+ private Driver getDriver() {
+ if (driver == null) {
+ Config config = Config.build().withEncryptionLevel(Config.EncryptionLevel.NONE).toConfig();
+ driver = GraphDatabase.driver(getProperty(NEO4J_SERVER_URL),
+ AuthTokens.basic(getProperty(NEO4J_SERVER_USER),
+ getProperty(NEO4J_SERVER_PASSWORD)), config);
+ }
+ return driver;
+ }
+
+ @Override
+ public void open() {
+ getDriver();
+ }
+
+ @Override
+ public void close() {
+ getDriver().close();
+ }
+
+ public Map getLabels(boolean refresh) {
+ if (labels == null || refresh) {
+ Map old = labels == null ?
+ new LinkedHashMap() : new LinkedHashMap<>(labels);
+ labels = new LinkedHashMap<>();
+ try (Session session = getDriver().session()) {
+ StatementResult result = session.run("CALL db.labels()");
+ Set colors = new HashSet<>();
+ while (result.hasNext()) {
+ Record record = result.next();
+ String label = record.get("label").asString();
+ String color = old.get(label);
+ while (color == null || colors.contains(color)) {
+ color = GraphUtils.getRandomColor();
+ }
+ colors.add(color);
+ labels.put(label, color);
+ }
+ }
+ }
+ return labels;
+ }
+
+ private Set getTypes(boolean refresh) {
+ if (types == null || refresh) {
+ types = new HashSet<>();
+ try (Session session = getDriver().session()) {
+ StatementResult result = session.run("CALL db.relationshipTypes()");
+ while (result.hasNext()) {
+ Record record = result.next();
+ types.add(record.get("relationshipType").asString());
+ }
+ }
+ }
+ return types;
+ }
+
+ private void setResultValue(Object value, Set nodes, Set relationships,
+ List line) {
+ if (value instanceof NodeValue
+ || value instanceof InternalNode) {
+ NodeValue nodeVal = value instanceof NodeValue ?
+ (NodeValue) value : (NodeValue) ((InternalNode) value).asValue();
+ nodes.add(nodeVal.asNode());
+ } else if (value instanceof RelationshipValue
+ || value instanceof InternalRelationship) {
+ RelationshipValue relVal = value instanceof RelationshipValue ?
+ (RelationshipValue) value : (RelationshipValue) ((InternalRelationship) value).asValue();
+ relationships.add(relVal.asRelationship());
+ } else if (value instanceof PathValue
+ || value instanceof InternalPath) {
+ PathValue pathVal = value instanceof PathValue ?
+ (PathValue) value : (PathValue) ((InternalPath) value).asValue();
+ nodes.addAll(Iterables.asList(pathVal.asPath().nodes()));
+ relationships.addAll(Iterables.asList(pathVal.asPath().relationships()));
+ } else if (value instanceof ListValue) {
+ ListValue listValues = (ListValue) value;
+ List