com.saxonica.xqj.SaxonXQPreparedExpression Maven / Gradle / Ivy
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2015 Saxonica Limited.
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
// This Source Code Form is "Incompatible With Secondary Licenses", as defined by the Mozilla Public License, v. 2.0.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
package com.saxonica.xqj;
import net.sf.saxon.expr.Expression;
import net.sf.saxon.expr.instruct.GlobalParam;
import net.sf.saxon.expr.instruct.GlobalVariable;
import net.sf.saxon.om.FocusTrackingIterator;
import net.sf.saxon.om.SequenceIterator;
import net.sf.saxon.om.StructuredQName;
import net.sf.saxon.query.DynamicQueryContext;
import net.sf.saxon.query.XQueryExpression;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.type.ItemType;
import net.sf.saxon.value.SequenceExtent;
import net.sf.saxon.value.SequenceType;
import net.sf.saxon.z.IntHashSet;
import net.sf.saxon.z.IntIterator;
import javax.xml.namespace.QName;
import javax.xml.xquery.*;
import java.util.HashSet;
import java.util.List;
/**
* Saxon implementation of the XQJ interface XQPreparedExpression. This represents a compiled XQuery
* expression, together with the dynamic context for its evaluation. Note that this means the object
* should not be used in more than one thread concurrently.
*
* Note that an expression is scrollable or not depending on the scrollability property of the XQConnection
* that was used to compile this expression (at the time it was compiled). If the expression is scrollable then
* its results are delivered in an XQSequence that supports scrolling backwards as well as forwards.
*
* For full Javadoc details, see the XQJ interface specification.
*/
public class SaxonXQPreparedExpression extends SaxonXQDynamicContext implements XQPreparedExpression {
private XQueryExpression expression;
private SaxonXQStaticContext staticContext;
private DynamicQueryContext context;
private boolean scrollable;
protected SaxonXQPreparedExpression(SaxonXQConnection connection,
XQueryExpression expression,
/*@NotNull*/ SaxonXQStaticContext sqc,
DynamicQueryContext context)
throws XQException {
this.connection = connection;
this.expression = expression;
this.staticContext = new SaxonXQStaticContext(sqc); // take a snapshot of the supplied static context
this.context = context;
scrollable = sqc.getScrollability() == XQConstants.SCROLLTYPE_SCROLLABLE;
setClosableContainer(connection);
}
protected DynamicQueryContext getDynamicContext() {
return context;
}
protected SaxonXQConnection getConnection() {
return connection;
}
protected SaxonXQDataFactory getDataFactory() throws XQException {
if (connection.isClosed()) {
close();
}
checkNotClosed();
return connection;
}
protected XQueryExpression getXQueryExpression() {
return expression;
}
protected SaxonXQStaticContext getSaxonXQStaticContext() {
return staticContext;
}
public void cancel() throws XQException {
checkNotClosed();
}
/*@NotNull*/
public XQResultSequence executeQuery() throws XQException {
checkNotClosed();
try {
SequenceIterator iter = expression.iterator(context);
if (scrollable) {
SequenceExtent value = new SequenceExtent(iter);
return new SaxonXQSequence(value, this);
} else {
return new SaxonXQForwardSequence(new FocusTrackingIterator(iter), this);
}
} catch (XPathException de) {
XQException xqe = new XQException(de.getMessage());
xqe.initCause(de);
throw xqe;
}
}
/*@NotNull*/
public QName[] getAllExternalVariables() throws XQException {
checkNotClosed();
List vars = expression.getPackageData().getGlobalVariableList();
if (vars == null || vars.isEmpty()) {
return EMPTY_QNAME_ARRAY;
} else {
HashSet params = new HashSet(vars.size());
for (GlobalVariable var : vars) {
if (var instanceof GlobalParam) {
params.add(var.getVariableQName());
}
}
QName[] qnames = new QName[params.size()];
int q = 0;
for (StructuredQName name : params) {
qnames[q++] = new QName(name.getURI(), name.getLocalPart(), name.getPrefix());
}
return qnames;
}
}
/*@NotNull*/ private static QName[] EMPTY_QNAME_ARRAY = new QName[0];
/*@NotNull*/
public QName[] getAllUnboundExternalVariables() throws XQException {
checkNotClosed();
java.util.Collection boundParameters = getDynamicContext().getParameters().getKeys();
IntHashSet unbound = new IntHashSet(boundParameters.size());
QName[] all = getAllExternalVariables();
for (int i = 0; i < all.length; i++) {
StructuredQName sq = new StructuredQName("", all[i].getNamespaceURI(), all[i].getLocalPart());
if (!boundParameters.contains(sq)) {
unbound.add(i);
}
}
QName[] unboundq = new QName[unbound.size()];
int c = 0;
IntIterator iter = unbound.iterator();
while (iter.hasNext()) {
int x = iter.next();
unboundq[c++] = all[x];
}
return unboundq;
}
public XQStaticContext getStaticContext() throws XQException {
checkNotClosed();
return staticContext; // a snapshot of the static context at the time the expression was created
// old code in Saxon 9.2:
// return new SaxonXQExpressionContext(expression);
}
/*@NotNull*/
public XQSequenceType getStaticResultType() throws XQException {
checkNotClosed();
Expression exp = expression.getExpression(); // unwrap two layers!
ItemType itemType = exp.getItemType();
int cardinality = exp.getCardinality();
SequenceType staticType = SequenceType.makeSequenceType(itemType, cardinality);
return new SaxonXQSequenceType(staticType, connection.getConfiguration());
}
/*@NotNull*/
public XQSequenceType getStaticVariableType(QName name) throws XQException {
checkNotClosed();
checkNotNull(name);
StructuredQName qn = new StructuredQName(
name.getPrefix(), name.getNamespaceURI(), name.getLocalPart());
for (GlobalVariable var : expression.getPackageData().getGlobalVariableList()) {
if (var instanceof GlobalParam && var.getVariableQName().equals(qn)) {
return new SaxonXQSequenceType(var.getRequiredType(), connection.getConfiguration());
}
}
throw new XQException("Variable " + name + " is not declared");
}
protected boolean externalVariableExists(QName name) {
StructuredQName qn = new StructuredQName(
name.getPrefix(), name.getNamespaceURI(), name.getLocalPart());
for (GlobalVariable var : expression.getPackageData().getGlobalVariableList()) {
if (var instanceof GlobalParam && var.getVariableQName().equals(qn)) {
return true;
}
}
return false;
}
private void checkNotNull(/*@Nullable*/ Object arg) throws XQException {
if (arg == null) {
throw new XQException("Argument is null");
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy