/** * 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(); }
/** * In the case of a text-only instruction (xsl:variable containing a text node or one or more * xsl:value-of instructions), return an expression that evaluates to the textual content as an * instance of xs:untypedAtomic * * @param env the static evaluation context * @return an expression that evaluates to the textual content */ public Expression getStringValueExpression(StaticContext env) { if (textOnly) { if (constantText != null) { return new StringLiteral(new UntypedAtomicValue(constantText)); } else if (content instanceof ValueOf) { return ((ValueOf) content).convertToStringJoin(env); } else { StringJoin fn = (StringJoin) SystemFunction.makeSystemFunction( "string-join", new Expression[] {content, new StringLiteral(StringValue.EMPTY_STRING)}); CastExpression cast = new CastExpression(fn, BuiltInAtomicType.UNTYPED_ATOMIC, false); ExpressionTool.copyLocationInfo(this, cast); return cast; } } else { throw new AssertionError( "getStringValueExpression() called on non-text-only document instruction"); } }
public Item evaluateItem(XPathContext xpathContext) throws XPathException { // Get parameters final Item item = argument[0].evaluateItem(xpathContext); final String excludeResultPrefixes = argument.length >= 2 ? argument[1].evaluateAsString(xpathContext).toString() : null; final boolean readonly = argument.length >= 3 && ExpressionTool.effectiveBooleanValue(argument[2].iterate(xpathContext)); // Make sure it is a NodeInfo if (!(item instanceof NodeInfo)) { return null; } // Get Element final Element rootElement; if (item instanceof NodeWrapper) { final Object node = ((NodeWrapper) item).getUnderlyingNode(); rootElement = (Element) node; } else { final NodeInfo nodeInfo = (NodeInfo) item; final Document document = TransformerUtils.tinyTreeToDom4j2(nodeInfo); rootElement = document.getRootElement(); } // Convert to Document or DocumentInfo final Object result = extractDocument( xpathContext.getConfiguration(), rootElement, excludeResultPrefixes, readonly); // Return DocumentInfo if (result instanceof Document) return new DocumentWrapper( (Document) result, null, getContainingDocument(xpathContext).getStaticState().getXPathConfiguration()); else return (DocumentInfo) result; }
/** 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); } }