package org.neo4j.kernel.impl.traversal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Stack;
import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Path;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.RelationshipExpander;
import org.neo4j.graphdb.RelationshipType;
import org.neo4j.graphdb.ReturnableEvaluator;
import org.neo4j.graphdb.StopEvaluator;
import org.neo4j.graphdb.TraversalPosition;
import org.neo4j.graphdb.Traverser.Order;
import org.neo4j.graphdb.traversal.PruneEvaluator;
import org.neo4j.graphdb.traversal.TraversalDescription;
import org.neo4j.helpers.Predicate;
import org.neo4j.kernel.OrderedByTypeExpander;
import org.neo4j.kernel.Traversal;
import org.neo4j.kernel.Uniqueness;
public class OldTraverserWrapper
{
private static class TraverserImpl implements org.neo4j.graphdb.Traverser,
Iterator<Node>
{
private TraversalPosition currentPos;
private Iterator<Path> iter;
private int count;
public TraversalPosition currentPosition()
{
return currentPos;
}
public Collection<Node> getAllNodes()
{
List<Node> result = new ArrayList<Node>();
for ( Node node : this )
{
result.add( node );
}
return result;
}
public Iterator<Node> iterator()
{
return this;
}
public boolean hasNext()
{
return iter.hasNext();
}
public Node next()
{
currentPos = new PositionImpl( this, iter.next() );
count++;
return currentPos.currentNode();
}
public void remove()
{
throw new UnsupportedOperationException();
}
}
private static class PositionImpl implements TraversalPosition
{
private final Path position;
private final int count;
PositionImpl( TraverserImpl traverser, Path position )
{
this.position = position;
this.count = traverser.count;
}
public Node currentNode()
{
return position.endNode();
}
public int depth()
{
return position.length();
}
public boolean isStartNode()
{
return position.length() == 0;
}
public boolean notStartNode()
{
return !isStartNode();
}
public Relationship lastRelationshipTraversed()
{
return position.lastRelationship();
}
public Node previousNode()
{
return position.lastRelationship().getOtherNode( position.endNode() );
}
public int returnedNodesCount()
{
return count;
}
}
private static void assertNotNull( Object object, String message )
{
if ( object == null )
{
throw new IllegalArgumentException( "Null " + message );
}
}
private static final TraversalDescription BASE_DESCRIPTION =
Traversal.description().uniqueness( Uniqueness.NODE_GLOBAL );
public static org.neo4j.graphdb.Traverser traverse( Node node, Order traversalOrder,
StopEvaluator stopEvaluator,
ReturnableEvaluator returnableEvaluator,
Object... relationshipTypesAndDirections )
{
assertNotNull( traversalOrder, "order" );
assertNotNull( stopEvaluator, "stop evaluator" );
assertNotNull( returnableEvaluator, "returnable evaluator" );
if ( relationshipTypesAndDirections.length % 2 != 0
|| relationshipTypesAndDirections.length == 0 )
{
throw new IllegalArgumentException();
}
TraverserImpl result = new TraverserImpl();
TraversalDescription description = traversal( result, traversalOrder,
stopEvaluator, returnableEvaluator );
description = description.expand( toExpander( relationshipTypesAndDirections ) );
result.iter = description.traverse( node ).iterator();
return result;
}
private static RelationshipExpander toExpander(
Object[] relationshipTypesAndDirections )
{
Stack<Object[]> entries = new Stack<Object[]>();
for ( int i = 0; i < relationshipTypesAndDirections.length; i += 2 )
{
Object relType = relationshipTypesAndDirections[i];
if ( relType == null )
{
throw new IllegalArgumentException(
"Null relationship type at " + i );
}
if ( !(relType instanceof RelationshipType) )
{
throw new IllegalArgumentException(
"Expected RelationshipType at var args pos " + i
+ ", found " + relType );
}
Object direction = relationshipTypesAndDirections[i+1];
if ( direction == null )
{
throw new IllegalArgumentException(
"Null direction at " + (i+1) );
}
if ( !(direction instanceof Direction) )
{
throw new IllegalArgumentException(
"Expected Direction at var args pos " + (i+1)
+ ", found " + direction );
}
entries.push( new Object[] { relType, direction } );
}
OrderedByTypeExpander expander = new OrderedByTypeExpander();
while ( !entries.isEmpty() )
{
Object[] entry = entries.pop();
expander = (OrderedByTypeExpander) expander.add(
(RelationshipType) entry[0], (Direction) entry[1] );
}
return expander;
}
private static TraversalDescription traversal( TraverserImpl traverser,
Order order, StopEvaluator stopEvaluator,
ReturnableEvaluator returnableEvaluator )
{
TraversalDescription description = BASE_DESCRIPTION;
switch ( order )
{
case BREADTH_FIRST:
description = description.breadthFirst();
break;
case DEPTH_FIRST:
description = description.depthFirst();
break;
default:
throw new IllegalArgumentException( "Onsupported traversal order: "
+ order );
}
description = description.prune( new Pruner( traverser, stopEvaluator ) );
description = description.filter( new Filter( traverser,
returnableEvaluator ) );
return description;
}
private static class Pruner implements PruneEvaluator
{
private final TraverserImpl traverser;
private final StopEvaluator evaluator;
Pruner( TraverserImpl traverser, StopEvaluator stopEvaluator )
{
this.traverser = traverser;
this.evaluator = stopEvaluator;
}
public boolean pruneAfter( Path position )
{
return evaluator.isStopNode( new PositionImpl( traverser, position ) );
}
}
private static class Filter implements Predicate<Path>
{
private final TraverserImpl traverser;
private final ReturnableEvaluator evaluator;
Filter( TraverserImpl traverser, ReturnableEvaluator returnableEvaluator )
{
this.traverser = traverser;
this.evaluator = returnableEvaluator;
}
public boolean accept( Path position )
{
return evaluator.isReturnableNode( new PositionImpl( traverser,
position ) );
}
}
}