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;
}
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);
}
}
}
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());
}
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;
}
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;
}
Aggregations