/** * 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(); }
/** * Get a controller that can be used to execute functions in this compiled query. Functions in the * query module can be found using {@link QueryModule#getUserDefinedFunction}. They can then be * called directly from the Java application using {@link * org.orbeon.saxon.instruct.UserFunction#call} The same Controller can be used for a series of * function calls. Note that the Controller should only be used in a single thread. * * @return a newly constructed Controller */ public Controller newController() { Controller controller = new Controller(executable.getConfiguration(), executable); executable.initializeBindery(controller.getBindery()); if (isUpdating && controller.getTreeModel() == Builder.TINY_TREE) { controller.setTreeModel(Builder.LINKED_TREE); } return controller; }
/** * 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; } }
/** * Run the query in pull mode. * * <p> * * <p>For maximum effect this method should be used when lazyConstructionMode has been set in the * Configuration. * * <p> * * <p><b>Note: this method usually has very similar performance to the {@link * #run(DynamicQueryContext,javax.xml.transform.Result,java.util.Properties)} method (which does * the same thing), but sometimes it is significantly slower. Therefore, the run() method is * preferred.</b> * * @param dynamicEnv the dynamic context for query evaluation * @param destination the destination of the query results * @param outputProperties the serialization parameters * @see Configuration#setLazyConstructionMode(boolean) */ public void pullOLD( DynamicQueryContext dynamicEnv, Result destination, Properties outputProperties) throws XPathException { try { SequenceIterator iter = iterator(dynamicEnv); PullProvider pull = new PullFromIterator(iter); pull = new PullNamespaceReducer(pull); final Configuration config = executable.getConfiguration(); pull.setPipelineConfiguration(config.makePipelineConfiguration()); SerializerFactory sf = config.getSerializerFactory(); Receiver receiver = sf.getReceiver(destination, pull.getPipelineConfiguration(), outputProperties); // NamespaceReducer reducer = new NamespaceReducer(); // PipelineConfiguration pipe = pull.getPipelineConfiguration(); // reducer.setPipelineConfiguration(pipe); // reducer.setUnderlyingReceiver(receiver); // ComplexContentOutputter outputter = new ComplexContentOutputter(); // outputter.setReceiver(reducer); // outputter.setPipelineConfiguration(pipe); Receiver outputter = receiver; if ("yes".equals(outputProperties.getProperty(SaxonOutputKeys.WRAP))) { receiver = new SequenceWrapper(outputter); } else { // receiver = new TreeReceiver(outputter); } new PullPushCopier(pull, receiver).copy(); } catch (UncheckedXPathException e) { throw e.getXPathException(); } }
/** * Get the path map for the query expression * * @return the path map (which is constructed if this has not already been done) */ public PathMap getPathMap() { if (pathMap == null) { pathMap = new PathMap(expression); } HashMap map = executable.getCompiledGlobalVariables(); if (map != null) { Iterator iter = map.values().iterator(); while (iter.hasNext()) { GlobalVariable var = (GlobalVariable) iter.next(); Expression select = var.getSelectExpression(); select.addToPathMap(pathMap, null); } } return pathMap; }
/** * Ask whether this query uses the context item * * @return true if the context item is referenced either in the query body or in the initializer * of any global variable */ public boolean usesContextItem() { if ((expression.getDependencies() & StaticProperty.DEPENDS_ON_FOCUS) != 0) { return true; } HashMap map = executable.getCompiledGlobalVariables(); if (map != null) { Iterator iter = map.values().iterator(); while (iter.hasNext()) { GlobalVariable var = (GlobalVariable) iter.next(); Expression select = var.getSelectExpression(); if (select != null && (select.getDependencies() & StaticProperty.DEPENDS_ON_FOCUS) != 0) { return true; } } } return false; }
/** * Run the query returning the results as an EventIterator * * @param controller The Controller used to run the query * @param dynamicEnv the XQuery dynamic context for evaluating the query * @return an EventIterator representing the results of the query as a sequence of events */ public EventIterator iterateEvents(Controller controller, DynamicQueryContext dynamicEnv) throws XPathException { if (isUpdating) { throw new XPathException("Cannot call iterateEvents() on an updating query"); } initializeController(dynamicEnv, controller); XPathContextMajor context = initialContext(dynamicEnv, controller); // In tracing/debugging mode, evaluate all the global variables first if (controller.getTraceListener() != null) { controller.preEvaluateGlobals(context); } context.openStackFrame(stackFrameMap); final Configuration config = executable.getConfiguration(); EventIterator ei = expression.iterateEvents(context); // ei = new TracingEventIterator(EventStackIterator.flatten(ei)); return new ComplexContentProcessor(config, ei); }
/** Get the LocationProvider allowing location identifiers to be resolved. */ public LocationProvider getLocationProvider() { return executable.getLocationMap(); }