use of org.exist.xquery.XPathException in project exist by eXist-db.
the class Update method eval.
/* (non-Javadoc)
* @see org.exist.xquery.AbstractExpression#eval(org.exist.xquery.value.Sequence, org.exist.xquery.value.Item)
*/
public Sequence eval(Sequence contextSequence, Item contextItem) throws XPathException {
if (context.getProfiler().isEnabled()) {
context.getProfiler().start(this);
context.getProfiler().message(this, Profiler.DEPENDENCIES, "DEPENDENCIES", Dependency.getDependenciesName(this.getDependencies()));
if (contextSequence != null) {
context.getProfiler().message(this, Profiler.START_SEQUENCES, "CONTEXT SEQUENCE", contextSequence);
}
if (contextItem != null) {
context.getProfiler().message(this, Profiler.START_SEQUENCES, "CONTEXT ITEM", contextItem.toSequence());
}
}
if (contextItem != null) {
contextSequence = contextItem.toSequence();
}
final Sequence contentSeq = value.eval(contextSequence);
if (contentSeq.isEmpty()) {
throw new XPathException(this, Messages.getMessage(Error.UPDATE_EMPTY_CONTENT));
}
final Sequence inSeq = select.eval(contextSequence);
/* If we try and Update a node at an invalid location,
* trap the error in a context variable,
* this is then accessible from xquery via. the context extension module - deliriumsky
* TODO: This trapping could be expanded further - basically where XPathException is thrown from thiss class
* TODO: Maybe we could provide more detailed messages in the trap, e.g. couldnt update node `xyz` into `abc` becuase... this would be nicer for the end user of the xquery application
*/
if (!Type.subTypeOf(inSeq.getItemType(), Type.NODE)) {
// Indicate the failure to perform this update by adding it to the sequence in the context variable XQueryContext.XQUERY_CONTEXTVAR_XQUERY_UPDATE_ERROR
ValueSequence prevUpdateErrors = null;
final XPathException xpe = new XPathException(this, Messages.getMessage(Error.UPDATE_SELECT_TYPE));
final Object ctxVarObj = context.getAttribute(XQueryContext.XQUERY_CONTEXTVAR_XQUERY_UPDATE_ERROR);
if (ctxVarObj == null) {
prevUpdateErrors = new ValueSequence();
} else {
prevUpdateErrors = (ValueSequence) XPathUtil.javaObjectToXPath(ctxVarObj, context);
}
prevUpdateErrors.add(new StringValue(xpe.getMessage()));
context.setAttribute(XQueryContext.XQUERY_CONTEXTVAR_XQUERY_UPDATE_ERROR, prevUpdateErrors);
if (!inSeq.isEmpty()) {
// TODO: should we trap this instead of throwing an exception - deliriumsky?
throw xpe;
}
}
if (!inSeq.isEmpty()) {
context.pushInScopeNamespaces();
// start a transaction
try (final Txn transaction = getTransaction()) {
final NotificationService notifier = context.getBroker().getBrokerPool().getNotificationService();
final StoredNode[] ql = selectAndLock(transaction, inSeq);
for (final StoredNode node : ql) {
final DocumentImpl doc = node.getOwnerDocument();
if (!doc.getPermissions().validate(context.getSubject(), Permission.WRITE)) {
throw new XPathException(this, "User '" + context.getSubject().getName() + "' does not have permission to write to the document '" + doc.getDocumentURI() + "'!");
}
// update the document
switch(node.getNodeType()) {
case Node.ELEMENT_NODE:
final NodeListImpl content = new NodeListImpl();
for (final SequenceIterator j = contentSeq.iterate(); j.hasNext(); ) {
final Item next = j.nextItem();
if (Type.subTypeOf(next.getType(), Type.NODE)) {
content.add(((NodeValue) next).getNode());
} else {
final TextImpl text = new TextImpl(next.getStringValue());
content.add(text);
}
}
((ElementImpl) node).update(transaction, content);
break;
case Node.TEXT_NODE:
final ElementImpl textParent = (ElementImpl) node.getParentNode();
final TextImpl text = new TextImpl(contentSeq.getStringValue());
text.setOwnerDocument(doc);
textParent.updateChild(transaction, node, text);
break;
case Node.ATTRIBUTE_NODE:
final ElementImpl attrParent = (ElementImpl) ((Attr) node).getOwnerElement();
if (attrParent == null) {
LOG.warn("parent node not found for {}", node.getNodeId());
break;
}
final AttrImpl attr = (AttrImpl) node;
final AttrImpl attribute = new AttrImpl(attr.getQName(), contentSeq.getStringValue(), context.getBroker().getBrokerPool().getSymbols());
attribute.setOwnerDocument(doc);
attrParent.updateChild(transaction, node, attribute);
break;
default:
throw new XPathException(this, "unsupported node-type");
}
doc.setLastModified(System.currentTimeMillis());
modifiedDocuments.add(doc);
context.getBroker().storeXMLResource(transaction, doc);
notifier.notifyUpdate(doc, UpdateListener.UPDATE);
}
finishTriggers(transaction);
// commit the transaction
transaction.commit();
} catch (final LockException | EXistException | TriggerException e) {
throw new XPathException(this, e.getMessage(), e);
} finally {
unlockDocuments();
context.popInScopeNamespaces();
}
}
if (context.getProfiler().isEnabled()) {
context.getProfiler().end(this, "", Sequence.EMPTY_SEQUENCE);
}
return Sequence.EMPTY_SEQUENCE;
}
use of org.exist.xquery.XPathException in project exist by eXist-db.
the class ArrayListValueSequence method toNodeSet.
@Override
public NodeSet toNodeSet() throws XPathException {
if (isEmpty) {
return NodeSet.EMPTY_SET;
}
// for this method to work, all items have to be nodes
if (itemType != Type.ANY_TYPE && Type.subTypeOf(itemType, Type.NODE)) {
final NodeSet set = new NewArrayNodeSet();
for (int i = 0; i <= values.size(); i++) {
NodeValue v = (NodeValue) values.get(i);
if (v.getImplementationType() != NodeValue.PERSISTENT_NODE) {
// found an in-memory document
final DocumentImpl doc;
if (v.getType() == Type.DOCUMENT) {
doc = (DocumentImpl) v;
} else {
doc = ((NodeImpl) v).getOwnerDocument();
}
if (doc == null) {
continue;
}
// make this document persistent: doc.makePersistent()
// returns a map of all root node ids mapped to the corresponding
// persistent node. We scan the current sequence and replace all
// in-memory nodes with their new persistent node objects.
final DocumentImpl expandedDoc = doc.expandRefs(null);
final org.exist.dom.persistent.DocumentImpl newDoc = expandedDoc.makePersistent();
if (newDoc != null) {
NodeId rootId = newDoc.getBrokerPool().getNodeFactory().createInstance();
for (int j = i; j <= values.size(); j++) {
v = (NodeValue) values.get(j);
if (v.getImplementationType() != NodeValue.PERSISTENT_NODE) {
NodeImpl node = (NodeImpl) v;
final Document nodeOwnerDoc;
if (node.getNodeType() == Node.DOCUMENT_NODE) {
nodeOwnerDoc = (Document) node;
} else {
nodeOwnerDoc = node.getOwnerDocument();
}
if (nodeOwnerDoc == doc) {
if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
node = expandedDoc.getAttribute(node.getNodeNumber());
} else {
node = expandedDoc.getNode(node.getNodeNumber());
}
NodeId nodeId = node.getNodeId();
if (nodeId == null) {
throw new XPathException("Internal error: nodeId == null");
}
if (node.getNodeType() == Node.DOCUMENT_NODE) {
nodeId = rootId;
} else {
nodeId = rootId.append(nodeId);
}
final NodeProxy p = new NodeProxy(newDoc, nodeId, node.getNodeType());
// replace the node by the NodeProxy
values.set(j, p);
setHasChanged();
}
}
}
set.add((NodeProxy) values.get(i));
}
} else {
set.add((NodeProxy) v);
}
}
// }
return set;
} else {
throw new XPathException("Type error: the sequence cannot be converted into" + " a node set. Item type is " + Type.getTypeName(itemType));
}
}
use of org.exist.xquery.XPathException in project exist by eXist-db.
the class BinaryValueFromBinaryString method convertTo.
@Override
public BinaryValue convertTo(BinaryValueType binaryValueType) throws XPathException {
// TODO temporary approach, consider implementing a TranscodingBinaryValueFromBinaryString(BinaryValueFromBinaryString) class
// that only does the transncoding lazily
final UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream();
FilterOutputStream fos = null;
try {
// transcode
fos = binaryValueType.getEncoder(baos);
streamBinaryTo(fos);
} catch (final IOException ioe) {
throw new XPathException(ioe);
} finally {
if (fos != null) {
try {
fos.close();
} catch (final IOException ioe) {
LOG.error("Unable to close stream: {}", ioe.getMessage(), ioe);
}
}
try {
baos.close();
} catch (final IOException ioe) {
LOG.error("Unable to close stream: {}", ioe.getMessage(), ioe);
}
}
return new BinaryValueFromBinaryString(binaryValueType, baos.toString(UTF_8));
}
use of org.exist.xquery.XPathException in project exist by eXist-db.
the class DecimalValue method mod.
/* (non-Javadoc)
* @see org.exist.xquery.value.NumericValue#mod(org.exist.xquery.value.NumericValue)
*/
public NumericValue mod(NumericValue other) throws XPathException {
if (other.getType() == Type.DECIMAL) {
if (other.isZero()) {
throw new XPathException(ErrorCodes.FOAR0001, "division by zero");
}
final BigDecimal quotient = value.divide(((DecimalValue) other).value, 0, RoundingMode.DOWN);
final BigDecimal remainder = value.subtract(quotient.setScale(0, RoundingMode.DOWN).multiply(((DecimalValue) other).value));
return new DecimalValue(remainder);
} else {
return ((NumericValue) convertTo(other.getType())).mod(other);
}
}
use of org.exist.xquery.XPathException in project exist by eXist-db.
the class AtomicValue method toSAX.
@Override
public void toSAX(final DBBroker broker, final ContentHandler handler, final Properties properties) throws SAXException {
try {
final String s = getStringValue();
handler.characters(s.toCharArray(), 0, s.length());
} catch (final XPathException e) {
throw new SAXException(e);
}
}
Aggregations