package examples;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.Set;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.DynamicRelationshipType;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.RelationshipType;
import org.neo4j.graphdb.Transaction;
import org.neo4j.graphmatching.CommonValueMatchers;
import org.neo4j.graphmatching.PatternMatch;
import org.neo4j.graphmatching.PatternMatcher;
import org.neo4j.graphmatching.PatternNode;
import org.neo4j.graphmatching.PatternRelationship;
import org.neo4j.graphmatching.ValueMatcher;
import org.neo4j.helpers.collection.IterableWrapper;
import org.neo4j.kernel.EmbeddedGraphDatabase;
/**
* Example code for the index page of the component site.
*
* @author Tobias Ivarsson
*/
public class TestSiteIndexExamples
{
// START SNIPPET: findNodesWithRelationshipsTo
public static Iterable<Node> findNodesWithRelationshipsTo(
RelationshipType type, Node... nodes )
{
if ( nodes == null || nodes.length == 0 )
{
throw new IllegalArgumentException( "No nodes supplied" );
}
final PatternNode requested = new PatternNode();
PatternNode anchor = null;
for ( Node node : nodes )
{
PatternNode pattern = new PatternNode();
pattern.setAssociation( node );
pattern.createRelationshipTo( requested, type );
if ( anchor == null )
{
anchor = pattern;
}
}
PatternMatcher matcher = PatternMatcher.getMatcher();
Iterable<PatternMatch> matches = matcher.match( anchor, nodes[0] );
return new IterableWrapper<Node, PatternMatch>( matches )
{
@Override
protected Node underlyingObjectToObject( PatternMatch match )
{
return match.getNodeFor( requested );
}
};
}
// END SNIPPET: findNodesWithRelationshipsTo
// START SNIPPET: findFriends
private static final long MILLSECONDS_PER_DAY = 1000 * 60 * 60 * 24;
enum FriendshipTypes implements RelationshipType
{
FRIEND,
LIVES_IN
}
/**
* Find all friends the specified person has known for more than the
* specified number of years.
*
* @param me the node to find the friends of.
* @param livesIn The name of the place where the friends should live.
* @param knownForYears the minimum age (in years) of the friendship.
* @return all nodes that live in the specified place that the specified
* nodes has known for the specified number of years.
*/
public Iterable<Node> findFriendsSinceSpecifiedTimeInSpecifiedPlace(
Node me, String livesIn,
final int knownForYears )
{
PatternNode root = new PatternNode(), place = new PatternNode();
final PatternNode friend = new PatternNode();
// Define the friendship
PatternRelationship friendship = root.createRelationshipTo( friend,
FriendshipTypes.FRIEND, Direction.BOTH );
// Define the age of the friendship
friendship.addPropertyConstraint( "since", new ValueMatcher()
{
long now = new Date().getTime();
public boolean matches( Object value )
{
if ( value instanceof Long )
{
long ageInDays = ( now - (Long) value )
/ MILLSECONDS_PER_DAY;
return ageInDays > ( knownForYears * 365 );
}
return false;
}
} );
// Define the place where the friend lives
friend.createRelationshipTo( place, FriendshipTypes.LIVES_IN );
place.addPropertyConstraint( "name",
CommonValueMatchers.exact( livesIn ) );
// Perform the matching
PatternMatcher matcher = PatternMatcher.getMatcher();
Iterable<PatternMatch> matches = matcher.match( root, me );
// Return the result
return new IterableWrapper<Node, PatternMatch>( matches )
{
@Override
protected Node underlyingObjectToObject( PatternMatch match )
{
return match.getNodeFor( friend );
}
};
}
// END SNIPPET: findFriends
@Test
public void verifyFunctionalityOfFindNodesWithRelationshipsTo()
throws Exception
{
final RelationshipType type = DynamicRelationshipType.withName( "RELATED" );
Node[] nodes = createGraph( new GraphDefinition<Node[]>()
{
public Node[] create( GraphDatabaseService graphdb )
{
Node[] nodes = new Node[5];
for ( int i = 0; i < nodes.length; i++ )
{
nodes[i] = graphdb.createNode();
}
for ( int i = 0; i < 3; i++ )
{
Node node = graphdb.createNode();
for ( int j = 0; j < nodes.length; j++ )
{
nodes[j].createRelationshipTo( node, type );
}
}
return nodes;
}
} );
Transaction tx = graphDb.beginTx();
try
{
assertEquals( 3,
count( findNodesWithRelationshipsTo( type, nodes ) ) );
tx.success();
}
finally
{
tx.finish();
}
}
@Test
public void verifyFunctionalityOfFindFriendsSinceSpecifiedTimeInSpecifiedPlace()
throws Exception
{
Node root = createGraph( new GraphDefinition<Node>()
{
public Node create( GraphDatabaseService graphdb )
{
Node me = graphdb.createNode();
Node stockholm = graphdb.createNode(), gothenburg = graphdb.createNode();
stockholm.setProperty( "name", "Stockholm" );
gothenburg.setProperty( "name", "Gothenburg" );
Node andy = friend( me, graphdb.createNode(), "Andy", 10,
stockholm );
friend( me, graphdb.createNode(), "Bob", 5, stockholm );
Node cecilia = friend( me, graphdb.createNode(), "Cecilia", 2,
stockholm );
andy.createRelationshipTo( cecilia, FriendshipTypes.FRIEND ).setProperty(
"since", yearsAgo( 10 ) );
friend( me, graphdb.createNode(), "David", 10, gothenburg );
return me;
}
Node friend( Node me, Node friend, String name, int knownForYears,
Node place )
{
friend.setProperty( "name", name );
me.createRelationshipTo( friend, FriendshipTypes.FRIEND ).setProperty(
"since", yearsAgo( knownForYears ) );
friend.createRelationshipTo( place, FriendshipTypes.LIVES_IN );
return friend;
}
Calendar calendar = Calendar.getInstance();
long yearsAgo( int years )
{
return new GregorianCalendar( calendar.get( Calendar.YEAR )
- years,
calendar.get( Calendar.MONTH ),
calendar.get( Calendar.DATE ) ).getTime().getTime();
}
} );
Set<String> expected = new HashSet<String>( Arrays.asList( "Andy",
"Bob" ) );
Iterable<Node> friends = findFriendsSinceSpecifiedTimeInSpecifiedPlace(
root, "Stockholm", 3 );
for ( Node friend : friends )
{
String name = (String) friend.getProperty( "name", null );
assertNotNull( name );
assertTrue( "Unexpected friend: " + name, expected.remove( name ) );
}
assertTrue( "These friends were not found: " + expected,
expected.isEmpty() );
}
private int count( Iterable<?> objects )
{
int count = 0;
for ( @SuppressWarnings( "unused" ) Object object : objects )
{
count++;
}
return count;
}
private interface GraphDefinition<RESULT>
{
RESULT create( GraphDatabaseService graphdb );
}
private <T> T createGraph( GraphDefinition<T> definition )
{
final T result;
Transaction tx = graphDb.beginTx();
try
{
result = definition.create( graphDb );
tx.success();
}
finally
{
tx.finish();
}
return result;
}
private static GraphDatabaseService graphDb;
@BeforeClass
public static void startGraphDatabase()
{
graphDb = new EmbeddedGraphDatabase( "target/var/db" );
}
@AfterClass
public static void shutdownGraphDatabase()
{
graphDb.shutdown();
graphDb = null;
}
}