package org.basex.query.ft;
import static org.basex.query.QueryText.*;
import static org.basex.util.Token.*;
import java.io.IOException;
import org.basex.data.FTMatch;
import org.basex.data.FTStringMatch;
import org.basex.io.serial.Serializer;
import org.basex.query.QueryContext;
import org.basex.query.QueryException;
import org.basex.query.expr.Expr;
import org.basex.query.util.Var;
import org.basex.util.InputInfo;
import org.basex.util.ft.FTLexer;
import org.basex.util.ft.FTUnit;
/**
* FTDistance expression.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
public final class FTDistance extends FTFilter {
/** Distance. */
private final Expr[] dist;
/**
* Constructor.
* @param ii input info
* @param e expression
* @param d distances
* @param u unit
*/
public FTDistance(final InputInfo ii, final FTExpr e, final Expr[] d,
final FTUnit u) {
super(ii, e);
dist = d;
unit = u;
}
@Override
public FTExpr comp(final QueryContext ctx) throws QueryException {
for(int d = 0; d != dist.length; ++d) dist[d] = dist[d].comp(ctx);
return super.comp(ctx);
}
@Override
protected boolean filter(final QueryContext ctx, final FTMatch mtc,
final FTLexer lex) throws QueryException {
final long min = checkItr(dist[0], ctx);
final long max = checkItr(dist[1], ctx);
mtc.sort();
final FTMatch match = new FTMatch();
FTStringMatch sm = null;
FTStringMatch f = null;
for(final FTStringMatch m : mtc) {
if(m.ex) {
match.add(m);
} else {
if(sm != null) {
final int d = pos(m.s, lex) - pos(sm.e, lex) - 1;
if(d < min || d > max) return false;
} else {
f = m;
}
sm = m;
}
}
f.e = sm.e;
mtc.reset();
mtc.add(f);
mtc.add(match);
return true;
}
@Override
public boolean uses(final Use u) {
for(final Expr d : dist) if(d.uses(u)) return true;
return super.uses(u);
}
@Override
public int count(final Var v) {
int c = 0;
for(final Expr d : dist) c += d.count(v);
return c + super.count(v);
}
@Override
public boolean removable(final Var v) {
for(final Expr d : dist) if(!d.removable(v)) return false;
return super.removable(v);
}
@Override
public FTExpr remove(final Var v) {
for(int d = 0; d != dist.length; ++d) dist[d] = dist[d].remove(v);
return super.remove(v);
}
@Override
public void plan(final Serializer ser) throws IOException {
ser.openElement(this, token(DISTANCE),
token(dist[0] + "-" + dist[1] + ' ' + unit));
super.plan(ser);
}
@Override
public String toString() {
return super.toString() + DISTANCE + PAR1 +
dist[0] + '-' + dist[1] + ' ' + unit + PAR2;
}
}