Search in sources :

Example 1 with NodeListImpl

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;
}
Also used : Item(org.exist.xquery.value.Item) NodeValue(org.exist.xquery.value.NodeValue) NodeListImpl(org.exist.dom.NodeListImpl) SequenceIterator(org.exist.xquery.value.SequenceIterator)

Example 2 with NodeListImpl

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);
    }
}
Also used : NodeListImpl(org.exist.dom.NodeListImpl) XPathException(org.exist.xquery.XPathException) Element(org.w3c.dom.Element) Node(org.w3c.dom.Node) Text(org.w3c.dom.Text) Sequence(org.exist.xquery.value.Sequence) Attr(org.w3c.dom.Attr) SAXException(org.xml.sax.SAXException) Item(org.exist.xquery.value.Item) SequenceIterator(org.exist.xquery.value.SequenceIterator)

Example 3 with NodeListImpl

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;
}
Also used : NodeListImpl(org.exist.dom.NodeListImpl) XPathException(org.exist.xquery.XPathException) NotificationService(org.exist.storage.NotificationService) ValueSequence(org.exist.xquery.value.ValueSequence) Sequence(org.exist.xquery.value.Sequence) Txn(org.exist.storage.txn.Txn) AttrImpl(org.exist.dom.persistent.AttrImpl) EXistException(org.exist.EXistException) DocumentImpl(org.exist.dom.persistent.DocumentImpl) TextImpl(org.exist.dom.persistent.TextImpl) Item(org.exist.xquery.value.Item) ElementImpl(org.exist.dom.persistent.ElementImpl) SequenceIterator(org.exist.xquery.value.SequenceIterator) LockException(org.exist.util.LockException) ValueSequence(org.exist.xquery.value.ValueSequence) StringValue(org.exist.xquery.value.StringValue) TriggerException(org.exist.collections.triggers.TriggerException) StoredNode(org.exist.dom.persistent.StoredNode)

Example 4 with NodeListImpl

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;
}
Also used : NodeListImpl(org.exist.dom.NodeListImpl) NodeList(org.w3c.dom.NodeList) Node(org.w3c.dom.Node)

Example 5 with NodeListImpl

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;
}
Also used : NodeListImpl(org.exist.dom.NodeListImpl)

Aggregations

NodeListImpl (org.exist.dom.NodeListImpl)7 Item (org.exist.xquery.value.Item)3 SequenceIterator (org.exist.xquery.value.SequenceIterator)3 XPathException (org.exist.xquery.XPathException)2 Sequence (org.exist.xquery.value.Sequence)2 Node (org.w3c.dom.Node)2 EXistException (org.exist.EXistException)1 TriggerException (org.exist.collections.triggers.TriggerException)1 QName (org.exist.dom.QName)1 AttrImpl (org.exist.dom.persistent.AttrImpl)1 DocumentImpl (org.exist.dom.persistent.DocumentImpl)1 ElementImpl (org.exist.dom.persistent.ElementImpl)1 StoredNode (org.exist.dom.persistent.StoredNode)1 TextImpl (org.exist.dom.persistent.TextImpl)1 NotificationService (org.exist.storage.NotificationService)1 Txn (org.exist.storage.txn.Txn)1 LockException (org.exist.util.LockException)1 NodeValue (org.exist.xquery.value.NodeValue)1 StringValue (org.exist.xquery.value.StringValue)1 ValueSequence (org.exist.xquery.value.ValueSequence)1