package org.basex.query.ft; import java.io.IOException; import org.basex.data.FTMatch; import org.basex.data.FTMatches; import org.basex.io.serial.Serializer; import org.basex.query.QueryContext; import org.basex.query.QueryException; import org.basex.query.item.FTNode; import org.basex.query.iter.FTIter; import org.basex.query.util.IndexContext; import org.basex.util.InputInfo; import org.basex.util.ft.FTLexer; import org.basex.util.ft.FTUnit; /** * Abstract FTFilter expression. * * @author BaseX Team 2005-12, BSD License * @author Christian Gruen */ public abstract class FTFilter extends FTExpr { /** Optional unit. */ FTUnit unit = FTUnit.WORD; /** * Constructor. * @param ii input info * @param e expression */ FTFilter(final InputInfo ii, final FTExpr e) { super(ii, e); } @Override public final FTNode item(final QueryContext ctx, final InputInfo ii) throws QueryException { final FTNode it = expr[0].item(ctx, input); filter(ctx, it, ctx.fttoken); return it; } @Override public final FTIter iter(final QueryContext ctx) throws QueryException { final FTIter ir = expr[0].iter(ctx); return new FTIter() { @Override public FTNode next() throws QueryException { FTNode it; while((it = ir.next()) != null) { if(filter(ctx, it, content() ? new FTLexer().init(it.string(input)) : null)) break; } return it; } }; } /** * Evaluates the position filters. * @param ctx query context * @param item input node * @param lex tokenizer * @return result of check * @throws QueryException query exception */ final boolean filter(final QueryContext ctx, final FTNode item, final FTLexer lex) throws QueryException { final FTMatches all = item.all; for(int a = 0; a < all.size; ++a) { if(!filter(ctx, all.match[a], lex)) all.delete(a--); } return all.size != 0; } /** * Evaluates the filter expression. * @param ctx query context * @param m full-text match * @param ft tokenizer * @return result of check * @throws QueryException query exception */ protected abstract boolean filter(final QueryContext ctx, final FTMatch m, final FTLexer ft) throws QueryException; /** * Checks if the filter requires the whole text node to be parsed. * Is overwritten by some filters to perform other checks. * @return result of check */ boolean content() { return unit != FTUnit.WORD; } /** * Calculates a position value, dependent on the specified unit. * @param p word position * @param ft tokenizer * @return new position */ final int pos(final int p, final FTLexer ft) { // ft can be zero if unit is WORD return unit == FTUnit.WORD ? p : ft.pos(p, unit); } @Override public final boolean indexAccessible(final IndexContext ic) throws QueryException { return expr[0].indexAccessible(ic); } @Override public void plan(final Serializer ser) throws IOException { expr[0].plan(ser); ser.closeElement(); } @Override public String toString() { return expr[0] + " "; } }