use of org.exist.dom.persistent.ElementImpl in project exist by eXist-db.
the class Update method process.
@Override
public long process(Txn transaction) throws PermissionDeniedException, LockException, EXistException, XPathException, TriggerException {
final NodeList children = content;
if (children.getLength() == 0) {
return 0;
}
int modifications = children.getLength();
try {
final StoredNode[] ql = selectAndLock(transaction);
final NotificationService notifier = broker.getBrokerPool().getNotificationService();
for (final StoredNode node : ql) {
if (node == null) {
LOG.warn("select {} returned empty node", selectStmt);
continue;
}
final DocumentImpl doc = node.getOwnerDocument();
if (!doc.getPermissions().validate(broker.getCurrentSubject(), Permission.WRITE)) {
throw new PermissionDeniedException("User '" + broker.getCurrentSubject().getName() + "' does not have permission to write to the document '" + doc.getDocumentURI() + "'!");
}
switch(node.getNodeType()) {
case Node.ELEMENT_NODE:
if (modifications == 0) {
modifications = 1;
}
((ElementImpl) node).update(transaction, children);
break;
case Node.TEXT_NODE:
final ElementImpl textParent = (ElementImpl) node.getParentNode();
final Node textTemp = children.item(0);
final TextImpl text = new TextImpl(textTemp.getNodeValue());
modifications = 1;
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 Node attrTemp = children.item(0);
final AttrImpl attribute = new AttrImpl(attr.getQName(), attrTemp.getNodeValue(), broker.getBrokerPool().getSymbols());
attribute.setOwnerDocument(doc);
attrParent.updateChild(transaction, node, attribute);
break;
default:
throw new EXistException("unsupported node-type");
}
doc.setLastModified(System.currentTimeMillis());
modifiedDocuments.add(doc);
broker.storeXMLResource(transaction, doc);
notifier.notifyUpdate(doc, UpdateListener.UPDATE);
}
checkFragmentation(transaction, modifiedDocuments);
} finally {
unlockDocuments(transaction);
}
return modifications;
}
use of org.exist.dom.persistent.ElementImpl 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.dom.persistent.ElementImpl in project exist by eXist-db.
the class Replace method process.
@Override
public long process(Txn transaction) throws PermissionDeniedException, LockException, EXistException, XPathException, TriggerException {
final NodeList children = content;
if (children.getLength() == 0) {
return 0;
}
if (children.getLength() > 1) {
throw new EXistException("xupdate:replace requires exactly one content node");
}
LOG.debug("processing replace ...");
int modifications = children.getLength();
try {
final StoredNode[] ql = selectAndLock(transaction);
final NotificationService notifier = broker.getBrokerPool().getNotificationService();
Node temp;
TextImpl text;
AttrImpl attribute;
ElementImpl parent;
for (final StoredNode node : ql) {
if (node == null) {
LOG.warn("select {} returned empty node set", selectStmt);
continue;
}
final DocumentImpl doc = node.getOwnerDocument();
if (!doc.getPermissions().validate(broker.getCurrentSubject(), Permission.WRITE)) {
throw new PermissionDeniedException("User '" + broker.getCurrentSubject().getName() + "' does not have permission to write to the document '" + doc.getDocumentURI() + "'!");
}
parent = (ElementImpl) node.getParentStoredNode();
if (parent == null) {
throw new EXistException("The root element of a document can not be replaced with 'xu:replace'. " + "Please consider removing the document or use 'xu:update' to just replace the children of the root.");
}
switch(node.getNodeType()) {
case Node.ELEMENT_NODE:
if (modifications == 0) {
modifications = 1;
}
temp = children.item(0);
parent.replaceChild(transaction, temp, node);
break;
case Node.TEXT_NODE:
temp = children.item(0);
text = new TextImpl(temp.getNodeValue());
modifications = 1;
text.setOwnerDocument(doc);
parent.updateChild(transaction, node, text);
break;
case Node.ATTRIBUTE_NODE:
final AttrImpl attr = (AttrImpl) node;
temp = children.item(0);
attribute = new AttrImpl(attr.getQName(), temp.getNodeValue(), broker.getBrokerPool().getSymbols());
attribute.setOwnerDocument(doc);
parent.updateChild(transaction, node, attribute);
break;
default:
throw new EXistException("unsupported node-type");
}
doc.setLastModified(System.currentTimeMillis());
modifiedDocuments.add(doc);
broker.storeXMLResource(transaction, doc);
notifier.notifyUpdate(doc, UpdateListener.UPDATE);
}
checkFragmentation(transaction, modifiedDocuments);
} finally {
unlockDocuments(transaction);
}
return modifications;
}
use of org.exist.dom.persistent.ElementImpl in project exist by eXist-db.
the class NativeSerializer method serializeToReceiver.
protected void serializeToReceiver(IStoredNode node, INodeIterator iter, DocumentImpl doc, boolean first, Match match, Set<String> namespaces) throws SAXException {
if (node == null && iter.hasNext()) {
node = iter.next();
}
if (node == null) {
return;
}
// char ch[];
String cdata;
switch(node.getNodeType()) {
case Node.ELEMENT_NODE:
receiver.setCurrentNode(node);
String defaultNS = null;
if (((ElementImpl) node).declaresNamespacePrefixes()) {
// declare namespaces used by this element
String prefix, uri;
for (final Iterator<String> i = ((ElementImpl) node).getPrefixes(); i.hasNext(); ) {
prefix = i.next();
if (prefix.isEmpty()) {
defaultNS = ((ElementImpl) node).getNamespaceForPrefix(prefix);
receiver.startPrefixMapping(XMLConstants.DEFAULT_NS_PREFIX, defaultNS);
namespaces.add(defaultNS);
} else {
uri = ((ElementImpl) node).getNamespaceForPrefix(prefix);
receiver.startPrefixMapping(prefix, uri);
namespaces.add(uri);
}
}
}
final String ns = defaultNS == null ? node.getNamespaceURI() : defaultNS;
if (ns != null && ns.length() > 0 && (!namespaces.contains(ns))) {
String prefix = node.getPrefix();
if (prefix == null) {
prefix = XMLConstants.DEFAULT_NS_PREFIX;
}
receiver.startPrefixMapping(prefix, ns);
}
final AttrList attribs = new AttrList();
if ((first && showId == EXIST_ID_ELEMENT) || showId == EXIST_ID_ALL) {
attribs.addAttribute(ID_ATTRIB, node.getNodeId().toString());
/*
* This is a proposed fix-up that the serializer could do
* to make sure elements always have the namespace declarations
*
} else {
// This is fix-up for when the node has a namespace but there is no
// namespace declaration.
String elementNS = node.getNamespaceURI();
Node parent = node.getParentNode();
if (parent instanceof ElementImpl) {
ElementImpl parentElement = (ElementImpl)parent;
String declaredNS = parentElement.getNamespaceForPrefix(node.getPrefix());
if (elementNS!=null && declaredNS==null) {
// We need to declare the prefix as it was missed somehow
receiver.startPrefixMapping(node.getPrefix(), elementNS);
} else if (elementNS==null && declaredNS!=null) {
// We need to declare the default namespace to be the no namespace
receiver.startPrefixMapping(node.getPrefix(), elementNS);
} else if (!elementNS.equals(defaultNS)) {
// Same prefix but different namespace
receiver.startPrefixMapping(node.getPrefix(), elementNS);
}
} else if (elementNS!=null) {
// If the parent is the document, we must have a namespace
// declaration when there is a namespace URI.
receiver.startPrefixMapping(node.getPrefix(), elementNS);
}
*/
}
if (first && showId > 0) {
// String src = doc.getCollection().getName() + "/" + doc.getFileName();
attribs.addAttribute(SOURCE_ATTRIB, doc.getFileURI().toString());
}
final int children = node.getChildCount();
int count = 0;
IStoredNode child = null;
StringBuilder matchAttrCdata = null;
StringBuilder matchAttrOffsetsCdata = null;
StringBuilder matchAttrLengthsCdata = null;
while (count < children) {
child = iter.hasNext() ? iter.next() : null;
if (child != null && child.getNodeType() == Node.ATTRIBUTE_NODE) {
if ((getHighlightingMode() & TAG_ATTRIBUTE_MATCHES) == TAG_ATTRIBUTE_MATCHES && match != null && child.getNodeId().equals(match.getNodeId())) {
if (matchAttrCdata == null) {
matchAttrCdata = new StringBuilder();
matchAttrOffsetsCdata = new StringBuilder();
matchAttrLengthsCdata = new StringBuilder();
} else {
matchAttrCdata.append(",");
matchAttrOffsetsCdata.append(",");
matchAttrLengthsCdata.append(",");
}
matchAttrCdata.append(child.getQName().toString());
matchAttrOffsetsCdata.append(match.getOffset(0).getOffset());
matchAttrLengthsCdata.append(match.getOffset(0).getLength());
match = match.getNextMatch();
}
cdata = ((AttrImpl) child).getValue();
attribs.addAttribute(child.getQName(), cdata);
count++;
child.release();
} else {
break;
}
}
if (matchAttrCdata != null) {
attribs.addAttribute(MATCHES_ATTRIB, matchAttrCdata.toString());
// mask the full-text index which doesn't provide offset and length
M_ZERO_VALUES.reset(matchAttrOffsetsCdata);
final boolean offsetsIsZero = M_ZERO_VALUES.matches();
M_ZERO_VALUES.reset(matchAttrLengthsCdata);
final boolean lengthsIsZero = M_ZERO_VALUES.matches();
if (!offsetsIsZero && !lengthsIsZero) {
attribs.addAttribute(MATCHES_OFFSET_ATTRIB, matchAttrOffsetsCdata.toString());
attribs.addAttribute(MATCHES_LENGTH_ATTRIB, matchAttrLengthsCdata.toString());
}
}
receiver.setCurrentNode(node);
receiver.startElement(node.getQName(), attribs);
while (count < children) {
serializeToReceiver(child, iter, doc, false, match, namespaces);
if (++count < children) {
child = iter.hasNext() ? iter.next() : null;
} else {
break;
}
}
receiver.setCurrentNode(node);
receiver.endElement(node.getQName());
if (((ElementImpl) node).declaresNamespacePrefixes()) {
for (final Iterator<String> i = ((ElementImpl) node).getPrefixes(); i.hasNext(); ) {
final String prefix = i.next();
receiver.endPrefixMapping(prefix);
}
}
if (ns != null && ns.length() > 0 && (!namespaces.contains(ns))) {
String prefix = node.getPrefix();
if (prefix == null) {
prefix = XMLConstants.DEFAULT_NS_PREFIX;
}
receiver.endPrefixMapping(prefix);
}
node.release();
break;
case Node.TEXT_NODE:
if (first && createContainerElements) {
final AttrList tattribs = new AttrList();
if (showId > 0) {
tattribs.addAttribute(ID_ATTRIB, node.getNodeId().toString());
tattribs.addAttribute(SOURCE_ATTRIB, doc.getFileURI().toString());
}
receiver.startElement(TEXT_ELEMENT, tattribs);
}
receiver.setCurrentNode(node);
receiver.characters(((TextImpl) node).getXMLString());
if (first && createContainerElements) {
receiver.endElement(TEXT_ELEMENT);
}
node.release();
break;
case Node.ATTRIBUTE_NODE:
if ((getHighlightingMode() & TAG_ATTRIBUTE_MATCHES) == TAG_ATTRIBUTE_MATCHES && match != null && node.getNodeId().equals(match.getNodeId())) {
// TODO(AR) do we need to expand attribute matches here also? see {@code matchAttrCdata} above
}
cdata = ((AttrImpl) node).getValue();
if (first) {
if (createContainerElements) {
final AttrList tattribs = new AttrList();
if (showId > 0) {
tattribs.addAttribute(ID_ATTRIB, node.getNodeId().toString());
tattribs.addAttribute(SOURCE_ATTRIB, doc.getFileURI().toString());
}
tattribs.addAttribute(node.getQName(), cdata);
receiver.startElement(ATTRIB_ELEMENT, tattribs);
receiver.endElement(ATTRIB_ELEMENT);
} else {
if (this.outputProperties.getProperty("output-method") != null && "text".equals(this.outputProperties.getProperty("output-method"))) {
receiver.characters(node.getNodeValue());
} else {
LOG.warn("Error SENR0001: attribute '{}' has no parent element. While serializing document {}", node.getQName(), doc.getURI());
throw new SAXException("Error SENR0001: attribute '" + node.getQName() + "' has no parent element");
}
}
} else {
receiver.attribute(node.getQName(), cdata);
}
node.release();
break;
case Node.DOCUMENT_TYPE_NODE:
final String systemId = ((DocumentTypeImpl) node).getSystemId();
final String publicId = ((DocumentTypeImpl) node).getPublicId();
final String name = ((DocumentTypeImpl) node).getName();
receiver.documentType(name, publicId, systemId);
break;
case Node.PROCESSING_INSTRUCTION_NODE:
receiver.processingInstruction(((ProcessingInstructionImpl) node).getTarget(), ((ProcessingInstructionImpl) node).getData());
node.release();
break;
case Node.COMMENT_NODE:
final String comment = ((CommentImpl) node).getData();
char[] data = new char[comment.length()];
comment.getChars(0, data.length, data, 0);
receiver.comment(data, 0, data.length);
node.release();
break;
case Node.CDATA_SECTION_NODE:
final String str = ((CDATASectionImpl) node).getData();
if (first) {
receiver.characters(str);
} else {
data = new char[str.length()];
str.getChars(0, str.length(), data, 0);
receiver.cdataSection(data, 0, data.length);
}
break;
}
}
use of org.exist.dom.persistent.ElementImpl in project exist by eXist-db.
the class IndexStatisticsWorker method updateDocument.
private void updateDocument(final DBBroker broker, final DocumentImpl doc) {
final ElementImpl root = (ElementImpl) doc.getDocumentElement();
final int rootLevel = root.getNodeId().getTreeLevel();
try {
final NodePath path = new NodePath();
final Deque<NodeStats> stack = new ArrayDeque<>();
final ExtendedXMLStreamReader reader = broker.getXMLStreamReader(root, false);
while (reader.hasNext()) {
final int status = reader.next();
switch(status) {
case XMLStreamReader.START_ELEMENT:
for (final NodeStats next : stack) {
next.incDepth();
}
final QName qname = reader.getQName();
path.addComponent(qname);
final NodeStats nodeStats = perDocGuide.add(path);
stack.push(nodeStats);
break;
case XMLStreamReader.END_ELEMENT:
path.removeLastComponent();
final NodeStats stats = stack.pop();
stats.updateMaxDepth();
final NodeId otherId = (NodeId) reader.getProperty(ExtendedXMLStreamReader.PROPERTY_NODE_ID);
final int otherLevel = otherId.getTreeLevel();
if (otherLevel == rootLevel) {
// exit-while
break;
}
break;
}
}
} catch (final IOException | XMLStreamException e) {
e.printStackTrace();
}
}
Aggregations