/** * 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 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; }
private void initializeController(DynamicQueryContext env, Controller controller) { HashMap parameters = env.getParameters(); if (parameters != null) { Iterator iter = parameters.keySet().iterator(); while (iter.hasNext()) { String paramName = (String) iter.next(); Object paramValue = parameters.get(paramName); controller.setParameter(paramName, paramValue); } } controller.setURIResolver(env.getURIResolver()); controller.setErrorListener(env.getErrorListener()); controller.addTraceListener(env.getTraceListener()); controller.setTraceFunctionDestination(env.getTraceFunctionDestination()); DateTimeValue currentDateTime = env.getCurrentDateTime(); if (currentDateTime != null) { try { controller.setCurrentDateTime(currentDateTime); } catch (XPathException e) { throw new AssertionError(e); // the value should already have been checked } } }