1   /**
2    * Licensed to Neo Technology under one or more contributor
3    * license agreements. See the NOTICE file distributed with
4    * this work for additional information regarding copyright
5    * ownership. Neo Technology licenses this file to you under
6    * the Apache License, Version 2.0 (the "License"); you may
7    * not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied. See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.neo4j.examples;
20  
21  import org.junit.AfterClass;
22  import org.junit.BeforeClass;
23  import org.junit.Test;
24  import org.neo4j.graphdb.*;
25  import org.neo4j.graphdb.traversal.TraversalDescription;
26  import org.neo4j.graphdb.traversal.Traverser;
27  import org.neo4j.kernel.EmbeddedGraphDatabase;
28  import org.neo4j.kernel.Traversal;
29  
30  import java.io.File;
31  
32  import static org.junit.Assert.assertEquals;
33  
34  public class MatrixTest
35  {
36      public enum RelTypes implements RelationshipType
37      {
38          NEO_NODE,
39          KNOWS,
40          CODED_BY
41      }
42  
43      private static final String MATRIX_DB = "target/matrix-db";
44      private static GraphDatabaseService graphDb;
45  
46      @BeforeClass
47      public static void setUp()
48      {
49          deleteFileOrDirectory( new File( MATRIX_DB ) );
50          graphDb = new EmbeddedGraphDatabase( MATRIX_DB );
51          registerShutdownHook();
52          createNodespace();
53      }
54  
55      @AfterClass
56      public static void tearDown()
57      {
58          graphDb.shutdown();
59      }
60  
61      private static void createNodespace()
62      {
63          Transaction tx = graphDb.beginTx();
64          try
65          {
66              Node thomas = graphDb.createNode();
67              thomas.setProperty( "name", "Thomas Anderson" );
68              thomas.setProperty( "age", 29 );
69  
70              // connect Neo/Thomas to the reference node
71              Node referenceNode = graphDb.getReferenceNode();
72              referenceNode.createRelationshipTo( thomas, RelTypes.NEO_NODE );
73  
74              Node trinity = graphDb.createNode();
75              trinity.setProperty( "name", "Trinity" );
76              Relationship rel = thomas.createRelationshipTo( trinity,
77                      RelTypes.KNOWS );
78              rel.setProperty( "age", "3 days" );
79              Node morpheus = graphDb.createNode();
80              morpheus.setProperty( "name", "Morpheus" );
81              morpheus.setProperty( "rank", "Captain" );
82              morpheus.setProperty( "occupation", "Total badass" );
83              thomas.createRelationshipTo( morpheus, RelTypes.KNOWS );
84              rel = morpheus.createRelationshipTo( trinity, RelTypes.KNOWS );
85              rel.setProperty( "age", "12 years" );
86              Node cypher = graphDb.createNode();
87              cypher.setProperty( "name", "Cypher" );
88              cypher.setProperty( "last name", "Reagan" );
89              trinity.createRelationshipTo( cypher, RelTypes.KNOWS );
90              rel = morpheus.createRelationshipTo( cypher, RelTypes.KNOWS );
91              rel.setProperty( "disclosure", "public" );
92              Node smith = graphDb.createNode();
93              smith.setProperty( "name", "Agent Smith" );
94              smith.setProperty( "version", "1.0b" );
95              smith.setProperty( "language", "C++" );
96              rel = cypher.createRelationshipTo( smith, RelTypes.KNOWS );
97              rel.setProperty( "disclosure", "secret" );
98              rel.setProperty( "age", "6 months" );
99              Node architect = graphDb.createNode();
100             architect.setProperty( "name", "The Architect" );
101             smith.createRelationshipTo( architect, RelTypes.CODED_BY );
102 
103             tx.success();
104         }
105         finally
106         {
107             tx.finish();
108         }
109     }
110 
111     /**
112      * Get the Neo node. (a.k.a. Thomas Anderson node)
113      *
114      * @return the Neo node
115      */
116     private static Node getNeoNode()
117     {
118         return graphDb.getReferenceNode().getSingleRelationship(
119                 RelTypes.NEO_NODE, Direction.OUTGOING ).getEndNode();
120     }
121 
122     @Test
123     public void printNeoFriends() throws Exception
124     {
125         Node neoNode = getNeoNode();
126         System.out.println( neoNode.getProperty( "name" ) + "'s friends:" );
127         // START SNIPPET: get-friends-usage
128         Traverser friendsTraverser = getFriends( neoNode );
129         int numberOfFriends = 0;
130         for ( Path friendPath : friendsTraverser )
131         {
132             System.out.println( "At depth " + friendPath.length() + " => "
133                     + friendPath.endNode().getProperty( "name" ) );
134             numberOfFriends++;
135         }
136         // END SNIPPET: get-friends-usage
137         assertEquals( 4, numberOfFriends );
138     }
139 
140     // START SNIPPET: get-friends
141 
142     private static Traverser getFriends( final Node person )
143     {
144         TraversalDescription td = Traversal.description().breadthFirst().relationships(
145                 RelTypes.KNOWS, Direction.OUTGOING ).filter(
146                 Traversal.returnAllButStartNode() );
147         return td.traverse( person );
148     }
149     // END SNIPPET: get-friends
150 
151     @Test
152     public void printMatrixHackers() throws Exception
153     {
154         System.out.println( "Hackers:" );
155         // START SNIPPET: find-hackers-usage
156         Traverser traverser = findHackers( getNeoNode() );
157         int numberOfHackers = 0;
158         for ( Path hackerPath : traverser )
159         {
160             System.out.println( "At depth " + hackerPath.length() + " => "
161                     + hackerPath.endNode().getProperty( "name" ) );
162             numberOfHackers++;
163         }
164         // END SNIPPET: find-hackers-usage
165         assertEquals( 1, numberOfHackers );
166     }
167 
168     // START SNIPPET: find-hackers
169 
170     private static Traverser findHackers( final Node startNode )
171     {
172         TraversalDescription td = Traversal.description().breadthFirst().relationships(
173                 RelTypes.CODED_BY, Direction.OUTGOING ).relationships(
174                 RelTypes.KNOWS, Direction.OUTGOING ).filter(
175                 Traversal.returnWhereLastRelationshipTypeIs( RelTypes.CODED_BY ) );
176         return td.traverse( startNode );
177     }
178     // END SNIPPET: find-hackers
179 
180     private static void registerShutdownHook()
181     {
182         // Registers a shutdown hook for the Neo4j instance so that it
183         // shuts down nicely when the VM exits (even if you "Ctrl-C" the
184         // running example before it's completed)
185         Runtime.getRuntime().addShutdownHook( new Thread()
186         {
187             @Override
188             public void run()
189             {
190                 graphDb.shutdown();
191             }
192         } );
193     }
194 
195     private static void deleteFileOrDirectory( final File file )
196     {
197         if ( !file.exists() )
198         {
199             return;
200         }
201 
202         if ( file.isDirectory() )
203         {
204             for ( File child : file.listFiles() )
205             {
206                 deleteFileOrDirectory( child );
207             }
208         } else
209         {
210             file.delete();
211         }
212     }
213 }