@@ -0,0 +1,122 @@
package com.graphaware.crawler.integration;

import com.graphaware.common.strategy.NodeInclusionStrategy;
import com.graphaware.common.strategy.RelationshipInclusionStrategy;
import com.graphaware.crawler.CrawlerRuntimeModule;
import com.graphaware.runtime.ProductionGraphAwareRuntime;
import java.util.LinkedList;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.neo4j.graphdb.DynamicLabel;
import org.neo4j.graphdb.DynamicRelationshipType;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Label;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.RelationshipType;
import org.neo4j.graphdb.ResourceIterable;
import org.neo4j.graphdb.Transaction;
import org.neo4j.helpers.Pair;
import org.neo4j.test.TestGraphDatabaseFactory;

/**
* This is a just playground, in truth. It won't be here for very long.
*/
public class NeoRankTest {

private GraphDatabaseService database;

/**
* Sets the up ;)
*/
@Before
public void setUp() {
this.database = new TestGraphDatabaseFactory().newImpermanentDatabase();
}

@Test
public void shouldBeAbleToCrawlAnArbitraryGraph() {
@SuppressWarnings("serial")
List<Pair<String, String>> folks = new LinkedList<Pair<String, String>>() {
{
add(Pair.of("Jeff", "Chris"));
add(Pair.of("Jeff", "Paul"));
add(Pair.of("Jeff", "Matthew"));
add(Pair.of("Gary", "Alan"));
add(Pair.of("Gary", "Robbie"));
add(Pair.of("Gary", "Mark"));
add(Pair.of("Gary", "Sue"));
add(Pair.of("John", "Matthew"));
add(Pair.of("John", "Sue"));
}
};

// first, we need a graph to crawl
try (Transaction transaction = this.database.beginTx()) {
Label personLabel = DynamicLabel.label("Person");
RelationshipType relationshipType = Relationships.CASUAL;

for (Pair<String, String> pairOfPeople : folks) {
Node person = findOrCreateNode(personLabel, pairOfPeople.first());
Node colleague = findOrCreateNode(personLabel, pairOfPeople.other());
person.createRelationshipTo(colleague, relationshipType);
}

transaction.success();
}

// so, now we have a graph, we can set up a crawler to find big bosses (i.e., who's got no incoming BOSS_OF relationship)


// this is serving the same purpose as the MATCH part of a cypher query, but is applied at each step of the graph walk
NodeInclusionStrategy nodeInclusionStrategy = new NodeInclusionStrategy() {
@Override
public boolean include(Node object) {
// for this example, I could easily say "does this node have any incoming relationships"
return object.hasLabel(DynamicLabel.label("Person"));
}
};

/* Adam: Any suggestions on how to extend the framework, so it
also includes the relationship types?
*/
RelationshipInclusionStrategy relInclusionStrategy = new RelationshipInclusionStrategy() {
@Override
public boolean include(Relationship object) {
return true;
}
};

ProductionGraphAwareRuntime graphAwareRuntime = new ProductionGraphAwareRuntime(this.database);
this.database.registerKernelEventHandler(graphAwareRuntime);
graphAwareRuntime.registerModule(new CrawlerRuntimeModule("TestingCrawler", nodeInclusionStrategy, relInclusionStrategy));

//assertFalse("The collection of names shouldn't be empty", namesOfBigBosses.isEmpty());
//Collections.sort(namesOfBigBosses);
//assertEquals("The resultant collection wasn't returned", Arrays.asList("Gary", "Jeff", "John"), namesOfBigBosses);
}

// TODO: this sort of thing should be part of GraphUnit, I reckon
private Node findOrCreateNode(Label label, String name) {
ResourceIterable<Node> existingNodes = this.database.findNodesByLabelAndProperty(label, "name", name);
if (existingNodes.iterator().hasNext()) {
return existingNodes.iterator().next();
}
Node newNode = this.database.createNode(label);
newNode.setProperty("name", name);
return newNode;
}

/*
MERGE (p:Person{name:'Jeff'}) MERGE (q:Person{name:'Chris'}) MERGE (p)-[:WORKS_WITH]->(q) RETURN p,q
MERGE (p:Person{name:'Jeff'}) MERGE (q:Person{name:'Paul'}) MERGE (p)-[:WORKS_WITH]->(q) RETURN p,q
MERGE (p:Person{name:'Jeff'}) MERGE (q:Person{name:'Matthew'}) MERGE (p)-[:WORKS_WITH]->(q) RETURN p,q
MERGE (p:Person{name:'Gary'}) MERGE (q:Person{name:'Alan'}) MERGE (p)-[:WORKS_WITH]->(q) RETURN p,q
MERGE (p:Person{name:'Gary'}) MERGE (q:Person{name:'Robbie'}) MERGE (p)-[:WORKS_WITH]->(q) RETURN p,q
MERGE (p:Person{name:'Gary'}) MERGE (q:Person{name:'Mark'}) MERGE (p)-[:WORKS_WITH]->(q) RETURN p,q
MERGE (p:Person{name:'Gary'}) MERGE (q:Person{name:'Sue'}) MERGE (p)-[:WORKS_WITH]->(q) RETURN p,q
MERGE (p:Person{name:'John'}) MERGE (q:Person{name:'Sue'}) MERGE (p)-[:WORKS_WITH]->(q) RETURN p,q
MERGE (p:Person{name:'John'}) MERGE (q:Person{name:'Matthew'}) MERGE (p)-[:WORKS_WITH]->(q) RETURN p,q
*/
}
@@ -0,0 +1,13 @@
package com.graphaware.crawler.integration;



import org.neo4j.graphdb.RelationshipType;

/**
* Enum of relationship used in NeoRank
* @author Vojta Havlicek (Graphaware)
*/
public enum Relationships implements RelationshipType {
CASUAL;
}
@@ -2,8 +2,6 @@

import static com.graphaware.common.util.IterableUtils.getSingle;

import java.lang.Exception;
import java.util.Iterator;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;