package org.basex.query.ft;
import static org.basex.query.util.Err.*;
import static org.basex.query.QueryText.*;
import org.basex.data.FTMatch;
import org.basex.data.FTMatches;
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;
/**
* FTMildnot expression.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
public final class FTMildNot extends FTExpr {
/**
* Constructor.
* @param ii input info
* @param e1 first expression
* @param e2 second expression
* @throws QueryException query exception
*/
public FTMildNot(final InputInfo ii, final FTExpr e1, final FTExpr e2)
throws QueryException {
super(ii, e1, e2);
if(usesExclude()) FTMILD.thrw(input);
}
@Override
public FTNode item(final QueryContext ctx, final InputInfo ii)
throws QueryException {
return mildnot(expr[0].item(ctx, input), expr[1].item(ctx, input));
}
@Override
public FTIter iter(final QueryContext ctx) throws QueryException {
return new FTIter() {
final FTIter i1 = expr[0].iter(ctx);
final FTIter i2 = expr[1].iter(ctx);
FTNode it1 = i1.next();
FTNode it2 = i2.next();
@Override
public FTNode next() throws QueryException {
while(it1 != null && it2 != null) {
final int d = it1.pre - it2.pre;
if(d < 0) break;
if(d > 0) {
it2 = i2.next();
} else {
if(mildnot(it1, it2).all.size != 0) break;
it1 = i1.next();
}
}
final FTNode it = it1;
it1 = i1.next();
return it;
}
};
}
/**
* Processes a hit.
* @param it1 first item
* @param it2 second item
* @return specified item
*/
static FTNode mildnot(final FTNode it1, final FTNode it2) {
it1.all = mildnot(it1.all, it2.all);
return it1;
}
/**
* Performs a mild not operation.
* @param m1 first match list
* @param m2 second match list
* @return resulting match
*/
private static FTMatches mildnot(final FTMatches m1, final FTMatches m2) {
final FTMatches all = new FTMatches(m1.sTokenNum);
for(final FTMatch s1 : m1) {
boolean n = true;
for(final FTMatch s2 : m2) n &= s1.notin(s2);
if(n) all.add(s1);
}
return all;
}
@Override
public boolean indexAccessible(final IndexContext ic) throws QueryException {
int is = ic.costs();
for(final FTExpr e : expr) {
if(!e.indexAccessible(ic)) return false;
is = Math.min(Integer.MIN_VALUE, is + ic.costs());
}
ic.costs(is);
return true;
}
@Override
public String toString() {
return toString(' ' + NOT + ' ' + IN + ' ');
}
}