use of org.exist.dom.NodeListImpl in project exist by eXist-db.
the class Insert method seq2nodeList.
private NodeList seq2nodeList(Sequence contentSeq) throws XPathException {
final NodeListImpl nl = new NodeListImpl();
for (final SequenceIterator i = contentSeq.iterate(); i.hasNext(); ) {
final Item item = i.nextItem();
if (Type.subTypeOf(item.getType(), Type.NODE)) {
final NodeValue val = (NodeValue) item;
nl.add(val.getNode());
}
}
return nl;
}
use of org.exist.dom.NodeListImpl in project exist by eXist-db.
the class XUpdateProcessor method startElement.
@Override
public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
// save accumulated character content
if (inModification && charBuf.length() > 0) {
// String normalized = charBuf.toString();
final String normalized = preserveWhitespace ? charBuf.toString() : charBuf.toString().trim();
if (!normalized.isEmpty()) {
final Text text = doc.createTextNode(charBuf.toString());
final Element last = stack.peek();
if (last == null) {
// LOG.debug("appending text to fragment: " + text.getData());
contents.add(text);
} else {
last.appendChild(text);
}
}
charBuf.setLength(0);
}
if (namespaceURI.equals(XUPDATE_NS)) {
String select = null;
switch(localName) {
case MODIFICATIONS:
startModifications(atts);
return;
case VARIABLE:
// variable declaration
startVariableDecl(atts);
return;
case IF:
if (inModification) {
throw new SAXException("xupdate:if is not allowed inside a modification");
}
select = atts.getValue("test");
final Conditional cond = new Conditional(broker, documentSet, select, namespaces, variables);
conditionals.push(cond);
return;
case VALUE_OF:
if (!inModification) {
throw new SAXException("xupdate:value-of is not allowed outside a modification");
}
break;
case APPEND:
case INSERT_BEFORE:
case INSERT_AFTER:
case REMOVE:
case RENAME:
case UPDATE:
case REPLACE:
if (inModification) {
throw new SAXException("nested modifications are not allowed");
}
select = atts.getValue("select");
if (select == null) {
throw new SAXException(localName + " requires a select attribute");
}
doc = builder.newDocument();
contents = new NodeListImpl();
inModification = true;
break;
case ELEMENT:
case ATTRIBUTE:
case TEXT:
case PROCESSING_INSTRUCTION:
case COMMENT:
if (!inModification) {
throw new SAXException("creation elements are only allowed inside " + "a modification");
}
charBuf.setLength(0);
break;
default:
throw new SAXException("Unknown XUpdate element: " + qName);
}
// start a new modification section
switch(localName) {
case APPEND:
final String child = atts.getValue("child");
modification = new Append(broker, documentSet, select, child, namespaces, variables);
break;
case UPDATE:
modification = new Update(broker, documentSet, select, namespaces, variables);
break;
case INSERT_BEFORE:
modification = new Insert(broker, documentSet, select, Insert.INSERT_BEFORE, namespaces, variables);
break;
case INSERT_AFTER:
modification = new Insert(broker, documentSet, select, Insert.INSERT_AFTER, namespaces, variables);
break;
case REMOVE:
modification = new Remove(broker, documentSet, select, namespaces, variables);
break;
case RENAME:
modification = new Rename(broker, documentSet, select, namespaces, variables);
break;
case REPLACE:
modification = new Replace(broker, documentSet, select, namespaces, variables);
break;
// process commands for node creation
case ELEMENT:
{
String name = atts.getValue("name");
if (name == null) {
throw new SAXException("element requires a name attribute");
}
final int p = name.indexOf(':');
String namespace = null;
String prefix = "";
if (p != Constants.STRING_NOT_FOUND) {
prefix = name.substring(0, p);
if (name.length() == p + 1) {
throw new SAXException("illegal prefix in qname: " + name);
}
name = name.substring(p + 1);
namespace = atts.getValue("namespace");
if (namespace == null) {
namespace = namespaces.get(prefix);
}
if (namespace == null) {
throw new SAXException("no namespace defined for prefix " + prefix);
}
}
Element elem;
if (namespace != null && !namespace.isEmpty()) {
elem = doc.createElementNS(namespace, name);
elem.setPrefix(prefix);
} else {
elem = doc.createElement(name);
}
final Element last = stack.peek();
if (last == null) {
contents.add(elem);
} else {
last.appendChild(elem);
}
stack.push(elem);
this.setWhitespaceHandling(elem);
break;
}
case ATTRIBUTE:
{
final String name = atts.getValue("name");
if (name == null) {
throw new SAXException("attribute requires a name attribute");
}
final int p = name.indexOf(':');
String namespace = null;
if (p != Constants.STRING_NOT_FOUND) {
final String prefix = name.substring(0, p);
if (name.length() == p + 1) {
throw new SAXException("illegal prefix in qname: " + name);
}
namespace = atts.getValue("namespace");
if (namespace == null) {
namespace = namespaces.get(prefix);
}
if (namespace == null) {
throw new SAXException("no namespace defined for prefix " + prefix);
}
}
Attr attrib = namespace != null && !namespace.isEmpty() ? doc.createAttributeNS(namespace, name) : doc.createAttribute(name);
if (stack.isEmpty()) {
for (int i = 0; i < contents.getLength(); i++) {
final Node n = contents.item(i);
String ns = n.getNamespaceURI();
final String nname = ns == null ? n.getNodeName() : n.getLocalName();
if (ns == null) {
ns = XMLConstants.NULL_NS_URI;
}
// check for duplicate attributes
if (n.getNodeType() == Node.ATTRIBUTE_NODE && nname.equals(name) && ns.equals(namespace)) {
throw new SAXException("The attribute " + attrib.getNodeName() + " cannot be specified twice");
}
}
contents.add(attrib);
} else {
final Element last = stack.peek();
if (namespace != null && last.hasAttributeNS(namespace, name) || namespace == null && last.hasAttribute(name)) {
throw new SAXException("The attribute " + attrib.getNodeName() + " cannot be specified " + "twice on the same element");
}
if (namespace != null) {
last.setAttributeNodeNS(attrib);
} else {
last.setAttributeNode(attrib);
}
}
inAttribute = true;
currentNode = attrib;
// process value-of
break;
}
case VALUE_OF:
select = atts.getValue("select");
if (select == null) {
throw new SAXException("value-of requires a select attribute");
}
final Sequence seq = processQuery(select);
if (LOG.isDebugEnabled()) {
LOG.debug("Found {} items for value-of", seq.getItemCount());
}
Item item;
try {
for (final SequenceIterator i = seq.iterate(); i.hasNext(); ) {
item = i.nextItem();
if (Type.subTypeOf(item.getType(), Type.NODE)) {
final Node node = NodeSetHelper.copyNode(doc, ((NodeValue) item).getNode());
final Element last = stack.peek();
if (last == null) {
contents.add(node);
} else {
last.appendChild(node);
}
} else {
final String value = item.getStringValue();
characters(value.toCharArray(), 0, value.length());
}
}
} catch (final XPathException e) {
throw new SAXException(e.getMessage(), e);
}
break;
}
} else if (inModification) {
final Element elem = namespaceURI != null && !namespaceURI.isEmpty() ? doc.createElementNS(namespaceURI, qName) : doc.createElement(qName);
Attr a;
for (int i = 0; i < atts.getLength(); i++) {
final String name = atts.getQName(i);
final String nsURI = atts.getURI(i);
if (name.startsWith("xmlns")) {
// Why are these showing up? They are supposed to be stripped out?
} else {
a = nsURI != null ? doc.createAttributeNS(nsURI, name) : doc.createAttribute(name);
a.setValue(atts.getValue(i));
if (nsURI != null) {
elem.setAttributeNodeNS(a);
} else {
elem.setAttributeNode(a);
}
}
}
final Element last = stack.peek();
if (last == null) {
contents.add(elem);
} else {
last.appendChild(elem);
}
stack.push(elem);
this.setWhitespaceHandling(elem);
}
}
use of org.exist.dom.NodeListImpl 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.NodeListImpl in project exist by eXist-db.
the class RangeIndexConfig method getFieldsAndConditions.
private NodeList getFieldsAndConditions(Element root) {
NodeListImpl fields = new NodeListImpl();
NodeList children = root.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node node = children.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE && (FIELD_ELEM.equals(node.getLocalName()) || CONDITION_ELEM.equals(node.getLocalName()))) {
fields.add(node);
}
}
return fields;
}
use of org.exist.dom.NodeListImpl in project exist by eXist-db.
the class DocumentImpl method getChildNodes.
@Override
public NodeList getChildNodes() {
if (size == 1) {
return new NodeListImpl(0);
}
// most likely a single element!
final NodeListImpl children = new NodeListImpl(1);
int nextChildNodeNum = 1;
while (nextChildNodeNum > 0) {
final NodeImpl child = getNode(nextChildNodeNum);
children.add(child);
nextChildNodeNum = next[nextChildNodeNum];
}
return children;
}
Aggregations