/** * The constructor is protected, to ensure that instances can only be created using the * compileQuery() methods of StaticQueryContext * * @param exp an expression to be wrapped as an XQueryExpression * @param exec the executable * @param mainModule the static context of the main module * @param config the configuration * @throws XPathException if an error occurs */ protected XQueryExpression( Expression exp, Executable exec, QueryModule mainModule, Configuration config) throws XPathException { stackFrameMap = config.makeSlotManager(); executable = exec; exp.setContainer(this); try { ExpressionVisitor visitor = ExpressionVisitor.make(mainModule); visitor.setExecutable(exec); exp = visitor.simplify(exp); exp.checkForUpdatingSubexpressions(); exp = visitor.typeCheck(exp, mainModule.getUserQueryContext().getRequiredContextItemType()); // ExpressionPresenter presenter = new ExpressionPresenter(config, // ExpressionPresenter.defaultDestination(config, new // FileOutputStream("c:/projects/montreal/before50.xml"))); // exp.explain(presenter); // presenter.close(); exp = exp.optimize(visitor, Type.ITEM_TYPE); } catch (XPathException err) { // err.printStackTrace(); mainModule.reportFatalError(err); throw err; } ExpressionTool.allocateSlots(exp, 0, stackFrameMap); expression = exp; executable.setConfiguration(config); executable.setDefaultCollationName(mainModule.getDefaultCollationName()); executable.setCollationTable(mainModule.getUserQueryContext().getAllCollations()); staticContext = mainModule; isUpdating = exp.isUpdatingExpression(); }
/** * Diagnostic method: display a representation of the compiled query on the selected output * stream. * * @param out an ExpressionPresenter to which the XML representation of the compiled query will be * sent */ public void explain(ExpressionPresenter out) { out.startElement("query"); staticContext.getExecutable().getKeyManager().explainKeys(out); staticContext.getExecutable().explainGlobalVariables(out); staticContext.explainGlobalFunctions(out); out.startElement("body"); expression.explain(out); out.endElement(); out.endElement(); out.close(); }
/** * Run an updating query, writing back eligible updated node to persistent storage. * * <p>A node is eligible to be written back to disk if it is present in the document pool, which * generally means that it was originally read using the doc() or collection() function. * * <p>On completion of this method it is generally unsafe to rely on the contents or relationships * of NodeInfo objects that were obtained before the updating query was run. Such objects may or * may not reflect the results of the update operations. This is especially true in the case of * nodes that are part of a subtree that has been deleted (detached from its parent). Instead, the * new updated tree should be accessed by navigation from the root nodes returned by this method. * * <p>If one or more eligible updated nodes cannot be written back to disk, perhaps because the * URI identifies a non-updatable location, then an exception is thrown. In this case it is * undefined * * @param dynamicEnv the dynamic context for query execution * @throws XPathException if evaluation of the update query fails, or it this is not an updating * query */ public void runUpdate(DynamicQueryContext dynamicEnv, UpdateAgent agent) throws XPathException { if (!isUpdating) { throw new XPathException("Calling runUpdate() on a non-updating query"); } Configuration config = executable.getConfiguration(); Controller controller = newController(); initializeController(dynamicEnv, controller); XPathContextMajor context = initialContext(dynamicEnv, controller); try { PendingUpdateList pul = config.newPendingUpdateList(); context.openStackFrame(stackFrameMap); expression.evaluatePendingUpdates(context, pul); pul.apply(context, staticContext.getRevalidationMode()); for (Iterator iter = pul.getAffectedTrees().iterator(); iter.hasNext(); ) { NodeInfo node = (NodeInfo) iter.next(); agent.update(node, controller); } } catch (XPathException e) { if (!e.hasBeenReported()) { try { controller.getErrorListener().fatalError(e); } catch (TransformerException e2) { // ignore secondary error } } throw e; } }
/** * Get an iterator over the results of the expression. This returns results without any conversion * of the returned items to "native" Java classes. The iterator will deliver a sequence of Item * objects, each item being either a NodeInfo (representing a node) or an AtomicValue * (representing an atomic value). * * <p> * * <p>To get the results of the query in the form of an XML document in which each item is wrapped * by an element indicating its type, use: * * <p> * * <p><code>QueryResult.wrap(iterator(env))</code> * * <p> * * <p>To serialize the results to a file, use the QueryResult.serialize() method. * * @param env Provides the dynamic query evaluation context * @return an iterator over the results of the query. The class SequenceIterator is modeled on the * standard Java Iterator class, but has extra functionality and can throw exceptions when * errors occur. * @throws XPathException if a dynamic error occurs in evaluating the query. Some dynamic errors * will not be reported by this method, but will only be reported when the individual items of * the result are accessed using the returned iterator. */ public SequenceIterator iterator(DynamicQueryContext env) throws XPathException { if (isUpdating) { throw new XPathException("Cannot call iterator() on an updating query"); } Controller controller = newController(); initializeController(env, controller); try { Item contextItem = env.getContextItem(); // Bindery bindery = controller.getBindery(); // bindery.openStackFrame(); controller.defineGlobalParameters(); XPathContextMajor context = controller.newXPathContext(); if (contextItem != null) { if (!staticContext .getUserQueryContext() .getRequiredContextItemType() .matchesItem(contextItem, false, env.getConfiguration())) { throw new XPathException( "The supplied context item does not match the required context item type"); } UnfailingIterator single = SingletonIterator.makeIterator(contextItem); single.next(); context.setCurrentIterator(single); controller.setInitialContextItem(contextItem); } // In tracing/debugging mode, evaluate all the global variables first if (controller.getTraceListener() != null) { controller.preEvaluateGlobals(context); } context.openStackFrame(stackFrameMap); SequenceIterator iterator = expression.iterate(context); return new ErrorReportingIterator(iterator, controller.getErrorListener()); } catch (XPathException err) { TransformerException terr = err; while (terr.getException() instanceof TransformerException) { terr = (TransformerException) terr.getException(); } XPathException de = XPathException.makeXPathException(terr); controller.reportFatalError(de); throw de; } }
private XPathContextMajor initialContext(DynamicQueryContext dynamicEnv, Controller controller) throws XPathException { Item contextItem = dynamicEnv.getContextItem(); controller.defineGlobalParameters(); XPathContextMajor context = controller.newXPathContext(); if (contextItem != null) { if (!staticContext .getUserQueryContext() .getRequiredContextItemType() .matchesItem(contextItem, false, dynamicEnv.getConfiguration())) { throw new XPathException( "The supplied context item does not match the required context item type"); } UnfailingIterator single = SingletonIterator.makeIterator(contextItem); single.next(); context.setCurrentIterator(single); controller.setInitialContextItem(contextItem); } return context; }