package org.basex.api.xqj; import static org.basex.api.xqj.BXQText.*; import java.io.InputStream; import java.io.Reader; import java.math.BigDecimal; import java.util.GregorianCalendar; import java.util.TimeZone; import javax.xml.namespace.QName; import javax.xml.stream.XMLStreamReader; import javax.xml.transform.Source; import javax.xml.xquery.XQCancelledException; import javax.xml.xquery.XQConstants; import javax.xml.xquery.XQDynamicContext; import javax.xml.xquery.XQException; import javax.xml.xquery.XQItem; import javax.xml.xquery.XQItemType; import javax.xml.xquery.XQQueryException; import javax.xml.xquery.XQSequence; import org.basex.core.ProgressException; import org.basex.io.IOContent; import org.basex.query.QueryContext; import org.basex.query.QueryException; import org.basex.query.QueryProcessor; import org.basex.query.item.Atm; import org.basex.query.item.AtomType; import org.basex.query.item.Bln; import org.basex.query.item.Dbl; import org.basex.query.item.Dec; import org.basex.query.item.Flt; import org.basex.query.item.Item; import org.basex.query.item.Int; import org.basex.query.item.QNm; import org.basex.query.item.Str; import org.basex.query.item.Type; import org.basex.query.item.Value; import org.basex.query.iter.Iter; import org.basex.query.util.Var; import org.basex.util.Performance; import org.basex.util.Token; import org.w3c.dom.Node; /** * Java XQuery API - Dynamic Context. * * @author BaseX Team 2005-12, BSD License * @author Christian Gruen */ abstract class BXQDynamicContext extends BXQAbstract implements XQDynamicContext { /** Context. */ protected final BXQStaticContext sc; /** Query processor. */ protected final QueryProcessor qp; /** Time zone. */ private TimeZone zone; /** * Constructor. * @param s static context * @param qu query * @param c closer */ protected BXQDynamicContext(final String qu, final BXQStaticContext s, final BXQConnection c) { super(c); sc = s; qp = new QueryProcessor(qu, BXQDataSource.context()); qp.ctx.sc.copy(sc.sc); } @Override public void bindAtomicValue(final QName qn, final String v, final XQItemType t) throws XQException { valid(t, XQItemType.class); bind(qn, new Atm(Token.token(valid(v, String.class).toString())), t); } @Override public void bindBoolean(final QName qn, final boolean v, final XQItemType it) throws XQException { bind(qn, Bln.get(v), it); } @Override public void bindByte(final QName qn, final byte v, final XQItemType t) throws XQException { bind(qn, Int.get(v, AtomType.BYT), t); } @Override public void bindDocument(final QName qn, final InputStream is, final String base, final XQItemType t) throws XQException { bind(qn, createNode(is), t); } @Override public void bindDocument(final QName qn, final Reader r, final String base, final XQItemType t) throws XQException { bind(qn, createNode(r), t); } @Override public void bindDocument(final QName qn, final Source s, final XQItemType t) throws XQException { bind(qn, createNode(s, t), t); } @Override public void bindDocument(final QName qn, final String v, final String base, final XQItemType t) throws XQException { valid(v, String.class); bind(qn, createNode(new IOContent(Token.token(v))), t); } @Override public void bindDocument(final QName qn, final XMLStreamReader sr, final XQItemType t) throws XQException { bind(qn, createNode(sr), t); } @Override public void bindDouble(final QName qn, final double v, final XQItemType t) throws XQException { bind(qn, Dbl.get(v), t); } @Override public void bindFloat(final QName qn, final float v, final XQItemType t) throws XQException { bind(qn, Flt.get(v), t); } @Override public void bindInt(final QName qn, final int v, final XQItemType t) throws XQException { bind(qn, Int.get(v), t); } @Override public void bindItem(final QName qn, final XQItem t) throws XQException { valid(t, XQItem.class); bind(qn, ((BXQItem) t).it, null); } @Override public void bindLong(final QName qn, final long v, final XQItemType t) throws XQException { bind(qn, new Dec(new BigDecimal(v), AtomType.LNG), t); } @Override public void bindNode(final QName qn, final Node v, final XQItemType t) throws XQException { bind(qn, create(v, null), t); } @Override public void bindObject(final QName qn, final Object v, final XQItemType t) throws XQException { bind(qn, create(v, null), t); } @Override public void bindSequence(final QName qn, final XQSequence s) throws XQException { valid(s, XQSequence.class); try { bind(qn, ((BXQSequence) s).result.value(), null); } catch(final QueryException ex) { throw new BXQException(ex); } } @Override public void bindShort(final QName qn, final short v, final XQItemType t) throws XQException { bind(qn, Int.get(v, AtomType.SHR), t); } @Override public void bindString(final QName qn, final String v, final XQItemType t) throws XQException { bind(qn, Str.get(valid(v, String.class)), t); } @Override public TimeZone getImplicitTimeZone() throws XQException { opened(); return zone != null ? zone : new GregorianCalendar().getTimeZone(); } @Override public void setImplicitTimeZone(final TimeZone tz) throws XQException { opened(); zone = tz; } /** * Binds an item to the specified variable. * @param var variable name * @param v value to be bound * @param t target type * @throws XQException query exception */ private void bind(final QName var, final Value v, final XQItemType t) throws XQException { opened(); valid(var, QName.class); final Type tt = check(v.type, t); Value vl = v; // don't cast sequences if(tt != v.type && v instanceof Item) { try { vl = tt.cast((Item) v, qp.ctx, null); } catch(final QueryException ex) { throw new BXQException(ex); } } try { if(var == XQConstants.CONTEXT_ITEM) { qp.context(vl); } else { if(this instanceof BXQPreparedExpression) { final Var vr = qp.ctx.vars.get(new QNm(var)); if(vr == null) throw new BXQException(VAR, var); vr.bind(vl, null); } else { qp.bind(var.getLocalPart(), vl); } } } catch(final QueryException ex) { throw new BXQException(ex); } } /** * Executes the specified query and returns the result iterator. * @return result sequence * @throws XQException exception */ protected final BXQSequence execute() throws XQException { opened(); final QueryContext qctx = qp.ctx; qctx.sc.ns = sc.sc.ns; try { if(sc.timeout != 0) { new Thread() { @Override public void run() { Performance.sleep(sc.timeout * 1000l); qctx.stop(); } }.start(); } qp.parse(); qctx.compile(); Iter iter = qctx.iter(); if(sc.scrollable) iter = iter.value().cache(); return new BXQSequence(iter, this, (BXQConnection) par); } catch(final QueryException ex) { final QNm qnm = ex.qname(); throw new XQQueryException(ex.getMessage(), new QName(Token.string(qnm.uri()), Token.string(qnm.local())), ex.line(), ex.col(), -1); } catch(final ProgressException ex) { throw new XQCancelledException(TIMEOUT, null, null, -1, -1, -1, null, null, null); } } @Override public final void close() throws XQException { try { if(!closed) qp.close(); } catch(final QueryException ex) { throw new XQQueryException(ex.getMessage()); } super.close(); } }