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.socnet;
20  
21  import static org.neo4j.examples.socnet.RelTypes.A_PERSON;
22  import static org.neo4j.examples.socnet.RelTypes.REF_PERSONS;
23  
24  import org.neo4j.graphdb.Direction;
25  import org.neo4j.graphdb.GraphDatabaseService;
26  import org.neo4j.graphdb.Node;
27  import org.neo4j.graphdb.Relationship;
28  import org.neo4j.graphdb.Transaction;
29  import org.neo4j.graphdb.index.Index;
30  import org.neo4j.helpers.collection.IterableWrapper;
31  
32  public class PersonRepository
33  {
34      private final GraphDatabaseService graphDb;
35      private final Index<Node> index;
36      private final Node personRefNode;
37  
38      public PersonRepository( GraphDatabaseService graphDb, Index<Node> index )
39      {
40          this.graphDb = graphDb;
41          this.index = index;
42  
43          personRefNode = getPersonsRootNode( graphDb );
44      }
45  
46      private Node getPersonsRootNode( GraphDatabaseService graphDb )
47      {
48          Relationship rel = graphDb.getReferenceNode().getSingleRelationship(
49                  REF_PERSONS, Direction.OUTGOING );
50          if ( rel != null )
51          {
52              return rel.getEndNode();
53          } else
54          {
55              Transaction tx = this.graphDb.beginTx();
56              try
57              {
58                  Node refNode = this.graphDb.createNode();
59                  this.graphDb.getReferenceNode().createRelationshipTo( refNode,
60                          REF_PERSONS );
61                  tx.success();
62                  return refNode;
63              }
64              finally
65              {
66                  tx.finish();
67              }
68          }
69      }
70  
71      public Person createPerson( String name ) throws Exception
72      {
73          // to guard against duplications we use the lock grabbed on ref node
74          // when
75          // creating a relationship and are optimistic about person not existing
76          Transaction tx = graphDb.beginTx();
77          try
78          {
79              Node newPersonNode = graphDb.createNode();
80              personRefNode.createRelationshipTo( newPersonNode, A_PERSON );
81              // lock now taken, we can check if  already exist in index
82              Node alreadyExist = index.get( Person.NAME, name ).getSingle();
83              if ( alreadyExist != null )
84              {
85                  tx.failure();
86                  throw new Exception( "Person with this name already exists " );
87              }
88              newPersonNode.setProperty( Person.NAME, name );
89              index.add( newPersonNode, Person.NAME, name );
90              tx.success();
91              return new Person( newPersonNode );
92          }
93          finally
94          {
95              tx.finish();
96          }
97      }
98  
99      public Person getPersonByName( String name )
100     {
101         Node personNode = index.get( Person.NAME, name ).getSingle();
102         if ( personNode == null )
103         {
104             throw new IllegalArgumentException( "Person[" + name
105                     + "] not found" );
106         }
107         return new Person( personNode );
108     }
109 
110     public void deletePerson( Person person )
111     {
112         Transaction tx = graphDb.beginTx();
113         try
114         {
115             Node personNode = person.getUnderlyingNode();
116             index.remove( personNode, Person.NAME, person.getName() );
117             for ( Person friend : person.getFriends() )
118             {
119                 person.removeFriend( friend );
120             }
121             personNode.getSingleRelationship( A_PERSON, Direction.INCOMING ).delete();
122 
123             for ( StatusUpdate status : person.getStatus() )
124             {
125                 Node statusNode = status.getUnderlyingNode();
126                 for ( Relationship r : statusNode.getRelationships() )
127                 {
128                     r.delete();
129                 }
130                 statusNode.delete();
131             }
132 
133             personNode.delete();
134             tx.success();
135         }
136         finally
137         {
138             tx.finish();
139         }
140     }
141 
142     public Iterable<Person> getAllPersons()
143     {
144         return new IterableWrapper<Person, Relationship>(
145                 personRefNode.getRelationships( A_PERSON ) )
146         {
147             @Override
148             protected Person underlyingObjectToObject( Relationship personRel )
149             {
150                 return new Person( personRel.getEndNode() );
151             }
152         };
153     }
154 }