if ( path instanceof P_Link )
{
Node pred = ((P_Link)path).getNode() ;
Triple t = new Triple(startNode, pred, endNode) ;
x.add(new TriplePath(t)) ;
return ;
}
if ( path instanceof P_Seq )
{
P_Seq ps = (P_Seq)path ;
Node v = varAlloc.allocVar() ;
reduce(x, varAlloc, startNode, ps.getLeft(), v) ;
reduce(x, varAlloc, v, ps.getRight(), endNode) ;
return ;
}
if ( path instanceof P_Inverse )
{
reduce(x, varAlloc, endNode, ((P_Inverse)path).getSubPath(), startNode) ;
return ;
}
if ( path instanceof P_FixedLength )
{
P_FixedLength pFixed = (P_FixedLength)path ;
long N = pFixed.getCount() ;
if ( N > 0 )
{
// Don't do {0}
Node stepStart = startNode ;
for ( long i = 0 ; i < N-1 ; i++ )
{
Node v = varAlloc.allocVar() ;
reduce(x, varAlloc, stepStart, pFixed.getSubPath(), v) ;
stepStart = v ;
}
reduce(x, varAlloc, stepStart, pFixed.getSubPath(), endNode) ;
return ;
}
}
if ( path instanceof P_Mod )
{
P_Mod pMod = (P_Mod)path ;
if ( pMod.isFixedLength() && pMod.getFixedLength() > 0 )
{
long N = pMod.getFixedLength() ;
if ( N > 0 )
{
Node stepStart = startNode ;
for ( long i = 0 ; i < N-1 ; i++ )
{
Node v = varAlloc.allocVar() ;
reduce(x, varAlloc, stepStart, pMod.getSubPath(), v) ;
stepStart = v ;
}
reduce(x, varAlloc, stepStart, pMod.getSubPath(), endNode) ;
return ;
}
}
// This is the rewrite of
// "x {N,} y" to "x :p{N} ?V . ?V :p* y"
// "x {N,M} y" to "x :p{N} ?V . ?V {0,M} y"
if ( pMod.getMin() > 0 )
{
Path p1 = PathFactory.pathFixedLength(pMod.getSubPath(), pMod.getMin()) ;
Path p2 ;
if ( pMod.getMax() < 0 )
p2 = PathFactory.pathZeroOrMore(pMod.getSubPath()) ;
else
{
long len2 = pMod.getMax()-pMod.getMin() ;
if ( len2 < 0 ) len2 = 0 ;
p2 = PathFactory.pathMod(pMod.getSubPath(),0, len2) ;
}
Node v = varAlloc.allocVar() ;
// Start at the fixed end.
if ( ! startNode.isVariable() || endNode.isVariable() )
{
reduce(x, varAlloc, startNode, p1, v) ;
reduce(x, varAlloc, v, p2, endNode) ;
}
else
{
// endNode fixed, start node not.
reduce(x, varAlloc, v, p2, endNode) ;
reduce(x, varAlloc, startNode, p1, v) ;
}
return ;
}
// Else drop through
}
// Nothing can be done.
x.add(new TriplePath(startNode, path, endNode)) ;
}