/** * 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(); }
/** Create and compile an XPath expression object. */ public Object makeObject() throws Exception { if (logger.isDebugEnabled()) logger.debug("makeObject(" + xpathString + ")"); // Create context final IndependentContext independentContext = new XPathCacheStaticContext(allowAllVariables); // Set the base URI if specified if (baseURI != null) independentContext.setBaseURI(baseURI); // Declare namespaces if (prefixToURIMap != null) { for (final String prefix : prefixToURIMap.keySet()) { independentContext.declareNamespace(prefix, prefixToURIMap.get(prefix)); } } // Declare variables (we don't use the values here, just the names) final Map<String, Variable> variables = new HashMap<String, Variable>(); if (variableNames != null) { for (final String name : variableNames) { final Variable variable = independentContext.declareVariable(name); variable.setUseStack( true); // "Indicate that values of variables are to be found on the stack, not in the // Variable object itself" variables.put(name, variable); } } // Add function library if (functionLibrary != null) { // This is ok ((FunctionLibraryList) independentContext.getFunctionLibrary()) .libraryList.add(0, functionLibrary); } // Create and compile the expression try { final Expression expression; if (isAvt) { final Expression tempExpression = AttributeValueTemplate.make(xpathString, -1, independentContext); // Running typeCheck() is mandatory otherwise things break! This is also done when using // evaluator.createExpression() expression = tempExpression.typeCheck(independentContext, Type.ITEM_TYPE); } else { // We used to use XPathEvaluator.createExpression(), but there is a bug in it related to // slots allocation, so we do the work ourselves instead. final Expression tempExpression = ExpressionTool.make(xpathString, independentContext, 0, Token.EOF, 1); expression = tempExpression.typeCheck(independentContext, Type.ITEM_TYPE); } // Allocate variable slots in all cases ExpressionTool.allocateSlots( expression, independentContext.getStackFrameMap().getNumberOfVariables(), independentContext.getStackFrameMap()); { // Provide an Executable with the only purpose of allowing the evaluate() function find // the right // FunctionLibrary if (expression instanceof ComputedExpression) { final ComputedExpression computedExpression = (ComputedExpression) expression; computedExpression.setParentExpression( new Container() { public Executable getExecutable() { return new Executable() { { setFunctionLibrary(independentContext.getFunctionLibrary()); setLocationMap(new LocationMap()); setConfiguration(independentContext.getConfiguration()); } }; } public LocationProvider getLocationProvider() { return computedExpression.getLocationProvider(); } public int getHostLanguage() { return Configuration.JAVA_APPLICATION; } public boolean replaceSubExpression( Expression expression, Expression expression1) { return computedExpression.replaceSubExpression(expression, expression1); } public int getColumnNumber() { return (locationData != null) ? locationData.getCol() : -1; } public int getLineNumber() { return (locationData != null) ? locationData.getLine() : -1; } public String getPublicId() { return (locationData != null) ? locationData.getPublicID() : null; } public String getSystemId() { return (locationData != null) ? locationData.getSystemID() : null; } }); } } // TODO: For now only play with XForms expressions. But should decide probably based on // flag? if (false && functionLibrary == XFormsContainingDocument.getFunctionLibrary()) { final List<String> instanceIds = analyzeExpression(expression, xpathString); if (instanceIds == null) logger.info(" XXX EXPRESSION DEPENDS ON MORE THAN INSTANCES: " + xpathString); else { logger.info(" XXX EXPRESSION DEPENDS ON INSTANCES: " + xpathString); for (String instanceId : instanceIds) { logger.info(" instance: " + instanceId); } } } return new PooledXPathExpression(expression, pool, independentContext, variables); } catch (Throwable t) { throw new OXFException(t); } }