package org.basex.query.ft; import static org.basex.query.QueryText.*; import org.basex.data.FTMatch; import org.basex.data.FTMatches; import org.basex.data.FTStringMatch; 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.Scoring; /** * FTUnaryNot expression. * * @author BaseX Team 2005-12, BSD License * @author Christian Gruen * @author Sebastian Gath */ public final class FTNot extends FTExpr { /** * Constructor. * @param ii input info * @param e expression */ public FTNot(final InputInfo ii, final FTExpr e) { super(ii, e); } @Override public FTExpr comp(final QueryContext ctx) throws QueryException { super.comp(ctx); return expr[0] instanceof FTNot ? expr[0].expr[0] : this; } @Override public FTNode item(final QueryContext ctx, final InputInfo ii) throws QueryException { return not(expr[0].item(ctx, input)); } @Override public FTIter iter(final QueryContext ctx) throws QueryException { return new FTIter() { final FTIter ir = expr[0].iter(ctx); @Override public FTNode next() throws QueryException { return not(ir.next()); } }; } /** * Negates a hit. * @param item item * @return specified item */ static FTNode not(final FTNode item) { if(item != null) { item.all = not(item.all); item.score(Scoring.not(item.score())); } return item; } /** * Negates the specified matches. * @param m match * @return resulting matches */ static FTMatches not(final FTMatches m) { return not(m, 0); } /** * Negates the specified matches. * @param m match * @param i position to start from * @return resulting match */ private static FTMatches not(final FTMatches m, final int i) { final FTMatches all = new FTMatches(m.sTokenNum); if(i == m.size) { all.add(new FTMatch()); } else { for(final FTStringMatch s : m.match[i]) { s.ex ^= true; for(final FTMatch tmp : not(m, i + 1)) { all.add(new FTMatch().add(s).add(tmp)); } } } return all; } @Override public boolean indexAccessible(final IndexContext ic) throws QueryException { final boolean ia = expr[0].indexAccessible(ic); ic.not ^= true; return ia; } @Override public boolean usesExclude() { return true; } @Override public String toString() { return FTNOT + ' ' + expr[0]; } }