Biblioteca Java - Rev 18
Subversion Repositories:
(root)/Frameworks and Technologies/Neo4J Samples/Neo4JTutorial/src/main/java/com/linkscreens/graphsin/repository/PersonNode.java @ 34
/**
* Licensed to Neo Technology under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Neo Technology licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package com.linkscreens.graphsin.repository;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import org.neo4j.graphalgo.GraphAlgoFactory;
import org.neo4j.graphalgo.PathFinder;
import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Path;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.traversal.Evaluators;
import org.neo4j.graphdb.traversal.TraversalDescription;
import org.neo4j.graphdb.traversal.Traverser;
import org.neo4j.helpers.collection.IterableWrapper;
import org.neo4j.helpers.collection.IteratorUtil;
import org.neo4j.graphdb.traversal.Uniqueness;
import com.linkscreens.graphsin.network.FriendsStatusUpdateIterator;
import static org.neo4j.graphdb.Direction.BOTH;
import static org.neo4j.graphdb.PathExpanders.forTypeAndDirection;
public class PersonNode
{
public static final String EMAIL = "email";
// START SNIPPET: the-node
private final Node underlyingNode;
public PersonNode( Node personNode )
{
this.underlyingNode = personNode;
}
public Node getUnderlyingNode()
{
return underlyingNode;
}
// END SNIPPET: the-node
// START SNIPPET: delegate-to-the-node
public String getName()
{
return (String)underlyingNode.getProperty( EMAIL );
}
// END SNIPPET: delegate-to-the-node
// START SNIPPET: override
@Override
public int hashCode()
{
return underlyingNode.hashCode();
}
@Override
public boolean equals( Object o )
{
return o instanceof PersonNode &&
underlyingNode.equals( ( (PersonNode)o ).getUnderlyingNode() );
}
@Override
public String toString()
{
return "Person[" + getName() + "]";
}
// END SNIPPET: override
public void addFriend( PersonNode otherPerson )
{
if ( !this.equals( otherPerson ) )
{
Relationship friendRel = getFriendRelationshipTo( otherPerson );
if ( friendRel == null )
{
underlyingNode.createRelationshipTo( otherPerson.getUnderlyingNode(), RelTypes.FRIEND );
}
}
}
public int getNrOfFriends()
{
return IteratorUtil.count( getFriends() );
}
public Iterable<PersonNode> getFriends()
{
return getFriendsByDepth( 1 );
}
public void removeFriend( PersonNode otherPerson )
{
if ( !this.equals( otherPerson ) )
{
Relationship friendRel = getFriendRelationshipTo( otherPerson );
if ( friendRel != null )
{
friendRel.delete();
}
}
}
public Iterable<PersonNode> getFriendsOfFriends()
{
return getFriendsByDepth( 2 );
}
public Iterable<PersonNode> getShortestPathTo( PersonNode otherPerson,
int maxDepth )
{
// use graph algo to calculate a shortest path
PathFinder<Path> finder = GraphAlgoFactory.shortestPath(
forTypeAndDirection(RelTypes.FRIEND, BOTH ), maxDepth );
Path path = finder.findSinglePath( underlyingNode,
otherPerson.getUnderlyingNode() );
return createPersonsFromNodes( path );
}
public Iterable<PersonNode> getFriendRecommendation(
int numberOfFriendsToReturn )
{
HashSet<PersonNode> friends = new HashSet<>();
IteratorUtil.addToCollection( getFriends(), friends );
HashSet<PersonNode> friendsOfFriends = new HashSet<>();
IteratorUtil.addToCollection( getFriendsOfFriends(), friendsOfFriends );
friendsOfFriends.removeAll( friends );
ArrayList<RankedPerson> rankedFriends = new ArrayList<>();
for ( PersonNode friend : friendsOfFriends )
{
int rank = getNumberOfPathsToPerson( friend );
rankedFriends.add( new RankedPerson( friend, rank ) );
}
Collections.sort( rankedFriends, new RankedComparer() );
trimTo( rankedFriends, numberOfFriendsToReturn );
return onlyFriend( rankedFriends );
}
// Status update management
public Iterable<StatusUpdateNode> getStatus()
{
Relationship firstStatus = underlyingNode.getSingleRelationship(
RelTypes.STATUS, Direction.OUTGOING );
if ( firstStatus == null )
{
return Collections.emptyList();
}
// START SNIPPET: getStatusTraversal
TraversalDescription traversal = graphDb().traversalDescription()
.depthFirst()
.relationships( RelTypes.NEXT );
// END SNIPPET: getStatusTraversal
return new IterableWrapper<StatusUpdateNode, Path>(
traversal.traverse( firstStatus.getEndNode() ) )
{
@Override
protected StatusUpdateNode underlyingObjectToObject( Path path )
{
return new StatusUpdateNode( path.endNode() );
}
};
}
public Iterator<StatusUpdateNode> friendStatuses()
{
return new FriendsStatusUpdateIterator( this );
}
public void addStatus( String text )
{
StatusUpdateNode oldStatus;
if ( getStatus().iterator().hasNext() )
{
oldStatus = getStatus().iterator().next();
} else
{
oldStatus = null;
}
Node newStatus = createNewStatusNode( text );
if ( oldStatus != null )
{
underlyingNode.getSingleRelationship( RelTypes.STATUS, Direction.OUTGOING ).delete();
newStatus.createRelationshipTo( oldStatus.getUnderlyingNode(), RelTypes.NEXT );
}
underlyingNode.createRelationshipTo( newStatus, RelTypes.STATUS );
}
private GraphDatabaseService graphDb()
{
return underlyingNode.getGraphDatabase();
}
private Node createNewStatusNode( String text )
{
Node newStatus = graphDb().createNode();
newStatus.setProperty( StatusUpdateNode.TEXT, text );
newStatus.setProperty( StatusUpdateNode.DATE, new Date().getTime() );
return newStatus;
}
private final class RankedPerson
{
final PersonNode person;
final int rank;
private RankedPerson( PersonNode person, int rank )
{
this.person = person;
this.rank = rank;
}
public PersonNode getPerson()
{
return person;
}
public int getRank()
{
return rank;
}
}
private class RankedComparer implements Comparator<RankedPerson>
{
@Override
public int compare( RankedPerson a, RankedPerson b )
{
return b.getRank() - a.getRank();
}
}
private void trimTo( ArrayList<RankedPerson> rankedFriends,
int numberOfFriendsToReturn )
{
while ( rankedFriends.size() > numberOfFriendsToReturn )
{
rankedFriends.remove( rankedFriends.size() - 1 );
}
}
private Iterable<PersonNode> onlyFriend( Iterable<RankedPerson> rankedFriends )
{
ArrayList<PersonNode> retVal = new ArrayList<>();
for ( RankedPerson person : rankedFriends )
{
retVal.add( person.getPerson() );
}
return retVal;
}
private Relationship getFriendRelationshipTo( PersonNode otherPerson )
{
Node otherNode = otherPerson.getUnderlyingNode();
for ( Relationship rel : underlyingNode.getRelationships( RelTypes.FRIEND ) )
{
if ( rel.getOtherNode( underlyingNode ).equals( otherNode ) )
{
return rel;
}
}
return null;
}
private Iterable<PersonNode> getFriendsByDepth( int depth )
{
// return all my friends and their friends using new traversal API
TraversalDescription travDesc = graphDb().traversalDescription()
.breadthFirst()
.relationships( RelTypes.FRIEND )
.uniqueness( Uniqueness.NODE_GLOBAL )
.evaluator( Evaluators.toDepth( depth ) )
.evaluator( Evaluators.excludeStartPosition() );
return createPersonsFromPath( travDesc.traverse( underlyingNode ) );
}
private IterableWrapper<PersonNode, Path> createPersonsFromPath(
Traverser iterableToWrap )
{
return new IterableWrapper<PersonNode, Path>( iterableToWrap )
{
@Override
protected PersonNode underlyingObjectToObject( Path path )
{
return new PersonNode( path.endNode() );
}
};
}
private int getNumberOfPathsToPerson( PersonNode otherPerson )
{
PathFinder<Path> finder = GraphAlgoFactory.allPaths( forTypeAndDirection( RelTypes.FRIEND, BOTH ), 2 );
Iterable<Path> paths = finder.findAllPaths( getUnderlyingNode(), otherPerson.getUnderlyingNode() );
return IteratorUtil.count( paths );
}
private Iterable<PersonNode> createPersonsFromNodes( final Path path )
{
return new IterableWrapper<PersonNode, Node>( path.nodes() )
{
@Override
protected PersonNode underlyingObjectToObject( Node node )
{
return new PersonNode( node );
}
};
}
///////////////////////////////
/**
* Create a relationship between person and album
* @param album
*/
private IterableWrapper<AlbumNode, Path> createAlbumsFromPath(
Traverser iterableToWrap )
{
return new IterableWrapper<AlbumNode, Path>( iterableToWrap )
{
@Override
protected AlbumNode underlyingObjectToObject( Path path )
{
return new AlbumNode( path.endNode() );
}
};
}
public void addAlbum(AlbumNode album){
underlyingNode.createRelationshipTo( album.getUnderlyingNode(), RelTypes.HAS_ALBUM );
}
public Iterable<AlbumNode> getAlbums(){
TraversalDescription travDesc = graphDb().traversalDescription()
.breadthFirst()
.relationships( RelTypes.HAS_ALBUM )
.uniqueness( Uniqueness.NODE_GLOBAL )
.evaluator( Evaluators.toDepth( 1 ) )
.evaluator( Evaluators.excludeStartPosition() );
return createAlbumsFromPath( travDesc.traverse( underlyingNode ) );
}
}
* Licensed to Neo Technology under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Neo Technology licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package com.linkscreens.graphsin.repository;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import org.neo4j.graphalgo.GraphAlgoFactory;
import org.neo4j.graphalgo.PathFinder;
import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Path;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.traversal.Evaluators;
import org.neo4j.graphdb.traversal.TraversalDescription;
import org.neo4j.graphdb.traversal.Traverser;
import org.neo4j.helpers.collection.IterableWrapper;
import org.neo4j.helpers.collection.IteratorUtil;
import org.neo4j.graphdb.traversal.Uniqueness;
import com.linkscreens.graphsin.network.FriendsStatusUpdateIterator;
import static org.neo4j.graphdb.Direction.BOTH;
import static org.neo4j.graphdb.PathExpanders.forTypeAndDirection;
public class PersonNode
{
public static final String EMAIL = "email";
// START SNIPPET: the-node
private final Node underlyingNode;
public PersonNode( Node personNode )
{
this.underlyingNode = personNode;
}
public Node getUnderlyingNode()
{
return underlyingNode;
}
// END SNIPPET: the-node
// START SNIPPET: delegate-to-the-node
public String getName()
{
return (String)underlyingNode.getProperty( EMAIL );
}
// END SNIPPET: delegate-to-the-node
// START SNIPPET: override
@Override
public int hashCode()
{
return underlyingNode.hashCode();
}
@Override
public boolean equals( Object o )
{
return o instanceof PersonNode &&
underlyingNode.equals( ( (PersonNode)o ).getUnderlyingNode() );
}
@Override
public String toString()
{
return "Person[" + getName() + "]";
}
// END SNIPPET: override
public void addFriend( PersonNode otherPerson )
{
if ( !this.equals( otherPerson ) )
{
Relationship friendRel = getFriendRelationshipTo( otherPerson );
if ( friendRel == null )
{
underlyingNode.createRelationshipTo( otherPerson.getUnderlyingNode(), RelTypes.FRIEND );
}
}
}
public int getNrOfFriends()
{
return IteratorUtil.count( getFriends() );
}
public Iterable<PersonNode> getFriends()
{
return getFriendsByDepth( 1 );
}
public void removeFriend( PersonNode otherPerson )
{
if ( !this.equals( otherPerson ) )
{
Relationship friendRel = getFriendRelationshipTo( otherPerson );
if ( friendRel != null )
{
friendRel.delete();
}
}
}
public Iterable<PersonNode> getFriendsOfFriends()
{
return getFriendsByDepth( 2 );
}
public Iterable<PersonNode> getShortestPathTo( PersonNode otherPerson,
int maxDepth )
{
// use graph algo to calculate a shortest path
PathFinder<Path> finder = GraphAlgoFactory.shortestPath(
forTypeAndDirection(RelTypes.FRIEND, BOTH ), maxDepth );
Path path = finder.findSinglePath( underlyingNode,
otherPerson.getUnderlyingNode() );
return createPersonsFromNodes( path );
}
public Iterable<PersonNode> getFriendRecommendation(
int numberOfFriendsToReturn )
{
HashSet<PersonNode> friends = new HashSet<>();
IteratorUtil.addToCollection( getFriends(), friends );
HashSet<PersonNode> friendsOfFriends = new HashSet<>();
IteratorUtil.addToCollection( getFriendsOfFriends(), friendsOfFriends );
friendsOfFriends.removeAll( friends );
ArrayList<RankedPerson> rankedFriends = new ArrayList<>();
for ( PersonNode friend : friendsOfFriends )
{
int rank = getNumberOfPathsToPerson( friend );
rankedFriends.add( new RankedPerson( friend, rank ) );
}
Collections.sort( rankedFriends, new RankedComparer() );
trimTo( rankedFriends, numberOfFriendsToReturn );
return onlyFriend( rankedFriends );
}
// Status update management
public Iterable<StatusUpdateNode> getStatus()
{
Relationship firstStatus = underlyingNode.getSingleRelationship(
RelTypes.STATUS, Direction.OUTGOING );
if ( firstStatus == null )
{
return Collections.emptyList();
}
// START SNIPPET: getStatusTraversal
TraversalDescription traversal = graphDb().traversalDescription()
.depthFirst()
.relationships( RelTypes.NEXT );
// END SNIPPET: getStatusTraversal
return new IterableWrapper<StatusUpdateNode, Path>(
traversal.traverse( firstStatus.getEndNode() ) )
{
@Override
protected StatusUpdateNode underlyingObjectToObject( Path path )
{
return new StatusUpdateNode( path.endNode() );
}
};
}
public Iterator<StatusUpdateNode> friendStatuses()
{
return new FriendsStatusUpdateIterator( this );
}
public void addStatus( String text )
{
StatusUpdateNode oldStatus;
if ( getStatus().iterator().hasNext() )
{
oldStatus = getStatus().iterator().next();
} else
{
oldStatus = null;
}
Node newStatus = createNewStatusNode( text );
if ( oldStatus != null )
{
underlyingNode.getSingleRelationship( RelTypes.STATUS, Direction.OUTGOING ).delete();
newStatus.createRelationshipTo( oldStatus.getUnderlyingNode(), RelTypes.NEXT );
}
underlyingNode.createRelationshipTo( newStatus, RelTypes.STATUS );
}
private GraphDatabaseService graphDb()
{
return underlyingNode.getGraphDatabase();
}
private Node createNewStatusNode( String text )
{
Node newStatus = graphDb().createNode();
newStatus.setProperty( StatusUpdateNode.TEXT, text );
newStatus.setProperty( StatusUpdateNode.DATE, new Date().getTime() );
return newStatus;
}
private final class RankedPerson
{
final PersonNode person;
final int rank;
private RankedPerson( PersonNode person, int rank )
{
this.person = person;
this.rank = rank;
}
public PersonNode getPerson()
{
return person;
}
public int getRank()
{
return rank;
}
}
private class RankedComparer implements Comparator<RankedPerson>
{
@Override
public int compare( RankedPerson a, RankedPerson b )
{
return b.getRank() - a.getRank();
}
}
private void trimTo( ArrayList<RankedPerson> rankedFriends,
int numberOfFriendsToReturn )
{
while ( rankedFriends.size() > numberOfFriendsToReturn )
{
rankedFriends.remove( rankedFriends.size() - 1 );
}
}
private Iterable<PersonNode> onlyFriend( Iterable<RankedPerson> rankedFriends )
{
ArrayList<PersonNode> retVal = new ArrayList<>();
for ( RankedPerson person : rankedFriends )
{
retVal.add( person.getPerson() );
}
return retVal;
}
private Relationship getFriendRelationshipTo( PersonNode otherPerson )
{
Node otherNode = otherPerson.getUnderlyingNode();
for ( Relationship rel : underlyingNode.getRelationships( RelTypes.FRIEND ) )
{
if ( rel.getOtherNode( underlyingNode ).equals( otherNode ) )
{
return rel;
}
}
return null;
}
private Iterable<PersonNode> getFriendsByDepth( int depth )
{
// return all my friends and their friends using new traversal API
TraversalDescription travDesc = graphDb().traversalDescription()
.breadthFirst()
.relationships( RelTypes.FRIEND )
.uniqueness( Uniqueness.NODE_GLOBAL )
.evaluator( Evaluators.toDepth( depth ) )
.evaluator( Evaluators.excludeStartPosition() );
return createPersonsFromPath( travDesc.traverse( underlyingNode ) );
}
private IterableWrapper<PersonNode, Path> createPersonsFromPath(
Traverser iterableToWrap )
{
return new IterableWrapper<PersonNode, Path>( iterableToWrap )
{
@Override
protected PersonNode underlyingObjectToObject( Path path )
{
return new PersonNode( path.endNode() );
}
};
}
private int getNumberOfPathsToPerson( PersonNode otherPerson )
{
PathFinder<Path> finder = GraphAlgoFactory.allPaths( forTypeAndDirection( RelTypes.FRIEND, BOTH ), 2 );
Iterable<Path> paths = finder.findAllPaths( getUnderlyingNode(), otherPerson.getUnderlyingNode() );
return IteratorUtil.count( paths );
}
private Iterable<PersonNode> createPersonsFromNodes( final Path path )
{
return new IterableWrapper<PersonNode, Node>( path.nodes() )
{
@Override
protected PersonNode underlyingObjectToObject( Node node )
{
return new PersonNode( node );
}
};
}
///////////////////////////////
/**
* Create a relationship between person and album
* @param album
*/
private IterableWrapper<AlbumNode, Path> createAlbumsFromPath(
Traverser iterableToWrap )
{
return new IterableWrapper<AlbumNode, Path>( iterableToWrap )
{
@Override
protected AlbumNode underlyingObjectToObject( Path path )
{
return new AlbumNode( path.endNode() );
}
};
}
public void addAlbum(AlbumNode album){
underlyingNode.createRelationshipTo( album.getUnderlyingNode(), RelTypes.HAS_ALBUM );
}
public Iterable<AlbumNode> getAlbums(){
TraversalDescription travDesc = graphDb().traversalDescription()
.breadthFirst()
.relationships( RelTypes.HAS_ALBUM )
.uniqueness( Uniqueness.NODE_GLOBAL )
.evaluator( Evaluators.toDepth( 1 ) )
.evaluator( Evaluators.excludeStartPosition() );
return createAlbumsFromPath( travDesc.traverse( underlyingNode ) );
}
}