/**
* Copyright (c) 2002-2010 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.neo4j.kernel.impl.traversal;
import org.junit.BeforeClass;
import org.junit.Test;
import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Path;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.traversal.TraversalDescription;
import org.neo4j.helpers.Predicate;
import org.neo4j.helpers.collection.IteratorUtil;
import org.neo4j.kernel.Traversal;
public class TestMultipleFilters extends AbstractTestBase
{
@BeforeClass
public static void setupGraph()
{
//
// (a)--------
// / \
// v v
// (b)-->(k)<----(c)-->(f)
// / \
// v v
// (d) (e)
createGraph( "a TO b", "b TO d", "b TO e", "b TO k", "a TO c", "c TO f", "c TO k" );
}
private static class MustBeConnectedToNodeFilter implements Predicate<Path>
{
private final Node node;
MustBeConnectedToNodeFilter( Node node )
{
this.node = node;
}
public boolean accept( Path item )
{
for ( Relationship rel : item.endNode().getRelationships( Direction.OUTGOING ) )
{
if ( rel.getEndNode().equals( node ) )
{
return true;
}
}
return false;
}
}
@Test
public void testNarrowingFilters()
{
Predicate<Path> mustBeConnectedToK = new MustBeConnectedToNodeFilter( getNodeWithName( "k" ) );
Predicate<Path> mustNotHaveMoreThanTwoOutRels = new Predicate<Path>()
{
public boolean accept( Path item )
{
return IteratorUtil.count( item.endNode().getRelationships( Direction.OUTGOING ) ) <= 2;
}
};
TraversalDescription description = Traversal.description().filter( mustBeConnectedToK );
expectNodes( description.traverse( referenceNode() ), "b", "c" );
expectNodes( description.filter( mustNotHaveMoreThanTwoOutRels ).traverse( referenceNode() ), "c" );
}
@Test
public void testBroadeningFilters()
{
Predicate<Path> mustBeConnectedToC = new MustBeConnectedToNodeFilter( getNodeWithName( "c" ) );
Predicate<Path> mustBeConnectedToE = new MustBeConnectedToNodeFilter( getNodeWithName( "e" ) );
// Nodes connected (OUTGOING) to c (which "a" is)
expectNodes( Traversal.description().filter( mustBeConnectedToC ).traverse( referenceNode() ), "a" );
// Nodes connected (OUTGOING) to c AND e (which none is)
expectNodes( Traversal.description().filter( mustBeConnectedToC ).filter( mustBeConnectedToE ).traverse( referenceNode() ) );
// Nodes connected (OUTGOING) to c OR e (which "a" and "b" is)
expectNodes( Traversal.description().filter( Traversal.returnAcceptedByAny( mustBeConnectedToC, mustBeConnectedToE ) ).traverse( referenceNode() ), "a", "b" );
}
}