/* * Copyright 2016 SteelBridge Laboratories, LLC. * * Licensed 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. * * For more information: http://steelbridgelabs.com */ package com.steelbridgelabs.oss.neo4j.structure; import com.steelbridgelabs.oss.neo4j.structure.partitions.NoReadPartition; import com.steelbridgelabs.oss.neo4j.structure.summary.ResultSummaryLogger; import org.apache.commons.configuration.Configuration; import org.apache.tinkerpop.gremlin.process.computer.GraphComputer; import org.apache.tinkerpop.gremlin.structure.Edge; import org.apache.tinkerpop.gremlin.structure.Graph; import org.apache.tinkerpop.gremlin.structure.Transaction; import org.apache.tinkerpop.gremlin.structure.Vertex; import org.apache.tinkerpop.gremlin.structure.util.AbstractThreadLocalTransaction; import org.apache.tinkerpop.gremlin.structure.util.GraphFactoryClass; import org.apache.tinkerpop.gremlin.structure.util.StringFactory; import org.apache.tinkerpop.gremlin.structure.util.TransactionException; import org.neo4j.driver.AccessMode; import org.neo4j.driver.Bookmark; import org.neo4j.driver.Driver; import org.neo4j.driver.Result; import org.neo4j.driver.SessionConfig; import org.neo4j.driver.Value; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.function.Consumer; import java.util.stream.Collectors; /** * @author Rogelio J. Baucells */ @Graph.OptIn(Graph.OptIn.SUITE_STRUCTURE_STANDARD) @Graph.OptIn(Graph.OptIn.SUITE_PROCESS_STANDARD) @GraphFactoryClass(Neo4JGraphFactory.class) public class Neo4JGraph implements Graph { private class Neo4JTransaction extends AbstractThreadLocalTransaction { Neo4JTransaction() { super(Neo4JGraph.this); } @Override protected void doOpen() { // current session Neo4JSession session = Neo4JGraph.this.currentSession(); // open database transaction session.beginTransaction(); } @Override protected void doCommit() throws TransactionException { // current session Neo4JSession session = Neo4JGraph.this.currentSession(); // commit transaction session.commit(); } @Override protected void doRollback() throws TransactionException { // current session Neo4JSession session = Neo4JGraph.this.currentSession(); // rollback transaction session.rollback(); } @Override public boolean isOpen() { // current session Neo4JSession session = Neo4JGraph.this.currentSession(); // check transaction is open return session.isTransactionOpen(); } @Override protected void doClose() { // close base super.doClose(); // current session Neo4JSession session = Neo4JGraph.this.currentSession(); // close transaction session.closeTransaction(); } } private final Neo4JReadPartition partition; private final Set<String> vertexLabels; private final Driver driver; private final String database; private final Neo4JElementIdProvider<?> vertexIdProvider; private final Neo4JElementIdProvider<?> edgeIdProvider; private final ThreadLocal<Neo4JSession> session = ThreadLocal.withInitial(() -> null); private final Neo4JTransaction transaction = new Neo4JTransaction(); private final Configuration configuration; private final boolean readonly; private final Iterable<Bookmark> bookmarks; private final Set<Consumer<Neo4JGraph>> closeListeners = new HashSet<>(); /** * Creates a {@link Neo4JGraph} instance. * * @param driver The {@link Driver} instance with the database connection information. * @param vertexIdProvider The {@link Neo4JElementIdProvider} for the {@link Vertex} id generation. * @param edgeIdProvider The {@link Neo4JElementIdProvider} for the {@link Edge} id generation. */ @Deprecated public Neo4JGraph(Driver driver, Neo4JElementIdProvider<?> vertexIdProvider, Neo4JElementIdProvider<?> edgeIdProvider) { Objects.requireNonNull(driver, "driver cannot be null"); Objects.requireNonNull(vertexIdProvider, "vertexIdProvider cannot be null"); Objects.requireNonNull(edgeIdProvider, "edgeIdProvider cannot be null"); // no label partition this.partition = new NoReadPartition(); this.vertexLabels = Collections.emptySet(); // store driver instance this.driver = driver; // database this.database = null; // store providers this.vertexIdProvider = vertexIdProvider; this.edgeIdProvider = edgeIdProvider; // graph factory configuration (required for tinkerpop test suite) this.configuration = null; // general purpose graph this.readonly = false; this.bookmarks = null; } /** * Creates a {@link Neo4JGraph} instance. * * @param driver The {@link Driver} instance with the database connection information. * @param database The database name. * @param vertexIdProvider The {@link Neo4JElementIdProvider} for the {@link Vertex} id generation. * @param edgeIdProvider The {@link Neo4JElementIdProvider} for the {@link Edge} id generation. */ public Neo4JGraph(Driver driver, String database, Neo4JElementIdProvider<?> vertexIdProvider, Neo4JElementIdProvider<?> edgeIdProvider) { Objects.requireNonNull(driver, "driver cannot be null"); Objects.requireNonNull(vertexIdProvider, "vertexIdProvider cannot be null"); Objects.requireNonNull(edgeIdProvider, "edgeIdProvider cannot be null"); // no label partition this.partition = new NoReadPartition(); this.vertexLabels = Collections.emptySet(); // store driver instance this.driver = driver; // database this.database = database; // store providers this.vertexIdProvider = vertexIdProvider; this.edgeIdProvider = edgeIdProvider; // graph factory configuration (required for tinkerpop test suite) this.configuration = null; // general purpose graph this.readonly = false; this.bookmarks = null; } /** * Creates a {@link Neo4JGraph} instance. * * @param driver The {@link Driver} instance with the database connection information. * @param vertexIdProvider The {@link Neo4JElementIdProvider} for the {@link Vertex} id generation. * @param edgeIdProvider The {@link Neo4JElementIdProvider} for the {@link Edge} id generation. * @param readonly {@code true} indicates the Graph instance will be used to read from the Neo4J database. * @param bookmarks The initial references to some previous transactions. Both null value and empty iterable are permitted, and indicate that the bookmarks do not exist or are unknown. */ @Deprecated public Neo4JGraph(Driver driver, Neo4JElementIdProvider<?> vertexIdProvider, Neo4JElementIdProvider<?> edgeIdProvider, boolean readonly, String... bookmarks) { Objects.requireNonNull(driver, "driver cannot be null"); Objects.requireNonNull(vertexIdProvider, "vertexIdProvider cannot be null"); Objects.requireNonNull(edgeIdProvider, "edgeIdProvider cannot be null"); // no label partition this.partition = new NoReadPartition(); this.vertexLabels = Collections.emptySet(); // store driver instance this.driver = driver; // database this.database = null; // store providers this.vertexIdProvider = vertexIdProvider; this.edgeIdProvider = edgeIdProvider; // graph factory configuration (required for tinkerpop test suite) this.configuration = null; // readonly & bookmarks this.readonly = readonly; this.bookmarks = Collections.singletonList(Bookmark.from(new HashSet<>(Arrays.asList(bookmarks)))); } /** * Creates a {@link Neo4JGraph} instance. * * @param driver The {@link Driver} instance with the database connection information. * @param database The database name. * @param vertexIdProvider The {@link Neo4JElementIdProvider} for the {@link Vertex} id generation. * @param edgeIdProvider The {@link Neo4JElementIdProvider} for the {@link Edge} id generation. * @param readonly {@code true} indicates the Graph instance will be used to read from the Neo4J database. * @param bookmarks The initial references to some previous transactions. Both null value and empty iterable are permitted, and indicate that the bookmarks do not exist or are unknown. */ public Neo4JGraph(Driver driver, String database, Neo4JElementIdProvider<?> vertexIdProvider, Neo4JElementIdProvider<?> edgeIdProvider, boolean readonly, String... bookmarks) { Objects.requireNonNull(driver, "driver cannot be null"); Objects.requireNonNull(vertexIdProvider, "vertexIdProvider cannot be null"); Objects.requireNonNull(edgeIdProvider, "edgeIdProvider cannot be null"); // no label partition this.partition = new NoReadPartition(); this.vertexLabels = Collections.emptySet(); // store driver instance this.driver = driver; // database this.database = database; // store providers this.vertexIdProvider = vertexIdProvider; this.edgeIdProvider = edgeIdProvider; // graph factory configuration (required for tinkerpop test suite) this.configuration = null; // readonly & bookmarks this.readonly = readonly; this.bookmarks = Collections.singletonList(Bookmark.from(new HashSet<>(Arrays.asList(bookmarks)))); } /** * Creates a {@link Neo4JGraph} instance with the given partition within the neo4j database. * * @param partition The {@link Neo4JReadPartition} within the neo4j database. * @param vertexLabels The set of labels to append to vertices created by the {@link Neo4JGraph} session. * @param driver The {@link Driver} instance with the database connection information. * @param vertexIdProvider The {@link Neo4JElementIdProvider} for the {@link Vertex} id generation. * @param edgeIdProvider The {@link Neo4JElementIdProvider} for the {@link Edge} id generation. */ @Deprecated public Neo4JGraph(Neo4JReadPartition partition, String[] vertexLabels, Driver driver, Neo4JElementIdProvider<?> vertexIdProvider, Neo4JElementIdProvider<?> edgeIdProvider) { Objects.requireNonNull(partition, "partition cannot be null"); Objects.requireNonNull(vertexLabels, "vertexLabels cannot be null"); Objects.requireNonNull(driver, "driver cannot be null"); Objects.requireNonNull(vertexIdProvider, "vertexIdProvider cannot be null"); Objects.requireNonNull(edgeIdProvider, "edgeIdProvider cannot be null"); // initialize fields this.partition = partition; this.vertexLabels = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(vertexLabels))); this.driver = driver; // database this.database = null; // validate partition & additional labels if (!partition.containsVertex(this.vertexLabels)) throw new IllegalArgumentException("Invalid vertexLabels, vertices created by the graph will not be part of the given partition"); // store providers this.vertexIdProvider = vertexIdProvider; this.edgeIdProvider = edgeIdProvider; // graph factory configuration (required for tinkerpop test suite) this.configuration = null; // general purpose graph this.readonly = false; this.bookmarks = null; } /** * Creates a {@link Neo4JGraph} instance with the given partition within the neo4j database. * * @param partition The {@link Neo4JReadPartition} within the neo4j database. * @param vertexLabels The set of labels to append to vertices created by the {@link Neo4JGraph} session. * @param driver The {@link Driver} instance with the database connection information. * @param database The database name. * @param vertexIdProvider The {@link Neo4JElementIdProvider} for the {@link Vertex} id generation. * @param edgeIdProvider The {@link Neo4JElementIdProvider} for the {@link Edge} id generation. */ public Neo4JGraph(Neo4JReadPartition partition, String[] vertexLabels, Driver driver, String database, Neo4JElementIdProvider<?> vertexIdProvider, Neo4JElementIdProvider<?> edgeIdProvider) { Objects.requireNonNull(partition, "partition cannot be null"); Objects.requireNonNull(vertexLabels, "vertexLabels cannot be null"); Objects.requireNonNull(driver, "driver cannot be null"); Objects.requireNonNull(vertexIdProvider, "vertexIdProvider cannot be null"); Objects.requireNonNull(edgeIdProvider, "edgeIdProvider cannot be null"); // initialize fields this.partition = partition; this.vertexLabels = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(vertexLabels))); this.driver = driver; // database this.database = database; // validate partition & additional labels if (!partition.containsVertex(this.vertexLabels)) throw new IllegalArgumentException("Invalid vertexLabels, vertices created by the graph will not be part of the given partition"); // store providers this.vertexIdProvider = vertexIdProvider; this.edgeIdProvider = edgeIdProvider; // graph factory configuration (required for tinkerpop test suite) this.configuration = null; // general purpose graph this.readonly = false; this.bookmarks = null; } /** * Creates a {@link Neo4JGraph} instance with the given partition within the neo4j database. * * @param partition The {@link Neo4JReadPartition} within the neo4j database. * @param vertexLabels The set of labels to append to vertices created by the {@link Neo4JGraph} session. * @param driver The {@link Driver} instance with the database connection information. * @param vertexIdProvider The {@link Neo4JElementIdProvider} for the {@link Vertex} id generation. * @param edgeIdProvider The {@link Neo4JElementIdProvider} for the {@link Edge} id generation. * @param readonly {@code true} indicates the Graph instance will be used to read from the Neo4J database. * @param bookmarks The initial references to some previous transactions. Both null value and empty iterable are permitted, and indicate that the bookmarks do not exist or are unknown. */ @Deprecated public Neo4JGraph(Neo4JReadPartition partition, String[] vertexLabels, Driver driver, Neo4JElementIdProvider<?> vertexIdProvider, Neo4JElementIdProvider<?> edgeIdProvider, boolean readonly, String... bookmarks) { Objects.requireNonNull(partition, "partition cannot be null"); Objects.requireNonNull(vertexLabels, "vertexLabels cannot be null"); Objects.requireNonNull(driver, "driver cannot be null"); Objects.requireNonNull(vertexIdProvider, "vertexIdProvider cannot be null"); Objects.requireNonNull(edgeIdProvider, "edgeIdProvider cannot be null"); // initialize fields this.partition = partition; this.vertexLabels = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(vertexLabels))); this.driver = driver; // database this.database = null; // validate partition & additional labels if (!partition.containsVertex(this.vertexLabels)) throw new IllegalArgumentException("Invalid vertexLabels, vertices created by the graph will not be part of the given partition"); // store providers this.vertexIdProvider = vertexIdProvider; this.edgeIdProvider = edgeIdProvider; // graph factory configuration (required for tinkerpop test suite) this.configuration = null; // readonly & bookmarks this.readonly = readonly; this.bookmarks = Collections.singletonList(Bookmark.from(new HashSet<>(Arrays.asList(bookmarks)))); } /** * Creates a {@link Neo4JGraph} instance with the given partition within the neo4j database. * * @param partition The {@link Neo4JReadPartition} within the neo4j database. * @param vertexLabels The set of labels to append to vertices created by the {@link Neo4JGraph} session. * @param driver The {@link Driver} instance with the database connection information. * @param database The database name. * @param vertexIdProvider The {@link Neo4JElementIdProvider} for the {@link Vertex} id generation. * @param edgeIdProvider The {@link Neo4JElementIdProvider} for the {@link Edge} id generation. * @param readonly {@code true} indicates the Graph instance will be used to read from the Neo4J database. * @param bookmarks The initial references to some previous transactions. Both null value and empty iterable are permitted, and indicate that the bookmarks do not exist or are unknown. */ public Neo4JGraph(Neo4JReadPartition partition, String[] vertexLabels, Driver driver, String database, Neo4JElementIdProvider<?> vertexIdProvider, Neo4JElementIdProvider<?> edgeIdProvider, boolean readonly, String... bookmarks) { Objects.requireNonNull(partition, "partition cannot be null"); Objects.requireNonNull(vertexLabels, "vertexLabels cannot be null"); Objects.requireNonNull(driver, "driver cannot be null"); Objects.requireNonNull(vertexIdProvider, "vertexIdProvider cannot be null"); Objects.requireNonNull(edgeIdProvider, "edgeIdProvider cannot be null"); // initialize fields this.partition = partition; this.vertexLabels = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(vertexLabels))); this.driver = driver; // database this.database = database; // validate partition & additional labels if (!partition.containsVertex(this.vertexLabels)) throw new IllegalArgumentException("Invalid vertexLabels, vertices created by the graph will not be part of the given partition"); // store providers this.vertexIdProvider = vertexIdProvider; this.edgeIdProvider = edgeIdProvider; // graph factory configuration (required for tinkerpop test suite) this.configuration = null; // readonly & bookmarks this.readonly = readonly; this.bookmarks = Collections.singletonList(Bookmark.from(new HashSet<>(Arrays.asList(bookmarks)))); } /** * Creates a {@link Neo4JGraph} instance with the given partition within the neo4j database. * * @param partition The {@link Neo4JReadPartition} within the neo4j database. * @param vertexLabels The set of labels to append to vertices created by the {@link Neo4JGraph} session. * @param driver The {@link Driver} instance with the database connection information. * @param vertexIdProvider The {@link Neo4JElementIdProvider} for the {@link Vertex} id generation. * @param edgeIdProvider The {@link Neo4JElementIdProvider} for the {@link Edge} id generation. * @param configuration The {@link Configuration} used to create the {@link Graph} instance. */ @Deprecated Neo4JGraph(Neo4JReadPartition partition, String[] vertexLabels, Driver driver, Neo4JElementIdProvider<?> vertexIdProvider, Neo4JElementIdProvider<?> edgeIdProvider, Configuration configuration, boolean readonly, String... bookmarks) { Objects.requireNonNull(partition, "partition cannot be null"); Objects.requireNonNull(vertexLabels, "vertexLabels cannot be null"); Objects.requireNonNull(driver, "driver cannot be null"); Objects.requireNonNull(vertexIdProvider, "vertexIdProvider cannot be null"); Objects.requireNonNull(edgeIdProvider, "edgeIdProvider cannot be null"); Objects.requireNonNull(configuration, "configuration cannot be null"); // initialize fields this.partition = partition; this.vertexLabels = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(vertexLabels))); this.driver = driver; // database this.database = null; // validate partition & additional labels if (!partition.containsVertex(this.vertexLabels)) throw new IllegalArgumentException("Invalid vertexLabels, vertices created by the graph will not be part of the given partition"); // store providers this.vertexIdProvider = vertexIdProvider; this.edgeIdProvider = edgeIdProvider; // graph factory configuration (required for tinkerpop test suite) this.configuration = configuration; // general purpose graph this.readonly = readonly; this.bookmarks = Collections.singletonList(Bookmark.from(new HashSet<>(Arrays.asList(bookmarks)))); } /** * Creates a {@link Neo4JGraph} instance with the given partition within the neo4j database. * * @param partition The {@link Neo4JReadPartition} within the neo4j database. * @param vertexLabels The set of labels to append to vertices created by the {@link Neo4JGraph} session. * @param driver The {@link Driver} instance with the database connection information. * @param database The database name. * @param vertexIdProvider The {@link Neo4JElementIdProvider} for the {@link Vertex} id generation. * @param edgeIdProvider The {@link Neo4JElementIdProvider} for the {@link Edge} id generation. * @param configuration The {@link Configuration} used to create the {@link Graph} instance. */ Neo4JGraph(Neo4JReadPartition partition, String[] vertexLabels, Driver driver, String database, Neo4JElementIdProvider<?> vertexIdProvider, Neo4JElementIdProvider<?> edgeIdProvider, Configuration configuration, boolean readonly, String... bookmarks) { Objects.requireNonNull(partition, "partition cannot be null"); Objects.requireNonNull(vertexLabels, "vertexLabels cannot be null"); Objects.requireNonNull(driver, "driver cannot be null"); Objects.requireNonNull(vertexIdProvider, "vertexIdProvider cannot be null"); Objects.requireNonNull(edgeIdProvider, "edgeIdProvider cannot be null"); Objects.requireNonNull(configuration, "configuration cannot be null"); // initialize fields this.partition = partition; this.vertexLabels = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(vertexLabels))); this.driver = driver; // database this.database = database; // validate partition & additional labels if (!partition.containsVertex(this.vertexLabels)) throw new IllegalArgumentException("Invalid vertexLabels, vertices created by the graph will not be part of the given partition"); // store providers this.vertexIdProvider = vertexIdProvider; this.edgeIdProvider = edgeIdProvider; // graph factory configuration (required for tinkerpop test suite) this.configuration = configuration; // general purpose graph this.readonly = readonly; this.bookmarks = Collections.singletonList(Bookmark.from(new HashSet<>(Arrays.asList(bookmarks)))); } Neo4JSession currentSession() { // get current session Neo4JSession session = this.session.get(); if (session == null) { // session config SessionConfig.Builder config = SessionConfig.builder() .withDefaultAccessMode(readonly ? AccessMode.READ : AccessMode.WRITE) .withBookmarks(bookmarks); // set database if needed if (database != null) config.withDatabase(database); // create new session session = new Neo4JSession(this, driver.session(config.build()), vertexIdProvider, edgeIdProvider, readonly); // attach it to current thread this.session.set(session); } return session; } /** * Gets the {@link Neo4JReadPartition} that has been applied to current {@link Neo4JGraph}. * * @return The partition labels. */ public Neo4JReadPartition getPartition() { return partition; } /** * Gets the {@link Neo4JElementIdProvider} used for vertex id generation. * * @return The {@link Neo4JElementIdProvider} instance. */ public Neo4JElementIdProvider<?> getVertexIdProvider() { return vertexIdProvider; } /** * Gets the {@link Neo4JElementIdProvider} used for edge id generation. * * @return The {@link Neo4JElementIdProvider} instance. */ public Neo4JElementIdProvider<?> getEdgeIdProvider() { return edgeIdProvider; } /** * Gets the labels that will be applied to vertices created by the current {@link Neo4JGraph}. * * @return The additional labels for new vertices. */ public Set<String> vertexLabels() { return vertexLabels; } /** * Return the bookmark received following the last completed * {@linkplain Transaction transaction}. If no bookmark was received * or if this transaction was rolled back, the bookmark value will * be null. * * @return a reference to a previous transaction */ public Set<String> lastBookmark() { // get current session Neo4JSession session = currentSession(); // return bookmark in session return session.lastBookmark().values(); } /** * {@inheritDoc} */ @Override public Vertex addVertex(Object... keyValues) { // check graph is readonly if (readonly) throw Graph.Exceptions.vertexAdditionsNotSupported(); // get current session Neo4JSession session = currentSession(); // transaction should be ready for io operations transaction.readWrite(); // add vertex return session.addVertex(keyValues); } /** * Creates an index in the neo4j database. * * @param label The label associated with the Index. * @param propertyName The property name associated with the Index. */ public void createIndex(String label, String propertyName) { Objects.requireNonNull(label, "label cannot be null"); Objects.requireNonNull(propertyName, "propertyName cannot be null"); // get current session Neo4JSession session = currentSession(); // transaction should be ready for io operations transaction.readWrite(); // execute statement session.executeStatement("CREATE INDEX ON :`" + label + "`(" + propertyName + ")", Collections.emptyMap()); } /** * {@inheritDoc} */ @Override public <C extends GraphComputer> C compute(Class<C> implementation) throws IllegalArgumentException { throw Graph.Exceptions.graphComputerNotSupported(); } /** * {@inheritDoc} */ @Override public GraphComputer compute() throws IllegalArgumentException { throw Graph.Exceptions.graphComputerNotSupported(); } /** * {@inheritDoc} */ @Override public Iterator<Vertex> vertices(Object... ids) { // get current session Neo4JSession session = currentSession(); // transaction should be ready for io operations transaction.readWrite(); // find vertices return session.vertices(ids); } public Iterator<Vertex> vertices(String statement, Map<String, Object> parameters) { Objects.requireNonNull(statement, "statement cannot be null"); Objects.requireNonNull(parameters, "parameters cannot be null"); // get current session Neo4JSession session = currentSession(); // transaction should be ready for io operations transaction.readWrite(); // execute statement Result result = session.executeStatement(statement, parameters); // find vertices Iterator<Vertex> iterator = session.vertices(result) .collect(Collectors.toCollection(LinkedList::new)) .iterator(); // process summary (query has been already consumed by collect) ResultSummaryLogger.log(result.consume()); // return iterator return iterator; } public Iterator<Vertex> vertices(String statement, Value parameters) { Objects.requireNonNull(statement, "statement cannot be null"); Objects.requireNonNull(parameters, "parameters cannot be null"); // get current session Neo4JSession session = currentSession(); // transaction should be ready for io operations transaction.readWrite(); // execute statement Result result = session.executeStatement(statement, parameters); // find vertices Iterator<Vertex> iterator = session.vertices(result) .collect(Collectors.toCollection(LinkedList::new)) .iterator(); // process summary (query has been already consumed by collect) ResultSummaryLogger.log(result.consume()); // return iterator return iterator; } public Iterator<Vertex> vertices(String statement) { Objects.requireNonNull(statement, "statement cannot be null"); // use overloaded method return vertices(statement, Collections.emptyMap()); } /** * {@inheritDoc} */ @Override public Iterator<Edge> edges(Object... ids) { // get current session Neo4JSession session = currentSession(); // transaction should be ready for io operations transaction.readWrite(); // find edges return session.edges(ids); } public Iterator<Edge> edges(String statement, Map<String, Object> parameters) { Objects.requireNonNull(statement, "statement cannot be null"); Objects.requireNonNull(parameters, "parameters cannot be null"); // get current session Neo4JSession session = currentSession(); // transaction should be ready for io operations transaction.readWrite(); // execute statement Result result = session.executeStatement(statement, parameters); // find edges Iterator<Edge> iterator = session.edges(result) .collect(Collectors.toCollection(LinkedList::new)) .iterator(); // process summary (query has been already consumed by collect) ResultSummaryLogger.log(result.consume()); // return iterator return iterator; } public Iterator<Edge> edges(String statement, Value parameters) { Objects.requireNonNull(statement, "statement cannot be null"); Objects.requireNonNull(parameters, "parameters cannot be null"); // get current session Neo4JSession session = currentSession(); // transaction should be ready for io operations transaction.readWrite(); // execute statement Result result = session.executeStatement(statement, parameters); // find edges Iterator<Edge> iterator = session.edges(result) .collect(Collectors.toCollection(LinkedList::new)) .iterator(); // process summary (query has been already consumed by collect) ResultSummaryLogger.log(result.consume()); // return iterator return iterator; } public Iterator<Edge> edges(String statement) { Objects.requireNonNull(statement, "statement cannot be null"); // use overloaded method return edges(statement, Collections.emptyMap()); } /** * Executes the given statement on the current {@link Graph} instance. WARNING: There is no * guarantee that the results are confined within the current {@link Neo4JReadPartition}. * * @param statement The CYPHER statement. * @param parameters The CYPHER statement parameters. * @return The {@link Result} with the CYPHER statement execution results. */ public Result execute(String statement, Map<String, Object> parameters) { Objects.requireNonNull(statement, "statement cannot be null"); Objects.requireNonNull(parameters, "parameters cannot be null"); // get current session Neo4JSession session = currentSession(); // transaction should be ready for io operations transaction.readWrite(); // find execute statement return session.executeStatement(statement, parameters); } /** * Executes the given statement on the current {@link Graph} instance. WARNING: There is no * guarantee that the results are confined within the current {@link Neo4JReadPartition}. * * @param statement The CYPHER statement. * @return The {@link Result} with the CYPHER statement execution results. */ public Result execute(String statement) { Objects.requireNonNull(statement, "statement cannot be null"); // use overloaded method return execute(statement, Collections.emptyMap()); } public boolean isProfilerEnabled() { // get current session Neo4JSession session = currentSession(); // get from session return session.isProfilerEnabled(); } public void setProfilerEnabled(boolean value) { // get current session Neo4JSession session = currentSession(); // enable/disable profiler session.setProfilerEnabled(value); } /** * {@inheritDoc} */ @Override public Transaction tx() { // return transaction, do not open transaction here! return transaction; } /** * {@inheritDoc} */ @Override public Variables variables() { throw Graph.Exceptions.variablesNotSupported(); } /** * {@inheritDoc} */ @Override public Configuration configuration() { return configuration; } /** * {@inheritDoc} */ @Override public void close() { // get current session Neo4JSession session = this.session.get(); if (session != null) { // close session session.close(); // remove session this.session.remove(); } // synchronize access to set synchronized (closeListeners) { // notify consumers closeListeners.forEach(consumer -> consumer.accept(this)); } } public void addCloseListener(Consumer<Neo4JGraph> consumer) { Objects.requireNonNull(consumer, "consumer cannot be null"); // synchronize access to set synchronized (closeListeners) { // add consumer closeListeners.add(consumer); } } public void removeCloseListener(Consumer<Neo4JGraph> consumer) { Objects.requireNonNull(consumer, "consumer cannot be null"); // synchronize access to set synchronized (closeListeners) { // remove consumer closeListeners.remove(consumer); } } /** * {@inheritDoc} */ @Override public String toString() { return StringFactory.graphString(this, ""); } /** * {@inheritDoc} */ @Override public Features features() { return new Neo4JGraphFeatures(readonly); } }