Biblioteca Java - Blame information for rev 18

Subversion Repositories:
Rev:
Rev Author Line No. Line
18 mihai 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 com.linkscreens.graphsin.repository;
20  
21 import java.util.ArrayList;
22 import java.util.Collections;
23 import java.util.Comparator;
24 import java.util.Date;
25 import java.util.HashSet;
26 import java.util.Iterator;
27  
28 import org.neo4j.graphalgo.GraphAlgoFactory;
29 import org.neo4j.graphalgo.PathFinder;
30 import org.neo4j.graphdb.Direction;
31 import org.neo4j.graphdb.GraphDatabaseService;
32 import org.neo4j.graphdb.Node;
33 import org.neo4j.graphdb.Path;
34 import org.neo4j.graphdb.Relationship;
35 import org.neo4j.graphdb.traversal.Evaluators;
36 import org.neo4j.graphdb.traversal.TraversalDescription;
37 import org.neo4j.graphdb.traversal.Traverser;
38 import org.neo4j.helpers.collection.IterableWrapper;
39 import org.neo4j.helpers.collection.IteratorUtil;
40 import org.neo4j.graphdb.traversal.Uniqueness;
41  
42 import com.linkscreens.graphsin.network.FriendsStatusUpdateIterator;
43  
44 import static org.neo4j.graphdb.Direction.BOTH;
45 import static org.neo4j.graphdb.PathExpanders.forTypeAndDirection;
46  
47 public class PersonNode
48 {
49         public static final String EMAIL = "email";
50  
51     // START SNIPPET: the-node
52     private final Node underlyingNode;
53  
54     public PersonNode( Node personNode )
55     {
56         this.underlyingNode = personNode;
57     }
58  
59     public Node getUnderlyingNode()
60     {
61         return underlyingNode;
62     }
63  
64     // END SNIPPET: the-node
65  
66     // START SNIPPET: delegate-to-the-node
67     public String getName()
68     {
69         return (String)underlyingNode.getProperty( EMAIL );
70     }
71  
72     // END SNIPPET: delegate-to-the-node
73  
74  
75     // START SNIPPET: override
76     @Override
77     public int hashCode()
78     {
79         return underlyingNode.hashCode();
80     }
81  
82     @Override
83     public boolean equals( Object o )
84     {
85         return o instanceof PersonNode &&
86                 underlyingNode.equals( ( (PersonNode)o ).getUnderlyingNode() );
87     }
88  
89     @Override
90     public String toString()
91     {
92         return "Person[" + getName() + "]";
93     }
94  
95     // END SNIPPET: override
96  
97     public void addFriend( PersonNode otherPerson )
98     {
99         if ( !this.equals( otherPerson ) )
100         {
101             Relationship friendRel = getFriendRelationshipTo( otherPerson );
102             if ( friendRel == null )
103             {
104                 underlyingNode.createRelationshipTo( otherPerson.getUnderlyingNode(), RelTypes.FRIEND );
105             }
106         }
107     }
108  
109     public int getNrOfFriends()
110     {
111         return IteratorUtil.count( getFriends() );
112     }
113  
114     public Iterable<PersonNode> getFriends()
115     {
116         return getFriendsByDepth( 1 );
117     }
118  
119     public void removeFriend( PersonNode otherPerson )
120     {
121         if ( !this.equals( otherPerson ) )
122         {
123             Relationship friendRel = getFriendRelationshipTo( otherPerson );
124             if ( friendRel != null )
125             {
126                 friendRel.delete();
127             }
128         }
129     }
130  
131     public Iterable<PersonNode> getFriendsOfFriends()
132     {
133         return getFriendsByDepth( 2 );
134     }
135  
136     public Iterable<PersonNode> getShortestPathTo( PersonNode otherPerson,
137                                                int maxDepth )
138     {
139         // use graph algo to calculate a shortest path
140         PathFinder<Path> finder = GraphAlgoFactory.shortestPath(
141                 forTypeAndDirection(RelTypes.FRIEND, BOTH ), maxDepth );
142  
143         Path path = finder.findSinglePath( underlyingNode,
144                 otherPerson.getUnderlyingNode() );
145         return createPersonsFromNodes( path );
146     }
147  
148     public Iterable<PersonNode> getFriendRecommendation(
149             int numberOfFriendsToReturn )
150     {
151         HashSet<PersonNode> friends = new HashSet<>();
152         IteratorUtil.addToCollection( getFriends(), friends );
153  
154         HashSet<PersonNode> friendsOfFriends = new HashSet<>();
155         IteratorUtil.addToCollection( getFriendsOfFriends(), friendsOfFriends );
156  
157         friendsOfFriends.removeAll( friends );
158  
159         ArrayList<RankedPerson> rankedFriends = new ArrayList<>();
160         for ( PersonNode friend : friendsOfFriends )
161         {
162             int rank = getNumberOfPathsToPerson( friend );
163             rankedFriends.add( new RankedPerson( friend, rank ) );
164         }
165  
166         Collections.sort( rankedFriends, new RankedComparer() );
167         trimTo( rankedFriends, numberOfFriendsToReturn );
168  
169         return onlyFriend( rankedFriends );
170     }
171  
172     // Status update management
173  
174     public Iterable<StatusUpdateNode> getStatus()
175     {
176         Relationship firstStatus = underlyingNode.getSingleRelationship(
177                         RelTypes.STATUS, Direction.OUTGOING );
178         if ( firstStatus == null )
179         {
180             return Collections.emptyList();
181         }
182  
183         // START SNIPPET: getStatusTraversal
184         TraversalDescription traversal = graphDb().traversalDescription()
185                 .depthFirst()
186                 .relationships( RelTypes.NEXT );
187         // END SNIPPET: getStatusTraversal
188  
189  
190         return new IterableWrapper<StatusUpdateNode, Path>(
191                 traversal.traverse( firstStatus.getEndNode() ) )
192         {
193             @Override
194             protected StatusUpdateNode underlyingObjectToObject( Path path )
195             {
196                 return new StatusUpdateNode( path.endNode() );
197             }
198         };
199     }
200  
201     public Iterator<StatusUpdateNode> friendStatuses()
202     {
203         return new FriendsStatusUpdateIterator( this );
204     }
205  
206     public void addStatus( String text )
207     {
208         StatusUpdateNode oldStatus;
209         if ( getStatus().iterator().hasNext() )
210         {
211             oldStatus = getStatus().iterator().next();
212         } else
213         {
214             oldStatus = null;
215         }
216  
217         Node newStatus = createNewStatusNode( text );
218  
219         if ( oldStatus != null )
220         {
221             underlyingNode.getSingleRelationship( RelTypes.STATUS, Direction.OUTGOING ).delete();
222             newStatus.createRelationshipTo( oldStatus.getUnderlyingNode(), RelTypes.NEXT );
223         }
224  
225         underlyingNode.createRelationshipTo( newStatus, RelTypes.STATUS );
226     }
227  
228     private GraphDatabaseService graphDb()
229     {
230         return underlyingNode.getGraphDatabase();
231     }
232  
233     private Node createNewStatusNode( String text )
234     {
235         Node newStatus = graphDb().createNode();
236         newStatus.setProperty( StatusUpdateNode.TEXT, text );
237         newStatus.setProperty( StatusUpdateNode.DATE, new Date().getTime() );
238         return newStatus;
239     }
240  
241     private final class RankedPerson
242     {
243         final PersonNode person;
244  
245         final int rank;
246  
247         private RankedPerson( PersonNode person, int rank )
248         {
249  
250             this.person = person;
251             this.rank = rank;
252         }
253  
254         public PersonNode getPerson()
255         {
256             return person;
257         }
258         public int getRank()
259         {
260             return rank;
261         }
262  
263     }
264  
265     private class RankedComparer implements Comparator<RankedPerson>
266     {
267         @Override
268         public int compare( RankedPerson a, RankedPerson b )
269         {
270             return b.getRank() - a.getRank();
271         }
272  
273     }
274  
275     private void trimTo( ArrayList<RankedPerson> rankedFriends,
276                          int numberOfFriendsToReturn )
277     {
278         while ( rankedFriends.size() > numberOfFriendsToReturn )
279         {
280             rankedFriends.remove( rankedFriends.size() - 1 );
281         }
282     }
283  
284     private Iterable<PersonNode> onlyFriend( Iterable<RankedPerson> rankedFriends )
285     {
286         ArrayList<PersonNode> retVal = new ArrayList<>();
287         for ( RankedPerson person : rankedFriends )
288         {
289             retVal.add( person.getPerson() );
290         }
291         return retVal;
292     }
293  
294     private Relationship getFriendRelationshipTo( PersonNode otherPerson )
295     {
296         Node otherNode = otherPerson.getUnderlyingNode();
297         for ( Relationship rel : underlyingNode.getRelationships( RelTypes.FRIEND ) )
298         {
299             if ( rel.getOtherNode( underlyingNode ).equals( otherNode ) )
300             {
301                 return rel;
302             }
303         }
304         return null;
305     }
306  
307     private Iterable<PersonNode> getFriendsByDepth( int depth )
308     {
309         // return all my friends and their friends using new traversal API
310         TraversalDescription travDesc = graphDb().traversalDescription()
311                 .breadthFirst()
312                 .relationships( RelTypes.FRIEND )
313                 .uniqueness( Uniqueness.NODE_GLOBAL )
314                 .evaluator( Evaluators.toDepth( depth ) )
315                 .evaluator( Evaluators.excludeStartPosition() );
316  
317         return createPersonsFromPath( travDesc.traverse( underlyingNode ) );
318     }
319  
320     private IterableWrapper<PersonNode, Path> createPersonsFromPath(
321             Traverser iterableToWrap )
322     {
323         return new IterableWrapper<PersonNode, Path>( iterableToWrap )
324         {
325             @Override
326             protected PersonNode underlyingObjectToObject( Path path )
327             {
328                 return new PersonNode( path.endNode() );
329             }
330         };
331     }
332  
333     private int getNumberOfPathsToPerson( PersonNode otherPerson )
334     {
335         PathFinder<Path> finder = GraphAlgoFactory.allPaths( forTypeAndDirection( RelTypes.FRIEND, BOTH ), 2 );
336         Iterable<Path> paths = finder.findAllPaths( getUnderlyingNode(), otherPerson.getUnderlyingNode() );
337         return IteratorUtil.count( paths );
338     }
339  
340     private Iterable<PersonNode> createPersonsFromNodes( final Path path )
341     {
342         return new IterableWrapper<PersonNode, Node>( path.nodes() )
343         {
344             @Override
345             protected PersonNode underlyingObjectToObject( Node node )
346             {
347                 return new PersonNode( node );
348             }
349         };
350     }
351  
352     ///////////////////////////////
353  
354     /**
355      * Create a relationship between person and album
356      * @param album
357      */
358  
359     private IterableWrapper<AlbumNode, Path> createAlbumsFromPath(
360             Traverser iterableToWrap )
361     {
362         return new IterableWrapper<AlbumNode, Path>( iterableToWrap )
363         {
364             @Override
365             protected AlbumNode underlyingObjectToObject( Path path )
366             {
367                 return new AlbumNode( path.endNode() );
368             }
369         };
370     }
371  
372  
373     public void addAlbum(AlbumNode album){
374         underlyingNode.createRelationshipTo( album.getUnderlyingNode(), RelTypes.HAS_ALBUM );      
375     }
376  
377     public Iterable<AlbumNode> getAlbums(){
378         TraversalDescription travDesc = graphDb().traversalDescription()
379                 .breadthFirst()
380                 .relationships( RelTypes.HAS_ALBUM )
381                 .uniqueness( Uniqueness.NODE_GLOBAL )
382                 .evaluator( Evaluators.toDepth( 1 ) )
383                 .evaluator( Evaluators.excludeStartPosition() );
384  
385         return createAlbumsFromPath( travDesc.traverse( underlyingNode ) );
386  
387     }
388  
389 }