<commit_before>package org.basex.query;

import static org.basex.core.Text.*;
import static org.basex.query.QueryError.*;
import static org.basex.util.Token.*;

import java.io.*;
import java.util.*;
import java.util.Map.*;

import org.basex.build.json.*;
import org.basex.build.json.JsonOptions.*;
import org.basex.core.*;
import org.basex.core.MainOptions.MainParser;
import org.basex.core.jobs.*;
import org.basex.core.locks.*;
import org.basex.core.users.*;
import org.basex.data.*;
import org.basex.io.parse.json.*;
import org.basex.io.serial.*;
import org.basex.query.func.*;
import org.basex.query.iter.*;
import org.basex.query.scope.*;
import org.basex.query.up.*;
import org.basex.query.util.*;
import org.basex.query.util.collation.*;
import org.basex.query.util.ft.*;
import org.basex.query.util.list.*;
import org.basex.query.value.*;
import org.basex.query.value.item.*;
import org.basex.query.value.node.*;
import org.basex.query.value.seq.*;
import org.basex.query.value.type.*;
import org.basex.query.var.*;
import org.basex.util.*;
import org.basex.util.ft.*;
import org.basex.util.hash.*;
import org.basex.util.list.*;

/**
 * This class organizes both static and dynamic properties that are specific to a
 * single query.
 *
 * @author BaseX Team 2005-18, BSD License
 * @author <NAME>
 */
public final class QueryContext extends Job implements Closeable {
  /** The evaluation stack. */
  public final QueryStack stack = new QueryStack();
  /** Static variables. */
  public final Variables vars = new Variables();
  /** Functions. */
  public final StaticFuncs funcs = new StaticFuncs();
  /** Externally bound variables. */
  private final HashMap<QNm, Value> bindings = new HashMap<>();
  /** External query properties. */
  private final HashMap<String, Object> props;

  /** Parent query context. */
  public final QueryContext parent;
  /** Query info. */
  public final QueryInfo info;
  /** Database context. */
  public final Context context;

  /** Query resources. */
  public QueryResources resources;
  /** Update container. */
  public Updates updates;

  /** Global database options (will be reassigned after query execution). */
  QueryOptions options = new QueryOptions(this);

  /** Current context value. */
  public QueryFocus focus = new QueryFocus();
  /** Current date/time values. */
  public QueryDateTime dateTime;

  /** Full-text position data (needed for highlighting full-text results). */
  public FTPosData ftPosData = Prop.gui ? new FTPosData() : null;
  /** Current full-text lexer. */
  public FTLexer ftLexer;
  /** Current full-text options. */
  private FTOpt ftOpt;
  /** Full-text token positions (needed for highlighting full-text results). */
  public int ftPos;
  /** Scoring flag. */
  public boolean scoring;

  /** Available collations. */
  public TokenObjMap<Collation> collations;

  /** Strings to lock defined by read-lock option. */
  public final LockList readLocks = new LockList();
  /** Strings to lock defined by write-lock option. */
  public final LockList writeLocks = new LockList();

  /** Number of successive tail calls. */
  public int tailCalls;
  /** Maximum number of successive tail calls (will be set before compilation). */
  public int maxCalls;

  /** Function for the next tail call. */
  private XQFunction tailFunc;
  /** Arguments for the next tail call. */
  private Value[] args;
  /** Counter for variable IDs. */
  public int varIDs;

  /** Parsed modules, containing the file path and module uri. */
  public final TokenMap modParsed = new TokenMap();
  /** Pre-declared modules, containing module uri and their file paths (required for test APIs). */
  final TokenMap modDeclared = new TokenMap();
  /** Stack of module files that are currently parsed. */
  final TokenList modStack = new TokenList();

  /** Initial context value. */
  public MainModule ctxItem;
  /** Root expression of the query. */
  public MainModule root;

  /** Serialization parameters. */
  private SerializerOptions serParams;
  /** Indicates if the default serialization parameters are used. */
  private boolean defaultOutput;

  /** Indicates if the query has been compiled. */
  private boolean compiled;
  /** Indicates if the query context has been closed. */
  private boolean closed;

  /**
   * Constructor.
   * @param parent parent context
   */
  public QueryContext(final QueryContext parent) {
    this(parent.context, parent, parent.info, parent.props);
    parent.pushJob(this);
    resources = parent.resources;
    updates = parent.updates;
  }

  /**
   * Constructor.
   * @param context database context
   */
  public QueryContext(final Context context) {
    this(context, null, null, new HashMap<>());
    resources = new QueryResources(this);
  }

  /**
   * Constructor.
   * @param context database context
   * @param parent parent context (can be {@code null})
   * @param info query info
   * @param props external properties
   */
  private QueryContext(final Context context, final QueryContext parent, final QueryInfo info,
      final HashMap<String, Object> props) {
    this.context = context;
    this.parent = parent;
    this.info = info != null ? info : new QueryInfo(this);
    this.props = props;
  }

  /**
   * Parses the specified query.
   * @param query query string
   * @param uri base URI (may be {@code null})
   * @return main module
   * @throws QueryException query exception
   */
  public Module parse(final String query, final String uri) throws QueryException {
    return parse(query, QueryProcessor.isLibrary(query), uri);
  }

  /**
   * Parses the specified query.
   * @param query query string
   * @param library library/main module
   * @param uri base URI (may be {@code null})
   * @return main module
   * @throws QueryException query exception
   */
  public Module parse(final String query, final boolean library, final String uri)
      throws QueryException {
    return library ? parseLibrary(query, uri) : parseMain(query, uri);
  }

  /**
   * Parses the specified query.
   * @param query query string
   * @param uri base URI (may be {@code null})
   * @return main module
   * @throws QueryException query exception
   */
  public MainModule parseMain(final String query, final String uri) throws QueryException {
    return parseMain(query, uri, null);
  }

  /**
   * Parses the specified query.
   * @param query query string
   * @param uri base URI (may be {@code null})
   * @param sc static context (may be {@code null})
   * @return main module
   * @throws QueryException query exception
   */
  public MainModule parseMain(final String query, final String uri, final StaticContext sc)
      throws QueryException {

    info.query = query;
    final QueryParser qp = new QueryParser(query, uri, this, sc);
    root = qp.parseMain();
    // updating expression: check if an updating expression is left in the expression tree
    if(updating) updating = (qp.sc.mixUpdates && qp.sc.dynFuncCall) || root.expr.has(Flag.UPD);
    return root;
  }

  /**
   * Parses the specified module.
   * @param query query string
   * @param uri base URI (may be {@code null})
   * @return name of module
   * @throws QueryException query exception
   */
  public LibraryModule parseLibrary(final String query, final String uri) throws QueryException {
    info.query = query;
    try {
      return new QueryParser(query, uri, this, null).parseLibrary(true);
    } finally {
      // library module itself is not updating
      updating = false;
    }
  }

  /**
   * Sets the main module (root expression).
   * @param rt main module
   */
  public void mainModule(final MainModule rt) {
    root = rt;
    updating = rt.expr.has(Flag.UPD);
  }

  /**
   * Compiles and optimizes the expression.
   * @throws QueryException query exception
   */
  public void compile() throws QueryException {
    checkStop();
    if(compiled) return;
    info.runtime = false;

    final CompileContext cc = new CompileContext(this);
    try {
      // bind external variables of global option (if not assigned yet by other APIs)
      final MainOptions mopts = context.options;
      if(root != null && parent == null) {
        for(final Entry<String, String> entry : mopts.toMap(MainOptions.BINDINGS).entrySet()) {
          final String key = entry.getKey();
          final Atm value = new Atm(entry.getValue());
          if(key.isEmpty()) {
            if(ctxItem != null) context(value, root.sc);
          } else {
            final QNm name = qname(key, root.sc);
            if(!bindings.containsKey(name)) bind(name, value);
          }
        }
      }

      // set database options
      options.compile();
      // set tail call option after assigning database options
      maxCalls = mopts.get(MainOptions.TAILCALLS);

      // bind external variables
      vars.bindExternal(this, bindings);

      if(ctxItem != null) {
        // evaluate initial expression
        try {
          ctxItem.comp(cc);
          focus.value = ctxItem.cache(this).value();
        } catch(final QueryException ex) {
          // only {@link ParseExpr} instances may lead to a missing context
          throw ex.error() == NOCTX_X ? CIRCCTX.get(ctxItem.info) : ex;
        }
      } else {
        // cache the initial context nodes
        final DBNodes nodes = context.current();<commit_msg>[FIX] XQuery, BINDINGS, set context item<commit_after>package org.basex.query;

import static org.basex.core.Text.*;
import static org.basex.query.QueryError.*;
import static org.basex.util.Token.*;

import java.io.*;
import java.util.*;
import java.util.Map.*;

import org.basex.build.json.*;
import org.basex.build.json.JsonOptions.*;
import org.basex.core.*;
import org.basex.core.MainOptions.MainParser;
import org.basex.core.jobs.*;
import org.basex.core.locks.*;
import org.basex.core.users.*;
import org.basex.data.*;
import org.basex.io.parse.json.*;
import org.basex.io.serial.*;
import org.basex.query.func.*;
import org.basex.query.iter.*;
import org.basex.query.scope.*;
import org.basex.query.up.*;
import org.basex.query.util.*;
import org.basex.query.util.collation.*;
import org.basex.query.util.ft.*;
import org.basex.query.util.list.*;
import org.basex.query.value.*;
import org.basex.query.value.item.*;
import org.basex.query.value.node.*;
import org.basex.query.value.seq.*;
import org.basex.query.value.type.*;
import org.basex.query.var.*;
import org.basex.util.*;
import org.basex.util.ft.*;
import org.basex.util.hash.*;
import org.basex.util.list.*;

/**
 * This class organizes both static and dynamic properties that are specific to a
 * single query.
 *
 * @author BaseX Team 2005-18, BSD License
 * @author <NAME>
 */
public final class QueryContext extends Job implements Closeable {
  /** The evaluation stack. */
  public final QueryStack stack = new QueryStack();
  /** Static variables. */
  public final Variables vars = new Variables();
  /** Functions. */
  public final StaticFuncs funcs = new StaticFuncs();
  /** Externally bound variables. */
  private final HashMap<QNm, Value> bindings = new HashMap<>();
  /** External query properties. */
  private final HashMap<String, Object> props;

  /** Parent query context. */
  public final QueryContext parent;
  /** Query info. */
  public final QueryInfo info;
  /** Database context. */
  public final Context context;

  /** Query resources. */
  public QueryResources resources;
  /** Update container. */
  public Updates updates;

  /** Global database options (will be reassigned after query execution). */
  QueryOptions options = new QueryOptions(this);

  /** Current context value. */
  public QueryFocus focus = new QueryFocus();
  /** Current date/time values. */
  public QueryDateTime dateTime;

  /** Full-text position data (needed for highlighting full-text results). */
  public FTPosData ftPosData = Prop.gui ? new FTPosData() : null;
  /** Current full-text lexer. */
  public FTLexer ftLexer;
  /** Current full-text options. */
  private FTOpt ftOpt;
  /** Full-text token positions (needed for highlighting full-text results). */
  public int ftPos;
  /** Scoring flag. */
  public boolean scoring;

  /** Available collations. */
  public TokenObjMap<Collation> collations;

  /** Strings to lock defined by read-lock option. */
  public final LockList readLocks = new LockList();
  /** Strings to lock defined by write-lock option. */
  public final LockList writeLocks = new LockList();

  /** Number of successive tail calls. */
  public int tailCalls;
  /** Maximum number of successive tail calls (will be set before compilation). */
  public int maxCalls;

  /** Function for the next tail call. */
  private XQFunction tailFunc;
  /** Arguments for the next tail call. */
  private Value[] args;
  /** Counter for variable IDs. */
  public int varIDs;

  /** Parsed modules, containing the file path and module uri. */
  public final TokenMap modParsed = new TokenMap();
  /** Pre-declared modules, containing module uri and their file paths (required for test APIs). */
  final TokenMap modDeclared = new TokenMap();
  /** Stack of module files that are currently parsed. */
  final TokenList modStack = new TokenList();

  /** Initial context value. */
  public MainModule ctxItem;
  /** Root expression of the query. */
  public MainModule root;

  /** Serialization parameters. */
  private SerializerOptions serParams;
  /** Indicates if the default serialization parameters are used. */
  private boolean defaultOutput;

  /** Indicates if the query has been compiled. */
  private boolean compiled;
  /** Indicates if the query context has been closed. */
  private boolean closed;

  /**
   * Constructor.
   * @param parent parent context
   */
  public QueryContext(final QueryContext parent) {
    this(parent.context, parent, parent.info, parent.props);
    parent.pushJob(this);
    resources = parent.resources;
    updates = parent.updates;
  }

  /**
   * Constructor.
   * @param context database context
   */
  public QueryContext(final Context context) {
    this(context, null, null, new HashMap<>());
    resources = new QueryResources(this);
  }

  /**
   * Constructor.
   * @param context database context
   * @param parent parent context (can be {@code null})
   * @param info query info
   * @param props external properties
   */
  private QueryContext(final Context context, final QueryContext parent, final QueryInfo info,
      final HashMap<String, Object> props) {
    this.context = context;
    this.parent = parent;
    this.info = info != null ? info : new QueryInfo(this);
    this.props = props;
  }

  /**
   * Parses the specified query.
   * @param query query string
   * @param uri base URI (may be {@code null})
   * @return main module
   * @throws QueryException query exception
   */
  public Module parse(final String query, final String uri) throws QueryException {
    return parse(query, QueryProcessor.isLibrary(query), uri);
  }

  /**
   * Parses the specified query.
   * @param query query string
   * @param library library/main module
   * @param uri base URI (may be {@code null})
   * @return main module
   * @throws QueryException query exception
   */
  public Module parse(final String query, final boolean library, final String uri)
      throws QueryException {
    return library ? parseLibrary(query, uri) : parseMain(query, uri);
  }

  /**
   * Parses the specified query.
   * @param query query string
   * @param uri base URI (may be {@code null})
   * @return main module
   * @throws QueryException query exception
   */
  public MainModule parseMain(final String query, final String uri) throws QueryException {
    return parseMain(query, uri, null);
  }

  /**
   * Parses the specified query.
   * @param query query string
   * @param uri base URI (may be {@code null})
   * @param sc static context (may be {@code null})
   * @return main module
   * @throws QueryException query exception
   */
  public MainModule parseMain(final String query, final String uri, final StaticContext sc)
      throws QueryException {

    info.query = query;
    final QueryParser qp = new QueryParser(query, uri, this, sc);
    root = qp.parseMain();
    // updating expression: check if an updating expression is left in the expression tree
    if(updating) updating = (qp.sc.mixUpdates && qp.sc.dynFuncCall) || root.expr.has(Flag.UPD);
    return root;
  }

  /**
   * Parses the specified module.
   * @param query query string
   * @param uri base URI (may be {@code null})
   * @return name of module
   * @throws QueryException query exception
   */
  public LibraryModule parseLibrary(final String query, final String uri) throws QueryException {
    info.query = query;
    try {
      return new QueryParser(query, uri, this, null).parseLibrary(true);
    } finally {
      // library module itself is not updating
      updating = false;
    }
  }

  /**
   * Sets the main module (root expression).
   * @param rt main module
   */
  public void mainModule(final MainModule rt) {
    root = rt;
    updating = rt.expr.has(Flag.UPD);
  }

  /**
   * Compiles and optimizes the expression.
   * @throws QueryException query exception
   */
  public void compile() throws QueryException {
    checkStop();
    if(compiled) return;
    info.runtime = false;

    final CompileContext cc = new CompileContext(this);
    try {
      // bind external variables of global option (if not assigned yet by other APIs)
      final MainOptions mopts = context.options;
      if(root != null && parent == null) {
        for(final Entry<String, String> entry : mopts.toMap(MainOptions.BINDINGS).entrySet()) {
          final String key = entry.getKey();
          final Atm value = new Atm(entry.getValue());
          if(key.isEmpty()) {
            if(ctxItem == null) context(value, root.sc);
          } else {
            final QNm name = qname(key, root.sc);
            if(!bindings.containsKey(name)) bind(name, value);
          }
        }
      }

      // set database options
      options.compile();
      // set tail call option after assigning database options
      maxCalls = mopts.get(MainOptions.TAILCALLS);

      // bind external variables
      vars.bindExternal(this, bindings);

      if(ctxItem != null) {
        // evaluate initial expression
        try {
          ctxItem.comp(cc);
          focus.value = ctxItem.cache(this).value();
        } catch(final QueryException ex) {
          // only {@link ParseExpr} instances may lead to a missing context
          throw ex.error() == NOCTX_X ? CIRCCTX.get(ctxItem.info) : ex;
        }
      } else {
        // cache the initial context nodes
        final DBNodes nodes = context.current();
{'fraction_non_alphanumeric': 0.11480233242390199, 'fraction_numerical': 0.0006419515326592842, 'mean_word_length': 3.062146892655367, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 19, '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': '2139799', 'n_tokens_mistral': 5311, 'n_tokens_neox': 5197, 'n_words': 1802}