Neo4j Traverser into table

Hi All,

Today, I would like to post a bit of my creation on the data Neo4j traversal. As you know that Neo4j traversal is one of powerful engine which may traverse a million of hops in just milliseconds. I created a class that uses the Neo4j traversal and show  the traversed node in the form of table. For some people it is easier to have their data shown in the table such as excel as below

Table Capture

To create this class, I use 3 component which are PathExpander, Traverser and Evaluators. The combination of them are just amazing. To create the data are able to show into table form as shown above, I use library downloaded from google code called BTC-ASCII-Table.

Here are my full class.


package neo4j.mytraversal;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.neo4j.cypher.internal.pipes.matching.MyEvaluator;
import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.DynamicRelationshipType;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Path;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.RelationshipType;
import org.neo4j.graphdb.traversal.Evaluation;
import org.neo4j.graphdb.traversal.Evaluator;
import org.neo4j.graphdb.traversal.Evaluators;
import org.neo4j.graphdb.traversal.TraversalDescription;
import org.neo4j.kernel.StandardExpander;
import org.neo4j.kernel.Uniqueness;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.neo4j.support.Neo4jTemplate;

import scala.actors.threadpool.Arrays;

import com.bethecoder.ascii_table.ASCIITable;

public class Runner {

@Autowired
Neo4jTemplate template;
Iterator<Path> path;

final MeExpander expander;

Map<Integer, List<String>> level;

public Runner() {
// TODO Auto-generated constructor stub
expander = new MeExpander();
level = new HashMap<Integer, List<String>>();
}

public void addRealtionshipSequence(String relationsipName,
Direction direction, Integer depth) {
expander.addRelationName(new NodeSequence(relationsipName, direction),
depth);
}

public void showField(int depth, String[] fields) {
level.put(depth, Arrays.asList(fields));
}

public void print() {

List<Map<String, String>> valuList = new ArrayList<Map<String, String>>();

while (path.hasNext()) {
Path temp = path.next();
Iterator<Node> nodeIterator = temp.nodes().iterator();
int itCount = 0;
Map<String, String> tempValue = new HashMap<String, String>();
while (nodeIterator.hasNext()) {
Node node = nodeIterator.next();
Iterator<Integer> i = level.keySet().iterator();
while (i.hasNext()) {
int key = i.next();
if (itCount == key) {
List<String> val = level.get(key);
List<String> newVal = new ArrayList<String>();
newVal.addAll(val);

String firstItem = newVal.get(0);

if (firstItem.equals("*")) {
Iterator<String> itProp = node.getPropertyKeys()
.iterator();
while (itProp.hasNext()) {
String fieldExtract = itProp.next();
if (!newVal.contains(itCount + "-"
+ fieldExtract)) {
newVal.add(itCount + "-" + fieldExtract);
}
tempValue.put(itCount + "-" + fieldExtract,
node.getProperty(fieldExtract)
.toString());
}
} else {
for (int checkfieldit = 0; checkfieldit < newVal
.size(); checkfieldit++) {
if (node.hasProperty(newVal.get(checkfieldit))) {
tempValue.put(
itCount + "-"
+ newVal.get(checkfieldit),
node.getProperty(
newVal.get(checkfieldit))
.toString());
if (!newVal.contains(itCount + "-"
+ newVal.get(checkfieldit))) {
newVal.add(itCount + "-" + newVal.get(checkfieldit));

}
if (!path.hasNext()) {
newVal.remove(newVal.get(checkfieldit));
}
}
}
}

if (!path.hasNext()) {
newVal.remove("*");
}

level.put(key, newVal);


}
}
itCount++;
}
valuList.add(tempValue);
}

List<String> Header = upHeader(level);
printTable(Header, valuList);
}

public void traverse(Long nodeID) {
if (template != null) {
TraversalDescription desc = template.traversalDescription()
.breadthFirst().evaluator(new Evaluator() {
public Evaluation evaluate(Path path) {
return Evaluation.INCLUDE_AND_CONTINUE;
}
}).expand(expander).evaluator(Evaluators.excludeStartPosition());

path = desc.traverse(template.getNode(nodeID)).iterator();
}

}

public List<String> upHeader(Map<Integer, List<String>> level) {
List<String> temp = new ArrayList<String>();
Iterator<Integer> ii = level.keySet().iterator();
while (ii.hasNext()) {
List<String> a = level.get(ii.next());
for (int i = 0; i < a.size(); i++) {
if (!temp.contains(a.get(i))) {
temp.add(a.get(i));
}
}
}
return temp;
}

public void printTable(List<String> header, List<Map<String, String>> row) {
String newHeader[] = new String[header.size()];
String[][] result = new String[row.size()][header.size()];

for (int i = 0; i < header.size(); i++) {
newHeader[i] = header.get(i);
}

for (int i = 0; i < row.size(); i++) {
for (int ii = 0; ii < header.size(); ii++) {
result[i][ii] = "";
}
}


for (int i = 0; i < row.size(); i++) {
Map<String, String> valueRow = row.get(i);
for (int ii = 0; ii < header.size(); ii++) {
if (valueRow.containsKey(header.get(ii))) {
result[i][ii] = valueRow.get(header.get(ii));
System.out.println(result[i][ii] + header.get(ii));
}
}
}

ASCIITable.getInstance().printTable(newHeader, result);
}

}


The above class is the main class which do the trick which do the traversal and print the data into table. In order to use the application correctly here is sample

public class Runner {

@Autowired
Neo4jTemplate template;
Iterator<Path> path;
final MeExpander expander;
Map<Integer, List<String>> level;

public Runner() {

expander = new MeExpander();
level = new HashMap<Integer, List<String>>();
}

public void addRealtionshipSequence(String relationsipName, Direction direction, Integer depth) {
expander.addRelationName(new NodeSequence(relationsipName, direction), depth);
}

public void showField(int depth, String[] fields) {
level.put(depth, Arrays.asList(fields));
}

public void print() {
List<Map<String, String>> valuList = new ArrayList<Map<String, String>>();

while (path.hasNext()) {
Path temp = path.next();
Iterator<Node> nodeIterator = temp.nodes().iterator();
int itCount = 0;
Map<String, String> tempValue = new HashMap<String, String>();
while (nodeIterator.hasNext()) {
Node node = nodeIterator.next();
Iterator<Integer> i = level.keySet().iterator();

while (i.hasNext()) {
int key = i.next();
if (itCount == key) {
List<String> val = level.get(key);
List<String> newVal = new ArrayList<String>();
newVal.addAll(val);
String firstItem = newVal.get(0);

if (firstItem.equals("*")) {
Iterator<String> itProp = node.getPropertyKeys().iterator();
while (itProp.hasNext()) {
String fieldExtract = itProp.next();
if (!newVal.contains(itCount + "-"+ fieldExtract)) {
newVal.add(itCount + "-" + fieldExtract);
}
tempValue.put(itCount + "-" + fieldExtract, node.getProperty(fieldExtract).toString());
}
} else {
for (int checkfieldit = 0; checkfieldit < newVal.size(); checkfieldit++) {
if (node.hasProperty(newVal.get(checkfieldit))) {
tempValue.put(itCount + "-"+ newVal.get(checkfieldit),node.getProperty(newVal.get(checkfieldit)).toString());
if (!newVal.contains(itCount + "-"+ newVal.get(checkfieldit))) {
newVal.add(itCount + "-" + newVal.get(checkfieldit));
}
if (!path.hasNext()) {
newVal.remove(newVal.get(checkfieldit));
}
}
}
}

if (!path.hasNext()) {
newVal.remove("*");
}

level.put(key, newVal);

}
}
itCount++;
}
valuList.add(tempValue);
}

List<String> Header = upHeader(level);
printTable(Header, valuList);
}

public void traverse(Long nodeID) {
if (template != null) {
TraversalDescription desc = template.traversalDescription().breadthFirst().evaluator(new Evaluator() {
public Evaluation evaluate(Path path) {
return Evaluation.INCLUDE_AND_CONTINUE;
}
}).expand(expander).evaluator(Evaluators.excludeStartPosition());

path = desc.traverse(template.getNode(nodeID)).iterator();
}

}

public List<String> upHeader(Map<Integer, List<String>> level) {
List<String> temp = new ArrayList<String>();
Iterator<Integer> ii = level.keySet().iterator();
while (ii.hasNext()) {
List<String> a = level.get(ii.next());
for (int i = 0; i < a.size(); i++) {
if (!temp.contains(a.get(i))) {
temp.add(a.get(i));
}
}
}
return temp;
}

public void printTable(List<String> header, List<Map<String, String>> row) {
String newHeader[] = new String[header.size()];
String[][] result = new String[row.size()][header.size()];

for (int i = 0; i < header.size(); i++) {
newHeader[i] = header.get(i);
}

for (int i = 0; i < row.size(); i++) {
for (int ii = 0; ii < header.size(); ii++) {
result[i][ii] = "";
}
}

for (int i = 0; i < row.size(); i++) {
Map<String, String> valueRow = row.get(i);
for (int ii = 0; ii < header.size(); ii++) {
if (valueRow.containsKey(header.get(ii))) {
result[i][ii] = valueRow.get(header.get(ii));
}
}
}

ASCIITable.getInstance().printTable(newHeader, result);
}

}

The above code will show the table as below

Table Capture
But if you wanted to change only viewing dome of the column then you may be able to change the * to the field name you want to show. As example below

<br />runner.showField(2, new String[]{"*"});<br />runner.showField(1, new String[]{"*"});<br />runner.showField(0, new String[]{"name"});<br />

NewTable

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s