Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
OGM-783 [Neo4j] Create DSL to assert the mapping in tests
- Loading branch information
Showing
3 changed files
with
334 additions
and
0 deletions.
There are no files selected for viewing
74 changes: 74 additions & 0 deletions
74
neo4j/src/test/java/org/hibernate/ogm/datastore/neo4j/test/dsl/GraphAssertions.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
/* | ||
* 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.test.dsl; | ||
|
||
import static org.fest.assertions.Assertions.assertThat; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Iterator; | ||
import java.util.List; | ||
import java.util.Set; | ||
|
||
import org.fest.assertions.Fail; | ||
import org.neo4j.cypher.javacompat.ExecutionEngine; | ||
import org.neo4j.graphdb.PropertyContainer; | ||
import org.neo4j.graphdb.ResourceIterator; | ||
|
||
/** | ||
* Assertion methods to check the mapping of nodes and relationships in Neo4j. | ||
* | ||
* @author Davide D'Alto | ||
*/ | ||
public class GraphAssertions { | ||
|
||
public static NodeForGraphAssertions node(String alias, String... labels) { | ||
return new NodeForGraphAssertions( alias, labels); | ||
} | ||
|
||
public static void assertThatExists(ExecutionEngine engine, NodeForGraphAssertions node) throws Exception { | ||
String nodeAsCypher = node.toCypher(); | ||
String query = "MATCH " + nodeAsCypher + " RETURN " + node.getAlias(); | ||
ResourceIterator<Object> columnAs = engine.execute( query, node.getParams() ).columnAs( node.getAlias() ); | ||
assertThat( columnAs.hasNext() ).as( "Node [" + node.getAlias() + "] not found, Looked for " + nodeAsCypher + " with parameters: " + node.getParams() ).isTrue(); | ||
|
||
PropertyContainer propertyContainer = (PropertyContainer) columnAs.next(); | ||
Iterable<String> propertyKeys = propertyContainer.getPropertyKeys(); | ||
List<String> unexpectedProperties = new ArrayList<String>(); | ||
Set<String> expectedProperties = node.getProperties().keySet(); | ||
for ( Iterator<String> iterator = propertyKeys.iterator(); iterator.hasNext(); ) { | ||
String actual = iterator.next(); | ||
if ( !expectedProperties.contains( actual ) ) { | ||
unexpectedProperties.add( actual ); | ||
} | ||
} | ||
List<String> missingProperties = new ArrayList<String>(); | ||
if ( expectedProperties != null ) { | ||
for ( String expected : expectedProperties ) { | ||
if ( !propertyContainer.hasProperty( expected ) ) { | ||
missingProperties.add( expected ); | ||
} | ||
} | ||
} | ||
assertThat( unexpectedProperties ).as( "Unexpected properties for node [" + node.getAlias() + "]" ).isEmpty(); | ||
assertThat( missingProperties ).as( "Missing properties for node [" + node.getAlias() + "]" ).isEmpty(); | ||
if ( columnAs.hasNext() ) { | ||
Fail.fail( "Unexpected result returned: " + columnAs.next() ); | ||
} | ||
} | ||
|
||
public static void assertThatExists(ExecutionEngine engine, RelationshipsChainForGraphAssertions relationship) throws Exception { | ||
String relationshipAsCypher = relationship.toCypher(); | ||
NodeForGraphAssertions node = relationship.getStart(); | ||
String query = "MATCH " + relationshipAsCypher + " RETURN " + node.getAlias(); | ||
ResourceIterator<Object> columnAs = engine.execute( query, relationship.getParams() ).columnAs( node.getAlias() ); | ||
assertThat( columnAs.hasNext() ).as( "Relationships not found, Looked for " + relationshipAsCypher + " with parameters: " + relationship.getParams() ).isTrue(); | ||
columnAs.next(); | ||
if ( columnAs.hasNext() ) { | ||
Fail.fail( "Unexpected result returned: " + columnAs.next() ); | ||
} | ||
} | ||
} |
102 changes: 102 additions & 0 deletions
102
neo4j/src/test/java/org/hibernate/ogm/datastore/neo4j/test/dsl/NodeForGraphAssertions.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
/* | ||
* 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.test.dsl; | ||
|
||
import static org.hibernate.ogm.datastore.neo4j.query.parsing.cypherdsl.impl.CypherDSL.escapeIdentifier; | ||
|
||
import java.util.Collections; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
/** | ||
* /** | ||
* A DSL to define a node like the following: | ||
* <p> | ||
* <pre> | ||
* (n:ENTITY:StoryGame {id: {n}.id}) | ||
* </pre> | ||
* | ||
* @author Davide D'Alto | ||
*/ | ||
public class NodeForGraphAssertions { | ||
|
||
private final String alias; | ||
private final String[] labels; | ||
private final Map<String, Object> properties = new HashMap<String, Object>(); | ||
private final Map<String, Object> params = new HashMap<String, Object>(); | ||
|
||
public NodeForGraphAssertions(String alias, String[] labels) { | ||
this.alias = alias; | ||
this.labels = labels; | ||
this.params.put( alias, properties ); | ||
} | ||
|
||
public NodeForGraphAssertions property(String property, Object value) { | ||
properties.put( property, value ); | ||
return this; | ||
} | ||
|
||
public RelationshipsChainForGraphAssertions relationshipTo(NodeForGraphAssertions endNode, String relationshipType) { | ||
Map<String, Object> emptyMap = Collections.emptyMap(); | ||
return relationshipTo( endNode, relationshipType, emptyMap ); | ||
} | ||
|
||
public RelationshipsChainForGraphAssertions relationshipTo(NodeForGraphAssertions endNode, String relationshipType, Map<String, Object> properties) { | ||
return new RelationshipsChainForGraphAssertions( this, endNode, relationshipType ); | ||
} | ||
|
||
public String toCypher() { | ||
StringBuilder builder = new StringBuilder(); | ||
builder.append( "(" ); | ||
builder.append( alias ); | ||
for ( String label : labels ) { | ||
builder.append( ":" ); | ||
builder.append( label ); | ||
} | ||
if ( !properties.isEmpty() ) { | ||
builder.append( " {" ); | ||
int index = 0; | ||
for ( String property : properties.keySet() ) { | ||
escapeIdentifier( builder, property ); | ||
builder.append( ": " ); | ||
builder.append( "{" ); | ||
builder.append( alias ); | ||
builder.append( "}" ); | ||
builder.append( "." ); | ||
escapeIdentifier( builder, property ); | ||
index++; | ||
if ( index < properties.size() ) { | ||
builder.append( ", " ); | ||
} | ||
} | ||
builder.append( "}" ); | ||
} | ||
builder.append( ")" ); | ||
return builder.toString(); | ||
} | ||
|
||
/** | ||
* The node alias. | ||
*/ | ||
public String getAlias() { | ||
return alias; | ||
} | ||
|
||
/** | ||
* The map with the values for the parameters in the cypher representation of the node. | ||
*/ | ||
public Map<String, Object> getParams() { | ||
return Collections.unmodifiableMap( params ); | ||
} | ||
|
||
/** | ||
* Returns the properties for the node. | ||
*/ | ||
public Map<String, Object> getProperties() { | ||
return Collections.unmodifiableMap( properties ); | ||
} | ||
} |
158 changes: 158 additions & 0 deletions
158
...java/org/hibernate/ogm/datastore/neo4j/test/dsl/RelationshipsChainForGraphAssertions.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
/* | ||
* 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.test.dsl; | ||
|
||
import static org.hibernate.ogm.datastore.neo4j.query.parsing.cypherdsl.impl.CypherDSL.escapeIdentifier; | ||
|
||
import java.util.ArrayList; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
/** | ||
* A DSL to define a chain of relationships like the following: | ||
* <p> | ||
* <pre> | ||
* () -> [r1:type1 {property: {r1}.property}] -> () -[r2:type2]-> () | ||
* </pre> | ||
* | ||
* @author Davide D'Alto | ||
*/ | ||
public class RelationshipsChainForGraphAssertions { | ||
|
||
private final NodeForGraphAssertions start; | ||
private final List<NextRelationship> stream = new ArrayList<NextRelationship>(); | ||
private final Map<String, Object> params = new HashMap<String, Object>(); | ||
|
||
public RelationshipsChainForGraphAssertions(NodeForGraphAssertions start, NodeForGraphAssertions end, String relationshipType) { | ||
this.start = start; | ||
this.params.put( start.getAlias(), start.getProperties() ); | ||
addToStream( end, relationshipType ); | ||
} | ||
|
||
private void addToStream(NodeForGraphAssertions end, String relationshipType) { | ||
stream.add( new NextRelationship( end, relationshipType, "r" + stream.size() ) ); | ||
params.put( end.getAlias(), end.getProperties() ); | ||
} | ||
|
||
public RelationshipsChainForGraphAssertions relationshipTo(NodeForGraphAssertions next, String relationshipType) { | ||
addToStream( next, relationshipType ); | ||
return this; | ||
} | ||
|
||
/** | ||
* Get the starting node of the current chain of relationships. | ||
*/ | ||
public NodeForGraphAssertions getStart() { | ||
return start; | ||
} | ||
|
||
/** | ||
* The map with the values for the parameters in the cypher representation of the current chain. | ||
*/ | ||
public Map<String, Object> getParams() { | ||
return params; | ||
} | ||
|
||
/** | ||
* The number of relationships in the chain. | ||
*/ | ||
public int getSize() { | ||
return stream.size(); | ||
} | ||
|
||
/** | ||
* Define a property on the last relationship of the chain. | ||
*/ | ||
public RelationshipsChainForGraphAssertions property(String name, Object value) { | ||
NextRelationship relationship = stream.get( stream.size() - 1 ); | ||
@SuppressWarnings("unchecked") | ||
Map<String, Object> properties = (Map<String, Object>) params.get( relationship.getAlias() ); | ||
if ( properties == null ) { | ||
params.put( relationship.getAlias(), relationship.getProperties() ); | ||
} | ||
relationship.addProperty( name, value ); | ||
return this; | ||
} | ||
|
||
/** | ||
* Returns the cypher representation of the chain of relationships, | ||
* <p> | ||
* Example: | ||
* <pre> | ||
* (n1:ENTITY {id: {n1}.id}) -[r0:type0 {property: {r0}.property}]-> (n2:EMBEDDED {property: {n2}.property}) -[r1:type1]-> (n3:EMBEDDED) | ||
* <pre> | ||
*/ | ||
public String toCypher() { | ||
StringBuilder builder = new StringBuilder(); | ||
builder.append( start.toCypher() ); | ||
for ( NextRelationship relationship : stream ) { | ||
builder.append( " -[" ); | ||
if ( !relationship.getProperties().isEmpty() ) { | ||
builder.append( relationship.getAlias() ); | ||
} | ||
builder.append( ":" ); | ||
builder.append( relationship.getRelationshipType() ); | ||
if ( !relationship.getProperties().isEmpty() ) { | ||
builder.append( " {" ); | ||
boolean first = true; | ||
for ( String property : relationship.getProperties().keySet() ) { | ||
if ( first ) { | ||
first = false; | ||
} | ||
else { | ||
builder.append( ", " ); | ||
} | ||
escapeIdentifier( builder, property ); | ||
builder.append( ": {" ); | ||
builder.append( relationship.getAlias() ); | ||
builder.append( "}." ); | ||
escapeIdentifier( builder, property ); | ||
} | ||
builder.append( " }" ); | ||
} | ||
builder.append( "]-> " ); | ||
builder.append( relationship.getEnd().toCypher() ); | ||
} | ||
return builder.toString(); | ||
} | ||
|
||
private static class NextRelationship { | ||
|
||
private final NodeForGraphAssertions end; | ||
private final String relationshipType; | ||
private final Map<String, Object> properties = new HashMap<String, Object>(); | ||
private final String alias; | ||
|
||
public NextRelationship(NodeForGraphAssertions to, String relationshipType, String alias) { | ||
this.end = to; | ||
this.relationshipType = relationshipType; | ||
this.alias = alias; | ||
} | ||
|
||
public String getAlias() { | ||
return alias; | ||
} | ||
|
||
public Map<String, Object> getProperties() { | ||
return properties; | ||
} | ||
|
||
public NodeForGraphAssertions getEnd() { | ||
return end; | ||
} | ||
|
||
public String getRelationshipType() { | ||
return relationshipType; | ||
} | ||
|
||
public void addProperty( String name, Object value ) { | ||
properties.put( name, value ); | ||
} | ||
} | ||
|
||
} |