public static Collection<Scope> areCompatibleEdges( PlannerContext plannerContext, ElementGraph elementGraph, List<ScopeExpression> matchers, List<Scope> scopes )
{
// if more than one matcher edge, ignore ANY/ALL path modifier
if( matchers.size() == 1 )
{
ScopeExpression matcher = matchers.get( 0 );
// test ALL
if( matcher.appliesToAllPaths() )
{
for( Scope scope : scopes )
{
if( !matcher.applies( plannerContext, elementGraph, scope ) )
return null;
}
return scopes;
}
if( matcher.appliesToAnyPath() )
{
for( Scope scope : scopes )
{
if( matcher.applies( plannerContext, elementGraph, scope ) )
return Collections.singleton( scope );
}
return null;
}
if( matcher.appliesToEachPath() )
{
scopes = new LinkedList<>( scopes );
ListIterator<Scope> iterator = scopes.listIterator();
while( iterator.hasNext() )
{
if( !matcher.applies( plannerContext, elementGraph, iterator.next() ) )
iterator.remove();
}
return scopes.isEmpty() ? null : scopes;
}
}
// must have the same number of edges
if( matchers.size() != scopes.size() )
return null;
// build a square matrix of all match permutations
boolean[][] compat = new boolean[ matchers.size() ][ scopes.size() ];
for( int i = 0; i < matchers.size(); i++ )
{
ScopeExpression matcher = matchers.get( i );
for( int j = 0; j < scopes.size(); j++ )
{
Scope scope = scopes.get( j );
compat[ i ][ j ] = matcher.applies( plannerContext, elementGraph, scope );
}
}
// all matchers must fire for a given permutation
List<Integer> range = new ArrayList<>();