Search in sources :

Example 1 with DescendantAxis

use of org.sirix.axis.DescendantAxis in project sirix by sirixdb.

the class PathSummaryReader method getPCRsForPath.

/**
 * Get path class records (PCRs) for the specified path.
 *
 * @param path the path for which to get a set of PCRs
 * @return set of PCRs belonging to the specified path
 * @throws SirixException if anything went wrong
 */
public Set<Long> getPCRsForPath(final Path<QNm> path) throws PathException {
    Set<Long> pcrSet = mPathCache.get(path);
    if (pcrSet != null) {
        return pcrSet;
    }
    pcrSet = new HashSet<Long>();
    final boolean isAttributePattern = path.isAttribute();
    final int pathLength = path.getLength();
    final long nodeKey = mCurrentNode.getNodeKey();
    moveToDocumentRoot();
    for (final Axis axis = new DescendantAxis(this); axis.hasNext(); ) {
        axis.next();
        final PathNode node = this.getPathNode();
        if (node == null) {
            continue;
        }
        if (node.getLevel() < pathLength) {
            continue;
        }
        if (isAttributePattern ^ (node.getPathKind() == Kind.ATTRIBUTE)) {
            continue;
        }
        if (path.matches(node.getPath(this))) {
            pcrSet.add(node.getNodeKey());
        }
    }
    moveTo(nodeKey);
    mPathCache.put(path, pcrSet);
    return pcrSet;
}
Also used : DescendantAxis(org.sirix.axis.DescendantAxis) Axis(org.sirix.api.Axis) FilterAxis(org.sirix.axis.filter.FilterAxis) DescendantAxis(org.sirix.axis.DescendantAxis)

Example 2 with DescendantAxis

use of org.sirix.axis.DescendantAxis in project sirix by sirixdb.

the class PathSummaryWriter method adaptPathForChangedNode.

/**
 * Adapt path summary either for moves or {@code setQName(QName)}.
 *
 * @param node the node for which the path node needs to be adapted
 * @param name the new {@link QName} in case of a new one is set, the old {@link QName} otherwise
 * @param nameKey nameKey of the new node
 * @param uriKey uriKey of the new node
 * @throws SirixException if a Sirix operation fails
 * @throws NullPointerException if {@code pNode} or {@code pQName} is null
 */
public void adaptPathForChangedNode(final ImmutableNameNode node, final QNm name, final int uriKey, final int prefixKey, final int localNameKey, final OPType type) throws SirixException {
    // Possibly either reset a path node or decrement its reference counter
    // and search for the new path node or insert it.
    movePathSummary();
    final long oldPathNodeKey = mPathSummaryReader.getNodeKey();
    // reference-counter would be 0).
    if (type == OPType.SETNAME && mPathSummaryReader.getReferences() == 1) {
        moveSummaryGetLevel(node);
        // Search for new path entry.
        final Axis axis = new FilterAxis(new ChildAxis(mPathSummaryReader), new NameFilter(mPathSummaryReader, Utils.buildName(name)), new PathKindFilter(mPathSummaryReader, node.getKind()));
        if (axis.hasNext()) {
            axis.next();
            // Found node.
            processFoundPathNode(oldPathNodeKey, mPathSummaryReader.getNodeKey(), node.getNodeKey(), uriKey, prefixKey, localNameKey, Remove.YES, type);
        } else {
            if (mPathSummaryReader.getKind() != Kind.DOCUMENT) {
                /* The path summary just needs to be updated for the new renamed node. */
                mPathSummaryReader.moveTo(oldPathNodeKey);
                final PathNode pathNode = (PathNode) mPageWriteTrx.prepareEntryForModification(mPathSummaryReader.getNodeKey(), PageKind.PATHSUMMARYPAGE, 0, Optional.<UnorderedKeyValuePage>empty());
                pathNode.setPrefixKey(prefixKey);
                pathNode.setLocalNameKey(localNameKey);
                pathNode.setURIKey(uriKey);
            }
        }
    } else {
        int level = moveSummaryGetLevel(node);
        // TODO: Johannes: Optimize? (either use this or use the name-mapping,
        // depending on the number of child nodes or nodes with a certain name).
        // Search for new path entry.
        final Axis axis = new FilterAxis(new ChildAxis(mPathSummaryReader), new NameFilter(mPathSummaryReader, Utils.buildName(name)), new PathKindFilter(mPathSummaryReader, node.getKind()));
        if (type == OPType.MOVEDSAMELEVEL || axis.hasNext()) {
            if (type != OPType.MOVEDSAMELEVEL) {
                axis.next();
            }
            // Found node.
            processFoundPathNode(oldPathNodeKey, mPathSummaryReader.getNodeKey(), node.getNodeKey(), uriKey, prefixKey, localNameKey, Remove.NO, type);
        } else {
            long nodeKey = mPathSummaryReader.getNodeKey();
            // Decrement reference count or remove path summary node.
            mNodeRtx.moveTo(node.getNodeKey());
            for (final Axis descendants = new PostOrderAxis(mNodeRtx, IncludeSelf.YES); descendants.hasNext(); ) {
                descendants.next();
                deleteOrDecrement();
                if (mNodeRtx.getKind() == Kind.ELEMENT) {
                    final ElementNode element = (ElementNode) mNodeRtx.getCurrentNode();
                    // Namespaces.
                    for (int i = 0, nsps = element.getNamespaceCount(); i < nsps; i++) {
                        mNodeRtx.moveToNamespace(i);
                        deleteOrDecrement();
                        mNodeRtx.moveToParent();
                    }
                    // Attributes.
                    for (int i = 0, atts = element.getAttributeCount(); i < atts; i++) {
                        mNodeRtx.moveToAttribute(i);
                        deleteOrDecrement();
                        mNodeRtx.moveToParent();
                    }
                }
            }
            mPathSummaryReader.moveTo(nodeKey);
            // Not found => create new path nodes for the whole subtree.
            boolean firstRun = true;
            for (final Axis descendants = new DescendantAxis(mNodeRtx, IncludeSelf.YES); descendants.hasNext(); ) {
                descendants.next();
                if (mNodeRtx.getKind() == Kind.ELEMENT) {
                    // Path Summary : New mapping.
                    if (firstRun) {
                        insertPathAsFirstChild(name, Kind.ELEMENT, ++level);
                        nodeKey = mPathSummaryReader.getNodeKey();
                    } else {
                        insertPathAsFirstChild(mNodeRtx.getName(), Kind.ELEMENT, ++level);
                    }
                    resetPathNodeKey(mNodeRtx.getNodeKey());
                    // Namespaces.
                    for (int i = 0, nsps = mNodeRtx.getNamespaceCount(); i < nsps; i++) {
                        mNodeRtx.moveToNamespace(i);
                        // Path Summary : New mapping.
                        insertPathAsFirstChild(mNodeRtx.getName(), Kind.NAMESPACE, level + 1);
                        resetPathNodeKey(mNodeRtx.getNodeKey());
                        mNodeRtx.moveToParent();
                        mPathSummaryReader.moveToParent();
                    }
                    // Attributes.
                    for (int i = 0, atts = mNodeRtx.getAttributeCount(); i < atts; i++) {
                        mNodeRtx.moveToAttribute(i);
                        // Path Summary : New mapping.
                        insertPathAsFirstChild(mNodeRtx.getName(), Kind.ATTRIBUTE, level + 1);
                        resetPathNodeKey(mNodeRtx.getNodeKey());
                        mNodeRtx.moveToParent();
                        mPathSummaryReader.moveToParent();
                    }
                    if (firstRun) {
                        firstRun = false;
                    } else {
                        mPathSummaryReader.moveToParent();
                        level--;
                    }
                }
            }
            // /*
            // * Remove path nodes with zero node references.
            // *
            // * (TODO: Johannes: might not be necessary, as it's likely that future
            // * updates will reinsert the path).
            // */
            // for (final long key : nodesToDelete) {
            // if (mPathSummaryReader.moveTo(key).hasMoved()) {
            // removePathSummaryNode(Remove.NO);
            // }
            // }
            mPathSummaryReader.moveTo(nodeKey);
        }
    }
}
Also used : ChildAxis(org.sirix.axis.ChildAxis) PostOrderAxis(org.sirix.axis.PostOrderAxis) UnorderedKeyValuePage(org.sirix.page.UnorderedKeyValuePage) ElementNode(org.sirix.node.ElementNode) FilterAxis(org.sirix.axis.filter.FilterAxis) NameFilter(org.sirix.axis.filter.NameFilter) DescendantAxis(org.sirix.axis.DescendantAxis) Axis(org.sirix.api.Axis) ChildAxis(org.sirix.axis.ChildAxis) PostOrderAxis(org.sirix.axis.PostOrderAxis) FilterAxis(org.sirix.axis.filter.FilterAxis) DescendantAxis(org.sirix.axis.DescendantAxis) LevelOrderAxis(org.sirix.axis.LevelOrderAxis) PathKindFilter(org.sirix.axis.filter.PathKindFilter)

Example 3 with DescendantAxis

use of org.sirix.axis.DescendantAxis in project sirix by sirixdb.

the class PathSummaryWriter method removePathSummaryNode.

/**
 * Remove a path summary node with the specified PCR.
 *
 * @throws SirixException if Sirix fails to remove the path node
 */
private void removePathSummaryNode(final Remove remove) throws SirixException {
    // Remove all descendant nodes.
    if (remove == Remove.YES) {
        for (final Axis axis = new DescendantAxis(mPathSummaryReader); axis.hasNext(); ) {
            axis.next();
            mPathSummaryReader.removeMapping(mPathSummaryReader.getNodeKey());
            mPathSummaryReader.removeQNameMapping(mPathSummaryReader.getPathNode(), mPathSummaryReader.getName());
            mPageWriteTrx.removeEntry(mPathSummaryReader.getNodeKey(), PageKind.PATHSUMMARYPAGE, 0, Optional.<UnorderedKeyValuePage>empty());
        }
    }
    // Adapt left sibling node if there is one.
    if (mPathSummaryReader.hasLeftSibling()) {
        final StructNode leftSibling = (StructNode) mPageWriteTrx.prepareEntryForModification(mPathSummaryReader.getLeftSiblingKey(), PageKind.PATHSUMMARYPAGE, 0, Optional.<UnorderedKeyValuePage>empty());
        leftSibling.setRightSiblingKey(mPathSummaryReader.getRightSiblingKey());
    }
    // Adapt right sibling node if there is one.
    if (mPathSummaryReader.hasRightSibling()) {
        final StructNode rightSibling = (StructNode) mPageWriteTrx.prepareEntryForModification(mPathSummaryReader.getRightSiblingKey(), PageKind.PATHSUMMARYPAGE, 0, Optional.<UnorderedKeyValuePage>empty());
        rightSibling.setLeftSiblingKey(mPathSummaryReader.getLeftSiblingKey());
    }
    // Adapt parent. If node has no left sibling it is a first child.
    StructNode parent = (StructNode) mPageWriteTrx.prepareEntryForModification(mPathSummaryReader.getParentKey(), PageKind.PATHSUMMARYPAGE, 0, Optional.<UnorderedKeyValuePage>empty());
    if (!mPathSummaryReader.hasLeftSibling()) {
        parent.setFirstChildKey(mPathSummaryReader.getRightSiblingKey());
    }
    parent.decrementChildCount();
    // Remove node.
    mPathSummaryReader.removeMapping(mPathSummaryReader.getNodeKey());
    mPathSummaryReader.removeQNameMapping(mPathSummaryReader.getPathNode(), mPathSummaryReader.getName());
    mPageWriteTrx.removeEntry(mPathSummaryReader.getNodeKey(), PageKind.PATHSUMMARYPAGE, 0, Optional.<UnorderedKeyValuePage>empty());
}
Also used : UnorderedKeyValuePage(org.sirix.page.UnorderedKeyValuePage) DescendantAxis(org.sirix.axis.DescendantAxis) Axis(org.sirix.api.Axis) ChildAxis(org.sirix.axis.ChildAxis) PostOrderAxis(org.sirix.axis.PostOrderAxis) FilterAxis(org.sirix.axis.filter.FilterAxis) DescendantAxis(org.sirix.axis.DescendantAxis) LevelOrderAxis(org.sirix.axis.LevelOrderAxis) StructNode(org.sirix.node.interfaces.StructNode)

Example 4 with DescendantAxis

use of org.sirix.axis.DescendantAxis in project sirix by sirixdb.

the class ExpressionSingle method isDupOrd.

/**
 * Determines for a given string representation of an axis, whether this axis leads to duplicates
 * in the result sequence or not. Furthermore it determines the new state for the order state that
 * specifies, if the result sequence is in document order. This method is implemented according to
 * the automata in [Hidders, J., Michiels, P., "Avoiding Unnecessary Ordering Operations in
 * XPath", 2003]
 *
 * @param ax name of the current axis
 * @return true, if expression is still duplicate free
 */
public boolean isDupOrd(final Axis ax) {
    Axis axis = ax;
    while (axis instanceof FilterAxis) {
        axis = ((FilterAxis) axis).getAxis();
    }
    if (axis instanceof UnionAxis) {
        mOrd = mOrd.updateOrdUnion();
        mDup = mDup.updateUnion();
    } else if (axis instanceof ChildAxis) {
        mOrd = mOrd.updateOrdChild();
        mDup = mDup.updateDupChild();
    } else if (axis instanceof ParentAxis) {
        mOrd = mOrd.updateOrdParent();
        mDup = mDup.updateDupParent();
    } else if (axis instanceof DescendantAxis) {
        mOrd = mOrd.updateOrdDesc();
        mDup = mDup.updateDupDesc();
    } else if (axis instanceof AncestorAxis) {
        mOrd = mOrd.updateOrdAncestor();
        mDup = mDup.updateDupAncestor();
    } else if (axis instanceof FollowingAxis || axis instanceof PrecedingAxis) {
        mOrd = mOrd.updateOrdFollPre();
        mDup = mDup.updateDupFollPre();
    } else if (axis instanceof FollowingSiblingAxis || axis instanceof PrecedingSiblingAxis) {
        mOrd = mOrd.updateOrdFollPreSib();
        mDup = mDup.updateDupFollPreSib();
    }
    return !DupState.nodup;
}
Also used : ChildAxis(org.sirix.axis.ChildAxis) AncestorAxis(org.sirix.axis.AncestorAxis) FollowingSiblingAxis(org.sirix.axis.FollowingSiblingAxis) FollowingAxis(org.sirix.axis.FollowingAxis) PrecedingAxis(org.sirix.axis.PrecedingAxis) PrecedingSiblingAxis(org.sirix.axis.PrecedingSiblingAxis) ParentAxis(org.sirix.axis.ParentAxis) DescendantAxis(org.sirix.axis.DescendantAxis) AncestorAxis(org.sirix.axis.AncestorAxis) PrecedingAxis(org.sirix.axis.PrecedingAxis) Axis(org.sirix.api.Axis) NestedAxis(org.sirix.axis.NestedAxis) ChildAxis(org.sirix.axis.ChildAxis) FollowingSiblingAxis(org.sirix.axis.FollowingSiblingAxis) UnionAxis(org.sirix.service.xml.xpath.expr.UnionAxis) FollowingAxis(org.sirix.axis.FollowingAxis) FilterAxis(org.sirix.axis.filter.FilterAxis) DescendantAxis(org.sirix.axis.DescendantAxis) ParentAxis(org.sirix.axis.ParentAxis) DupFilterAxis(org.sirix.service.xml.xpath.filter.DupFilterAxis) PrecedingSiblingAxis(org.sirix.axis.PrecedingSiblingAxis) FilterAxis(org.sirix.axis.filter.FilterAxis) DupFilterAxis(org.sirix.service.xml.xpath.filter.DupFilterAxis) UnionAxis(org.sirix.service.xml.xpath.expr.UnionAxis)

Example 5 with DescendantAxis

use of org.sirix.axis.DescendantAxis in project sirix by sirixdb.

the class AbstractDiff method checkReplace.

/**
 * Check for a replace of a node.
 *
 * @param newRtx first {@link XdmNodeReadTrx} instance
 * @param oldRtx second {@link XdmNodeReadTrx} instance
 * @return true if node has been replaced, false otherwise
 */
boolean checkReplace(final XdmNodeReadTrx newRtx, final XdmNodeReadTrx oldRtx) {
    boolean replaced = false;
    if (newRtx.getNodeKey() != oldRtx.getNodeKey()) {
        final long newKey = newRtx.getNodeKey();
        boolean movedNewRtx = newRtx.moveToRightSibling().hasMoved();
        final long oldKey = oldRtx.getNodeKey();
        boolean movedOldRtx = oldRtx.moveToRightSibling().hasMoved();
        if (movedNewRtx && movedOldRtx) {
            if (newRtx.getNodeKey() == oldRtx.getNodeKey()) {
                replaced = true;
            } else {
                while (newRtx.hasRightSibling() && oldRtx.hasRightSibling()) {
                    newRtx.moveToRightSibling();
                    oldRtx.moveToRightSibling();
                    if (newRtx.getNodeKey() == oldRtx.getNodeKey()) {
                        replaced = true;
                        break;
                    }
                }
            }
        } else if (!movedNewRtx && !movedOldRtx && (mDiff == DiffType.SAME || mDiff == DiffType.SAMEHASH)) {
            movedNewRtx = newRtx.moveToParent().hasMoved();
            movedOldRtx = oldRtx.moveToParent().hasMoved();
            if (movedNewRtx && movedOldRtx && newRtx.getNodeKey() == oldRtx.getNodeKey()) {
                replaced = true;
            }
        }
        newRtx.moveTo(newKey);
        oldRtx.moveTo(oldKey);
        if (replaced) {
            final long newNodeKey = newRtx.getNodeKey();
            final long oldNodeKey = oldRtx.getNodeKey();
            final Axis oldAxis = new DescendantAxis(oldRtx, IncludeSelf.YES);
            final Axis newAxis = new DescendantAxis(newRtx, IncludeSelf.YES);
            while (oldAxis.hasNext()) {
                oldAxis.next();
                fireDiff(DiffType.REPLACEDOLD, newRtx.getNodeKey(), oldRtx.getNodeKey(), new DiffDepth(mDepth.getNewDepth(), mDepth.getOldDepth()));
                adjustDepth(oldRtx, oldNodeKey, Revision.OLD);
            }
            while (newAxis.hasNext()) {
                newAxis.next();
                fireDiff(DiffType.REPLACEDNEW, newRtx.getNodeKey(), oldRtx.getNodeKey(), new DiffDepth(mDepth.getNewDepth(), mDepth.getOldDepth()));
                adjustDepth(newRtx, newNodeKey, Revision.NEW);
            }
            newRtx.moveTo(newNodeKey);
            oldRtx.moveTo(oldNodeKey);
            mDiff = DiffType.REPLACED;
            // final IAxis oldAxis = new DescendantAxis(pOldRtx, EIncludeSelf.YES);
            // final IAxis newAxis = new DescendantAxis(pNewRtx, EIncludeSelf.YES);
            // if (pNewRtx.getDescendantCount() >= pOldRtx
            // .getDescendantCount()) {
            // while (newAxis.hasNext()) {
            // newAxis.next();
            // boolean moved = false;
            // if (oldAxis.hasNext()) {
            // oldAxis.next();
            // moved = true;
            // }
            // fireDiff(EDiff.REPLACEDNEW, pNewRtx, pOldRtx,
            // new DiffDepth(mDepth.getNewDepth(), mDepth.getOldDepth()));
            // adjustDepth(newAxis.getTransaction(), newNodeKey, ERevision.NEW);
            // if (moved) {
            // adjustDepth(oldAxis.getTransaction(), oldNodeKey, ERevision.OLD);
            // }
            // }
            // 
            // } else {
            // while (oldAxis.hasNext()) {
            // oldAxis.next();
            // boolean moved = false;
            // if (newAxis.hasNext()) {
            // newAxis.next();
            // moved = true;
            // }
            // fireDiff(EDiff.REPLACEDOLD, pNewRtx, pOldRtx,
            // new DiffDepth(mDepth.getNewDepth(), mDepth.getOldDepth()));
            // adjustDepth(oldAxis.getTransaction(), oldNodeKey, ERevision.OLD);
            // if (moved) {
            // adjustDepth(newAxis.getTransaction(), newNodeKey, ERevision.NEW);
            // }
            // }
            // }
            newRtx.moveTo(newNodeKey);
            oldRtx.moveTo(oldNodeKey);
        }
    }
    return replaced;
}
Also used : DescendantAxis(org.sirix.axis.DescendantAxis) Axis(org.sirix.api.Axis) DescendantAxis(org.sirix.axis.DescendantAxis)

Aggregations

DescendantAxis (org.sirix.axis.DescendantAxis)44 Axis (org.sirix.api.Axis)27 Test (org.junit.Test)18 XdmNodeReadTrx (org.sirix.api.XdmNodeReadTrx)17 FilterAxis (org.sirix.axis.filter.FilterAxis)16 ChildAxis (org.sirix.axis.ChildAxis)14 QNm (org.brackit.xquery.atomic.QNm)7 XdmNodeWriteTrx (org.sirix.api.XdmNodeWriteTrx)7 NonStructuralWrapperAxis (org.sirix.axis.NonStructuralWrapperAxis)7 NameFilter (org.sirix.axis.filter.NameFilter)7 NestedAxis (org.sirix.axis.NestedAxis)6 PostOrderAxis (org.sirix.axis.PostOrderAxis)6 PathSummaryReader (org.sirix.index.path.summary.PathSummaryReader)6 AbstractAxis (org.sirix.axis.AbstractAxis)5 AncestorAxis (org.sirix.axis.AncestorAxis)5 FollowingAxis (org.sirix.axis.FollowingAxis)5 FollowingSiblingAxis (org.sirix.axis.FollowingSiblingAxis)5 LevelOrderAxis (org.sirix.axis.LevelOrderAxis)5 ParentAxis (org.sirix.axis.ParentAxis)5 PrecedingAxis (org.sirix.axis.PrecedingAxis)5