Search in sources :

Example 1 with IndexController

use of org.exist.indexing.IndexController in project exist by eXist-db.

the class ElementImpl method setAttributeNode.

private Attr setAttributeNode(final Attr newAttr, final Function<QName, Attr> getFn) {
    final QName attrName = new QName(newAttr.getLocalName(), newAttr.getNamespaceURI(), newAttr.getPrefix(), ElementValue.ATTRIBUTE);
    final Attr existingAttr = getFn.apply(attrName);
    if (existingAttr != null) {
        if (existingAttr.equals(newAttr)) {
            return newAttr;
        }
        // update an existing attribute
        existingAttr.setValue(newAttr.getValue());
        try (final DBBroker broker = ownerDocument.getBrokerPool().getBroker();
            final Txn transaction = broker.getBrokerPool().getTransactionManager().beginTransaction()) {
            if (!(existingAttr instanceof IStoredNode)) {
                throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, "Wrong node type");
            }
            final IStoredNode<?> existing = (IStoredNode<?>) existingAttr;
            if (!existing.getNodeId().isChildOf(nodeId)) {
                throw new DOMException(DOMException.NOT_FOUND_ERR, "node " + existing.getNodeId().getParentId() + " is not a child of element " + nodeId);
            }
            // update old custom indexes
            final IndexController indexes = broker.getIndexController();
            indexes.reindex(transaction, existing, ReindexMode.STORE);
            broker.updateNode(transaction, existing, true);
            transaction.commit();
        } catch (final EXistException e) {
            LOG.error(e);
            throw new DOMException(DOMException.INVALID_ACCESS_ERR, e.getMessage());
        }
        return existingAttr;
    } else {
        try (final DBBroker broker = ownerDocument.getBrokerPool().getBroker()) {
            final AttrImpl attrib = new AttrImpl(attrName, newAttr.getValue(), broker.getBrokerPool().getSymbols());
            return (Attr) appendChild(attrib);
        } catch (final EXistException e) {
            LOG.error(e);
            throw new DOMException(DOMException.INVALID_ACCESS_ERR, e.getMessage());
        }
    }
}
Also used : QName(org.exist.dom.QName) IndexController(org.exist.indexing.IndexController) Txn(org.exist.storage.txn.Txn) EXistException(org.exist.EXistException)

Example 2 with IndexController

use of org.exist.indexing.IndexController in project exist by eXist-db.

the class ElementImpl method appendChild.

private Node appendChild(final Txn transaction, final NodeId newNodeId, final NodeImplRef last, final NodePath lastPath, final Node child, final StreamListener listener) throws DOMException {
    if (last == null || last.getNode() == null) {
        throw new DOMException(DOMException.INVALID_MODIFICATION_ERR, "invalid node");
    }
    final DocumentImpl owner = getOwnerDocument();
    try (final DBBroker broker = ownerDocument.getBrokerPool().getBroker()) {
        switch(child.getNodeType()) {
            case Node.DOCUMENT_FRAGMENT_NODE:
                appendChildren(transaction, newNodeId, null, last, lastPath, child.getChildNodes(), listener);
                // TODO: implement document fragments so
                return null;
            case Node.ELEMENT_NODE:
                // create new element
                final ElementImpl elem = new ElementImpl(new QName(child.getLocalName() == null ? child.getNodeName() : child.getLocalName(), child.getNamespaceURI(), child.getPrefix()), broker.getBrokerPool().getSymbols());
                elem.setNodeId(newNodeId);
                elem.setOwnerDocument(owner);
                final org.exist.dom.NodeListImpl ch = new org.exist.dom.NodeListImpl();
                final NamedNodeMap attribs = child.getAttributes();
                int numActualAttribs = 0;
                for (int i = 0; i < attribs.getLength(); i++) {
                    final Attr attr = (Attr) attribs.item(i);
                    if (!attr.getNodeName().startsWith(XMLConstants.XMLNS_ATTRIBUTE)) {
                        ch.add(attr);
                        numActualAttribs++;
                    } else {
                        final String xmlnsDecl = attr.getNodeName();
                        final String prefix = xmlnsDecl.length() == 5 ? XMLConstants.DEFAULT_NS_PREFIX : xmlnsDecl.substring(6);
                        elem.addNamespaceMapping(prefix, attr.getNodeValue());
                    }
                }
                final NodeList cl = child.getChildNodes();
                for (int i = 0; i < cl.getLength(); i++) {
                    final Node n = cl.item(i);
                    ch.add(n);
                }
                elem.setChildCount(ch.getLength());
                if (numActualAttribs != (short) numActualAttribs) {
                    throw new DOMException(DOMException.INVALID_MODIFICATION_ERR, "Too many attributes");
                }
                elem.setAttributes((short) numActualAttribs);
                lastPath.addComponent(elem.getQName());
                // insert the node
                broker.insertNodeAfter(transaction, last.getNode(), elem);
                broker.indexNode(transaction, elem, lastPath);
                final IndexController indexes = broker.getIndexController();
                indexes.startIndexDocument(transaction, listener);
                try {
                    indexes.indexNode(transaction, elem, lastPath, listener);
                    elem.setChildCount(0);
                    last.setNode(elem);
                    // process child nodes
                    elem.appendChildren(transaction, newNodeId.newChild(), null, last, lastPath, ch, listener);
                    broker.endElement(elem, lastPath, null);
                    indexes.endElement(transaction, elem, lastPath, listener);
                } finally {
                    indexes.endIndexDocument(transaction, listener);
                }
                lastPath.removeLastComponent();
                return elem;
            case Node.TEXT_NODE:
                final TextImpl text = new TextImpl(newNodeId, ((Text) child).getData());
                text.setOwnerDocument(owner);
                // insert the node
                broker.insertNodeAfter(transaction, last.getNode(), text);
                broker.indexNode(transaction, text, lastPath);
                broker.getIndexController().indexNode(transaction, text, lastPath, listener);
                last.setNode(text);
                return text;
            case Node.CDATA_SECTION_NODE:
                final CDATASectionImpl cdata = new CDATASectionImpl(newNodeId, ((CDATASection) child).getData());
                cdata.setOwnerDocument(owner);
                // insert the node
                broker.insertNodeAfter(transaction, last.getNode(), cdata);
                broker.indexNode(transaction, cdata, lastPath);
                last.setNode(cdata);
                return cdata;
            case Node.ATTRIBUTE_NODE:
                final Attr attr = (Attr) child;
                final String ns = attr.getNamespaceURI();
                final String prefix = (Namespaces.XML_NS.equals(ns) ? XMLConstants.XML_NS_PREFIX : attr.getPrefix());
                String name = attr.getLocalName();
                if (name == null) {
                    name = attr.getName();
                }
                final QName attrName = new QName(name, ns, prefix);
                final AttrImpl attrib = new AttrImpl(attrName, attr.getValue(), broker.getBrokerPool().getSymbols());
                attrib.setNodeId(newNodeId);
                attrib.setOwnerDocument(owner);
                if (ns != null && attrName.compareTo(Namespaces.XML_ID_QNAME) == Constants.EQUAL) {
                    // an xml:id attribute. Normalize the attribute and set its type to ID
                    attrib.setValue(StringValue.trimWhitespace(StringValue.collapseWhitespace(attrib.getValue())));
                    attrib.setType(AttrImpl.ID);
                } else {
                    attrib.setQName(new QName(attrib.getQName(), ElementValue.ATTRIBUTE));
                }
                broker.insertNodeAfter(transaction, last.getNode(), attrib);
                broker.indexNode(transaction, attrib, lastPath);
                broker.getIndexController().indexNode(transaction, attrib, lastPath, listener);
                last.setNode(attrib);
                return attrib;
            case Node.COMMENT_NODE:
                final CommentImpl comment = new CommentImpl(((Comment) child).getData());
                comment.setNodeId(newNodeId);
                comment.setOwnerDocument(owner);
                // insert the node
                broker.insertNodeAfter(transaction, last.getNode(), comment);
                broker.indexNode(transaction, comment, lastPath);
                last.setNode(comment);
                return comment;
            case Node.PROCESSING_INSTRUCTION_NODE:
                final ProcessingInstructionImpl pi = new ProcessingInstructionImpl(newNodeId, ((ProcessingInstruction) child).getTarget(), ((ProcessingInstruction) child).getData());
                pi.setOwnerDocument(owner);
                // insert the node
                broker.insertNodeAfter(transaction, last.getNode(), pi);
                broker.indexNode(transaction, pi, lastPath);
                last.setNode(pi);
                return pi;
            default:
                throw new DOMException(DOMException.INVALID_MODIFICATION_ERR, "Unknown node type: " + child.getNodeType() + " " + child.getNodeName());
        }
    } catch (final EXistException e) {
        LOG.warn("Exception while appending node: {}", e.getMessage(), e);
    }
    return null;
}
Also used : org.w3c.dom(org.w3c.dom) QName(org.exist.dom.QName) IndexController(org.exist.indexing.IndexController) EXistException(org.exist.EXistException)

Example 3 with IndexController

use of org.exist.indexing.IndexController in project exist by eXist-db.

the class ElementImpl method appendChildren.

@Override
public void appendChildren(final Txn transaction, NodeList nodes, final int child) throws DOMException {
    // attributes are handled differently. Call checkForAttributes to extract them.
    nodes = checkForAttributes(transaction, nodes);
    if (nodes == null || nodes.getLength() == 0) {
        return;
    }
    try (final DBBroker broker = ownerDocument.getBrokerPool().getBroker()) {
        final NodePath path = getPath();
        StreamListener listener = null;
        final IndexController indexes = broker.getIndexController();
        // May help getReindexRoot() to make some useful things
        indexes.setDocument(ownerDocument);
        final IStoredNode reindexRoot = indexes.getReindexRoot(this, path, true, true);
        indexes.setMode(ReindexMode.STORE);
        // only reindex if reindexRoot is an ancestor of the current node
        if (reindexRoot == null) {
            listener = indexes.getStreamListener();
        }
        if (children == 0) {
            // no children: append a new child
            appendChildren(transaction, nodeId.newChild(), null, new NodeImplRef(this), path, nodes, listener);
        } else {
            if (child == 1) {
                final Node firstChild = getFirstChild();
                insertBefore(transaction, nodes, firstChild);
            } else {
                if (child > 1 && child <= children) {
                    final NodeList cl = getAttrsAndChildNodes();
                    final IStoredNode<?> last = (IStoredNode<?>) cl.item(child - 2);
                    insertAfter(transaction, nodes, last);
                } else {
                    final IStoredNode<?> last = (IStoredNode<?>) getLastChild(true);
                    appendChildren(transaction, last.getNodeId().nextSibling(), null, new NodeImplRef(getLastNode(last)), path, nodes, listener);
                }
            }
        }
        broker.updateNode(transaction, this, false);
        indexes.reindex(transaction, reindexRoot, ReindexMode.STORE);
        broker.flush();
    } catch (final EXistException e) {
        LOG.warn("Exception while appending child node: {}", e.getMessage(), e);
    }
}
Also used : IndexController(org.exist.indexing.IndexController) EXistException(org.exist.EXistException) StreamListener(org.exist.indexing.StreamListener)

Example 4 with IndexController

use of org.exist.indexing.IndexController in project exist by eXist-db.

the class ElementImpl method replaceChild.

/**
 * Replaces the oldNode with the newChild
 *
 * @param transaction the transaction
 * @param newChild to replace oldChild
 * @param oldChild to be replace by newChild
 * @return The new node (this differs from the {@link org.w3c.dom.Node#replaceChild(Node, Node)} specification)
 * @throws DOMException in case of a DOM error
 * @see org.w3c.dom.Node#replaceChild(org.w3c.dom.Node, org.w3c.dom.Node)
 */
@Override
public Node replaceChild(final Txn transaction, final Node newChild, final Node oldChild) throws DOMException {
    if (!(oldChild instanceof IStoredNode)) {
        throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, "Wrong node type");
    }
    final IStoredNode<?> oldNode = (IStoredNode<?>) oldChild;
    if (!oldNode.getNodeId().getParentId().equals(nodeId)) {
        throw new DOMException(DOMException.NOT_FOUND_ERR, "Node is not a child of this element");
    }
    final NodePath thisPath = getPath();
    IStoredNode<?> previous = (IStoredNode<?>) oldNode.getPreviousSibling();
    if (previous == null) {
        previous = this;
    } else {
        previous = getLastNode(previous);
    }
    final NodePath oldPath = oldNode.getPath();
    StreamListener listener = null;
    Node newNode = null;
    try (final DBBroker broker = ownerDocument.getBrokerPool().getBroker()) {
        final IndexController indexes = broker.getIndexController();
        // May help getReindexRoot() to make some useful things
        indexes.setDocument(ownerDocument);
        final IStoredNode reindexRoot = broker.getIndexController().getReindexRoot(oldNode, oldPath, false);
        indexes.setMode(ReindexMode.REMOVE_SOME_NODES);
        if (reindexRoot == null) {
            listener = indexes.getStreamListener();
        } else {
            indexes.reindex(transaction, reindexRoot, ReindexMode.REMOVE_SOME_NODES);
        }
        broker.removeAllNodes(transaction, oldNode, oldPath, listener);
        broker.endRemove(transaction);
        broker.flush();
        indexes.setMode(ReindexMode.STORE);
        listener = indexes.getStreamListener();
        newNode = appendChild(transaction, oldNode.getNodeId(), new NodeImplRef(previous), thisPath, newChild, listener);
        // Reindex if required
        broker.storeXMLResource(transaction, getOwnerDocument());
        broker.updateNode(transaction, this, false);
        indexes.reindex(transaction, reindexRoot, ReindexMode.STORE);
        broker.flush();
    } catch (final EXistException e) {
        LOG.warn("Exception while inserting node: {}", e.getMessage(), e);
    }
    // returning the newNode is more sensible than returning the oldNode
    return newNode;
}
Also used : IndexController(org.exist.indexing.IndexController) EXistException(org.exist.EXistException) StreamListener(org.exist.indexing.StreamListener)

Example 5 with IndexController

use of org.exist.indexing.IndexController in project exist by eXist-db.

the class ElementImpl method setAttribute.

private void setAttribute(final QName attrName, final String value, final Function<QName, Attr> getFn) {
    final Attr existingAttr = getFn.apply(attrName);
    if (existingAttr != null) {
        // update an existing attribute
        existingAttr.setValue(value);
        try (final DBBroker broker = ownerDocument.getBrokerPool().getBroker();
            final Txn transaction = broker.getBrokerPool().getTransactionManager().beginTransaction()) {
            if (!(existingAttr instanceof IStoredNode)) {
                throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, "Wrong node type");
            }
            final IStoredNode<?> existing = (IStoredNode<?>) existingAttr;
            if (!existing.getNodeId().isChildOf(nodeId)) {
                throw new DOMException(DOMException.NOT_FOUND_ERR, "node " + existing.getNodeId().getParentId() + " is not a child of element " + nodeId);
            }
            // update old custom indexes
            final IndexController indexes = broker.getIndexController();
            indexes.reindex(transaction, existing, ReindexMode.STORE);
            broker.updateNode(transaction, existing, true);
            transaction.commit();
        } catch (final EXistException e) {
            LOG.error(e);
            throw new DOMException(DOMException.INVALID_ACCESS_ERR, e.getMessage());
        }
    } else {
        try (final DBBroker broker = ownerDocument.getBrokerPool().getBroker()) {
            final AttrImpl attrib = new AttrImpl(attrName, value, broker.getBrokerPool().getSymbols());
            appendChild(attrib);
        } catch (final EXistException e) {
            LOG.error(e);
            throw new DOMException(DOMException.INVALID_ACCESS_ERR, e.getMessage());
        }
    }
}
Also used : IndexController(org.exist.indexing.IndexController) Txn(org.exist.storage.txn.Txn) EXistException(org.exist.EXistException)

Aggregations

IndexController (org.exist.indexing.IndexController)17 EXistException (org.exist.EXistException)12 StreamListener (org.exist.indexing.StreamListener)9 NodeId (org.exist.numbering.NodeId)4 MatchListener (org.exist.indexing.MatchListener)3 Txn (org.exist.storage.txn.Txn)3 QName (org.exist.dom.QName)2 Receiver (org.exist.util.serializer.Receiver)2 SAXResult (javax.xml.transform.sax.SAXResult)1 PermissionDeniedException (org.exist.security.PermissionDeniedException)1 ReceiverToSAX (org.exist.util.serializer.ReceiverToSAX)1 SAXSerializer (org.exist.util.serializer.SAXSerializer)1 XmldbURI (org.exist.xmldb.XmldbURI)1 org.w3c.dom (org.w3c.dom)1