package org.basex.query.ft; 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.QueryText; 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; /** * FTWindow expression. * * @author BaseX Team 2005-12, BSD License * @author Christian Gruen */ public final class FTWindow extends FTFilter { /** Window. */ private Expr win; /** * Constructor. * @param ii input info * @param e expression * @param w window * @param u unit */ public FTWindow(final InputInfo ii, final FTExpr e, final Expr w, final FTUnit u) { super(ii, e); win = w; unit = u; } @Override public FTExpr comp(final QueryContext ctx) throws QueryException { win = checkUp(win, ctx).comp(ctx); return super.comp(ctx); } @Override protected boolean filter(final QueryContext ctx, final FTMatch mtc, final FTLexer lex) throws QueryException { final int n = (int) checkItr(win, ctx) - 1; mtc.sort(); FTStringMatch f = null; for(final FTStringMatch m : mtc) { if(m.ex) continue; if(f == null) f = m; f.g |= m.e - f.e > 1; f.e = m.e; if(pos(f.e, lex) - pos(f.s, lex) > n) return false; } if(f == null) return false; final int w = n - pos(f.e, lex) + pos(f.s, lex); for(int s = pos(f.s, lex) - w; s <= pos(f.s, lex); ++s) { boolean h = false; for(final FTStringMatch m : mtc) { h = m.ex && pos(m.s, lex) >= s && pos(m.e, lex) <= s + w; if(h) break; } if(!h) { mtc.reset(); mtc.add(f); return true; } } return false; } @Override public boolean uses(final Use u) { return win.uses(u) || super.uses(u); } @Override public int count(final Var v) { return win.count(v) + super.count(v); } @Override public boolean removable(final Var v) { return win.removable(v) && super.removable(v); } @Override public FTExpr remove(final Var v) { win = win.remove(v); return super.remove(v); } @Override public void plan(final Serializer ser) throws IOException { ser.openElement(this, token(QueryText.WINDOW), token(unit.toString())); win.plan(ser); super.plan(ser); } @Override public String toString() { return super.toString() + QueryText.WINDOW + ' ' + win + ' ' + unit; } }