/* * Hibernate OGM, Domain model persistence for NoSQL datastores * * License: GNU Lesser General Public License (LGPL), version 2.1 or later * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. */ package org.hibernate.ogm.datastore.neo4j.utils; import java.util.List; import java.util.Map; import org.hibernate.Session; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.ogm.datastore.neo4j.BoltNeo4jDialect; import org.hibernate.ogm.datastore.neo4j.logging.impl.Log; import org.hibernate.ogm.datastore.neo4j.logging.impl.LoggerFactory; import org.hibernate.ogm.datastore.neo4j.remote.bolt.impl.BoltNeo4jClient; import org.hibernate.ogm.datastore.neo4j.remote.bolt.impl.BoltNeo4jDatastoreProvider; import org.hibernate.ogm.datastore.neo4j.test.dsl.NodeForGraphAssertions; import org.hibernate.ogm.datastore.neo4j.test.dsl.RelationshipsChainForGraphAssertions; import org.hibernate.ogm.datastore.spi.DatastoreProvider; import org.hibernate.ogm.dialect.impl.IdentifiableDriver; import org.hibernate.ogm.dialect.spi.GridDialect; import org.hibernate.resource.transaction.spi.TransactionStatus; import org.neo4j.driver.v1.Driver; import org.neo4j.driver.v1.Record; import org.neo4j.driver.v1.Statement; import org.neo4j.driver.v1.StatementResult; import org.neo4j.driver.v1.Transaction; import org.neo4j.driver.v1.exceptions.ClientException; import org.neo4j.driver.v1.types.Node; /** * @author Davide D'Alto */ class BoltNeo4jTestHelperDelegate implements Neo4jTestHelperDelegate { public static final BoltNeo4jTestHelperDelegate INSTANCE = new BoltNeo4jTestHelperDelegate(); private static final Log log = LoggerFactory.getLogger(); private BoltNeo4jTestHelperDelegate() { } @Override public long getNumberOfEntities(Session session, DatastoreProvider provider) { BoltNeo4jClient client = createClient( provider ); return readCountFromResponse( session, client.getDriver(), ENTITY_COUNT_QUERY ); } @Override public long getNumberOfAssociations(Session session, DatastoreProvider provider) { BoltNeo4jClient client = createClient( provider ); return readCountFromResponse( session, client.getDriver(), ASSOCIATION_COUNT_QUERY ); } private long readCountFromResponse(Session session, Driver driver, String query) { StatementResult response = null; if ( session != null ) { Transaction transactionId = transactionId( session ); if ( transactionId != null ) { response = transactionId.run( query ); } else { // Transaction rollbacked or committed try ( org.neo4j.driver.v1.Session neo4jSession = driver.session() ) { response = neo4jSession.run( query ); } } } else { try ( org.neo4j.driver.v1.Session neo4jSession = driver.session() ) { response = neo4jSession.run( query ); } } return response.single().get( 0 ).asInt(); } private Transaction transactionId(Session session) { IdentifiableDriver driver = (IdentifiableDriver) ( ( (SessionImplementor) session ).getTransactionCoordinator().getTransactionDriverControl() ); if ( session.getTransaction().getStatus() != TransactionStatus.ACTIVE ) { return null; } return (Transaction) driver.getTransactionId(); } private BoltNeo4jClient createClient(DatastoreProvider provider) { BoltNeo4jClient client = ( (BoltNeo4jDatastoreProvider) provider ).getClient(); return client; } @Override public GridDialect getDialect(DatastoreProvider datastoreProvider) { return new BoltNeo4jDialect( (BoltNeo4jDatastoreProvider) datastoreProvider ); } @Override public Node findNode(DatastoreProvider datastoreProvider, NodeForGraphAssertions node) { String nodeAsCypher = node.toCypher(); String query = "MATCH " + nodeAsCypher + " RETURN " + node.getAlias(); Driver driver = driver( datastoreProvider ); List<Record> records = null; try ( org.neo4j.driver.v1.Session neo4jSession = driver.session() ) { Statement statement = new Statement( query, node.getParams() ); StatementResult result = neo4jSession.run( statement ); validate( result ); records = result.list(); } if ( records.isEmpty() ) { return null; } if ( records.size() > 1 ) { throw new NotUniqueException(); } Node nodeFound = records.get( 0 ).get( node.getAlias() ).asNode(); return nodeFound; } @Override public Map<String, Object> findProperties(DatastoreProvider datastoreProvider, NodeForGraphAssertions node) { Node result = findNode( datastoreProvider, node ); return result.asMap(); } @Override public Object findRelationshipStartNode(DatastoreProvider datastoreProvider, RelationshipsChainForGraphAssertions relationship) { String relationshipAsCypher = relationship.toCypher(); NodeForGraphAssertions node = relationship.getStart(); String query = "MATCH " + relationshipAsCypher + " RETURN " + node.getAlias(); List<Record> records = null; Driver driver = driver( datastoreProvider ); try ( org.neo4j.driver.v1.Session neo4jSession = driver.session() ) { Statement statement = new Statement( query, relationship.getParams() ); StatementResult result = neo4jSession.run( statement ); validate( result ); records = result.list(); } if ( records.isEmpty() ) { return null; } if ( records.size() > 1 ) { throw new NotUniqueException(); } Node nodeFound = records.get( 0 ).get( node.getAlias() ).asNode(); return nodeFound; } @Override public void deleteAllElements(DatastoreProvider datastoreProvider) { Driver driver = driver( datastoreProvider ); try ( org.neo4j.driver.v1.Session session = driver.session() ) { session.run( DELETE_ALL ); } } private Driver driver(DatastoreProvider datastoreProvider) { BoltNeo4jDatastoreProvider boltProvider = (BoltNeo4jDatastoreProvider) datastoreProvider; Driver driver = boltProvider.getClient().getDriver(); return driver; } @Override public void dropDatabase(DatastoreProvider datastoreProvider) { deleteAllElements( datastoreProvider ); } @Override public void executeCypherQuery(DatastoreProvider datastoreProvider, String query, Map<String, Object> parameters) { Driver driver = driver( datastoreProvider ); try ( org.neo4j.driver.v1.Session session = driver.session() ) { StatementResult result = session.run( query, parameters ); validate( result ); } } private void validate(StatementResult result) { try { result.hasNext(); } catch (ClientException e) { throw log.nativeQueryException( e.neo4jErrorCode(), e.getMessage(), null ); } } @Override public Long executeCountQuery(DatastoreProvider datastoreProvider, String queryString) { Driver driver = driver( datastoreProvider ); StatementResult result = driver.session().run( queryString ); return result.single().get( 0 ).asLong(); } }