<commit_before>package org.basex.query.xpath.expr;

import org.basex.query.QueryException;
import org.basex.query.xpath.XPContext;
import org.basex.query.xpath.XPOptimizer;
import org.basex.query.xpath.internal.FTIndex;
import org.basex.query.xpath.locpath.LocPath;
import org.basex.query.xpath.locpath.LocPathRel;
import org.basex.query.xpath.locpath.Step;
import org.basex.query.xpath.locpath.TestNode;
import org.basex.query.xpath.values.Bool;
import org.basex.query.xpath.values.Comp;
import org.basex.query.xpath.values.Literal;
import org.basex.query.xpath.values.NodeSet;
import org.basex.util.Token;
import static org.basex.query.xpath.XPText.*;

/**
 * FTContains Expression; used for fulltext operations.
 * 
 * @author Workgroup DBIS, University of Konstanz 2005-08, ISC License
 * @author <NAME>
 */
public final class FTContains extends Comparison {
  /** FullText options. */
  private FTOption option;
  /** Flag for FTPosFilter queries.*/
  boolean ftpos = false;
 
  /**
   * Constructor.
   * @param e1 first expression
   * @param e2 second expression to compare with first
   */
  public FTContains(final Expr e1, final Expr e2) {
    super(e1, e2);
    type = Comp.FTCONTAINS;
  }
  
  /**
   * Constructor.
   * @param e1 first expression
   * @param e2 second expression to compare with first
   * @param opt fulltext options
   */
  public FTContains(final Expr e1, final Expr e2, final FTOption opt) {
    super(e1, e2);
    option = opt;
    type = Comp.FTCONTAINS;
  }

  /**
   * Constructor.
   * @param e1 first expression
   * @param e2 second expression to compare with first
   * @param opt fulltext options
   * @param ftposfilter flag to be set if query contains an ft pososition filter
   */
  public FTContains(final Expr e1, final Expr e2, final FTOption opt, 
      final boolean ftposfilter) {
    super(e1, e2);
    expr1 = e1;
    expr2 = e2;
    option = opt;
    type = Comp.FTCONTAINS;
    ftpos = ftposfilter;
  }

  
  @Override
  public Expr compile(final XPContext ctx) throws QueryException {
    if (expr2 instanceof Literal && expr1 instanceof Literal) {
      final byte[] lit = ((Literal)  expr2).str();

      ctx.compInfo(OPTFTINDEX);
      
//    <SG> to be change if ftnot is combined with further options like order...
      if (Token.indexOf(lit, ' ') > 0) {
        return new FTIndex(lit, option, false, false);
      }
        
      return new FTIndex(lit, option, false, true);
    }

    expr1 = expr1.compile(ctx);
    expr2 = expr2.compile(ctx);

    XPOptimizer.addText(expr1, ctx);
    XPOptimizer.addText(expr2, ctx);

   return this;
  }

  @Override
  public Bool eval(final XPContext ctx) throws QueryException {
    
    if(expr1 instanceof LocPath && expr2 instanceof FTUnaryNot) {
      final NodeSet ns = ctx.local;
      ctx.local = (NodeSet) expr1.eval(ctx); 
    
      Bool bool = Bool.get(expr2.eval(ctx).bool());
      ctx.local = ns;
      return bool;

      /*
      FTIndex f = (FTIndex) ((FTUnaryNot) expr2).exprs[0];
      NodeSet n = f.eval(ctx);
      // evaluate location path to get resulting nodes
      ctx.local = (NodeSet) ctx.eval(expr1);

      // check if index is fulltext index exists
      final Data data = ctx.local.data;
      if(data.meta.ftxindex) {
        if(ctx.local.ftids == null) {
          ctx.local.ftids = Array.extractIDsFromData(data.ftIDs(l, f.option));
        }
        return Bool.get(expr2.eval(ctx).bool());
      }
      */
    }
   
    // use conventional check for other cases..
    
    return super.eval(ctx);
  }

  @Override
  public Expr indexEquivalent(final XPContext ctx, final Step curr)
    throws QueryException {
    LocPath path = (LocPath) expr1;;
    
    
    return new Path(expr2.indexEquivalent(ctx, curr), path.invertPath(curr));
    
    /*
    // simple ftcontains invert path for index access
    if (expr1 instanceof LocPath && expr2 instanceof Literal) {
      path = (LocPath) expr1;
      final byte[] lit = ((Literal)  expr2).str();
<commit_msg>Bugfix<commit_after>package org.basex.query.xpath.expr;

import org.basex.query.QueryException;
import org.basex.query.xpath.XPContext;
import org.basex.query.xpath.XPOptimizer;
import org.basex.query.xpath.internal.FTIndex;
import org.basex.query.xpath.locpath.LocPath;
import org.basex.query.xpath.locpath.LocPathRel;
import org.basex.query.xpath.locpath.Step;
import org.basex.query.xpath.locpath.TestNode;
import org.basex.query.xpath.values.Bool;
import org.basex.query.xpath.values.Comp;
import org.basex.query.xpath.values.Literal;
import org.basex.query.xpath.values.NodeSet;
import org.basex.util.Token;
import static org.basex.query.xpath.XPText.*;

/**
 * FTContains Expression; used for fulltext operations.
 * 
 * @author Workgroup DBIS, University of Konstanz 2005-08, ISC License
 * @author <NAME>
 */
public final class FTContains extends Comparison {
  /** FullText options. */
  private FTOption option;
  /** Flag for FTPosFilter queries.*/
  boolean ftpos = false;
 
  /**
   * Constructor.
   * @param e1 first expression
   * @param e2 second expression to compare with first
   */
  public FTContains(final Expr e1, final Expr e2) {
    super(e1, e2);
    type = Comp.FTCONTAINS;
  }
  
  /**
   * Constructor.
   * @param e1 first expression
   * @param e2 second expression to compare with first
   * @param opt fulltext options
   */
  public FTContains(final Expr e1, final Expr e2, final FTOption opt) {
    super(e1, e2);
    option = opt;
    type = Comp.FTCONTAINS;
  }

  /**
   * Constructor.
   * @param e1 first expression
   * @param e2 second expression to compare with first
   * @param opt fulltext options
   * @param ftposfilter flag to be set if query contains an ft pososition filter
   */
  public FTContains(final Expr e1, final Expr e2, final FTOption opt, 
      final boolean ftposfilter) {
    super(e1, e2);
    expr1 = e1;
    expr2 = e2;
    option = opt;
    type = Comp.FTCONTAINS;
    ftpos = ftposfilter;
  }

  
  @Override
  public Expr compile(final XPContext ctx) throws QueryException {
    if (!ctx.local.data.meta.ftxindex) 
      throw new QueryException("Please create full-text index first.");

    if (expr2 instanceof Literal && expr1 instanceof Literal) {
      final byte[] lit = ((Literal)  expr2).str();
      
      
      ctx.compInfo(OPTFTINDEX);
      
//    <SG> to be change if ftnot is combined with further options like order...
      if (Token.indexOf(lit, ' ') > 0) {
        return new FTIndex(lit, option, false, false);
      }
        
      return new FTIndex(lit, option, false, true);
    }

    expr1 = expr1.compile(ctx);
    expr2 = expr2.compile(ctx);

    XPOptimizer.addText(expr1, ctx);
    XPOptimizer.addText(expr2, ctx);

   return this;
  }

  @Override
  public Bool eval(final XPContext ctx) throws QueryException {
    
    if(expr1 instanceof LocPath && expr2 instanceof FTUnaryNot) {
      final NodeSet ns = ctx.local;
      ctx.local = (NodeSet) expr1.eval(ctx); 
    
      Bool bool = Bool.get(expr2.eval(ctx).bool());
      ctx.local = ns;
      return bool;

      /*
      FTIndex f = (FTIndex) ((FTUnaryNot) expr2).exprs[0];
      NodeSet n = f.eval(ctx);
      // evaluate location path to get resulting nodes
      ctx.local = (NodeSet) ctx.eval(expr1);

      // check if index is fulltext index exists
      final Data data = ctx.local.data;
      if(data.meta.ftxindex) {
        if(ctx.local.ftids == null) {
          ctx.local.ftids = Array.extractIDsFromData(data.ftIDs(l, f.option));
        }
        return Bool.get(expr2.eval(ctx).bool());
      }
      */
    }
   
    // use conventional check for other cases..
    
    return super.eval(ctx);
  }

  @Override
  public Expr indexEquivalent(final XPContext ctx, final Step curr)
    throws QueryException {
    
    LocPath path = (LocPath) expr1;;
    
    
    return new Path(expr2.indexEquivalent(ctx, curr), path.invertPath(curr));
    
    /*
    // simple ftcontains invert path for index access
    if (expr1 instanceof LocPath && expr2 instanceof Literal) {
      path = (LocPath) expr1;
      final byte[] lit = ((Literal)  expr2).str();

{'fraction_non_alphanumeric': 0.1119035907525824, 'fraction_numerical': 0.01278898180029513, 'mean_word_length': 2.804022450888681, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5387510', 'n_tokens_mistral': 2711, 'n_tokens_neox': 2648, 'n_words': 713}