use of org.sirix.axis.filter.PathKindFilter 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.filter.PathKindFilter in project sirix by sirixdb.
the class PathSummaryWriter method processFoundPathNode.
/**
* Process a found path node.
*
* @param oldPathNodeKey key of old path node
* @param newPathNodeKey key of new path node
* @param oldNodeKey key of old node
* @param uriKey key of URI
* @param prefixKey key of prefix
* @param localNameKey key of local name
* @param remove determines if a {@link PathNode} must be removed or not
* @param type type of operation
* @throws SirixException if Sirix fails to do so
*/
private void processFoundPathNode(@Nonnegative final long oldPathNodeKey, @Nonnegative final long newPathNodeKey, @Nonnegative final long oldNodeKey, final int uriKey, final int prefixKey, final int localNameKey, final Remove remove, final OPType type) throws SirixException {
final PathSummaryReader cloned = PathSummaryReader.getInstance(mPageWriteTrx, mNodeRtx.getResourceManager());
boolean moved = cloned.moveTo(oldPathNodeKey).hasMoved();
assert moved;
// Set new reference count of the root.
if (type != OPType.MOVEDSAMELEVEL) {
final PathNode currNode = (PathNode) mPageWriteTrx.prepareEntryForModification(mPathSummaryReader.getNodeKey(), PageKind.PATHSUMMARYPAGE, 0, Optional.<UnorderedKeyValuePage>empty());
currNode.setReferenceCount(currNode.getReferences() + cloned.getReferences());
currNode.setLocalNameKey(localNameKey);
currNode.setPrefixKey(prefixKey);
currNode.setURIKey(uriKey);
}
// For all old path nodes: Merge paths and adapt reference counts.
mPathSummaryReader.moveToFirstChild();
final int oldLevel = cloned.getLevel();
for (final Axis oldDescendants = new DescendantAxis(cloned); oldDescendants.hasNext(); ) {
oldDescendants.next();
// Search for new path entry.
final Axis axis = new FilterAxis(new LevelOrderAxis.Builder(mPathSummaryReader).filterLevel(cloned.getLevel() - oldLevel).includeSelf().build(), new NameFilter(mPathSummaryReader, Utils.buildName(cloned.getName())), new PathKindFilter(mPathSummaryReader, cloned.getPathKind()), new PathLevelFilter(mPathSummaryReader, cloned.getLevel()));
if (axis.hasNext()) {
axis.next();
// Set new reference count.
if (type != OPType.MOVEDSAMELEVEL) {
final PathNode currNode = (PathNode) mPageWriteTrx.prepareEntryForModification(mPathSummaryReader.getNodeKey(), PageKind.PATHSUMMARYPAGE, 0, Optional.<UnorderedKeyValuePage>empty());
currNode.setReferenceCount(currNode.getReferences() + cloned.getReferences());
}
} else {
// Insert new node.
insertPathAsFirstChild(cloned.getName(), cloned.getPathKind(), mPathSummaryReader.getLevel() + 1);
// Set new reference count.
final PathNode currNode = (PathNode) mPageWriteTrx.prepareEntryForModification(mPathSummaryReader.getNodeKey(), PageKind.PATHSUMMARYPAGE, 0, Optional.<UnorderedKeyValuePage>empty());
currNode.setReferenceCount(cloned.getReferences());
}
mPathSummaryReader.moveTo(newPathNodeKey);
}
// Set new path nodes of the changed nodes, that is set their PCR
// references.
mPathSummaryReader.moveTo(newPathNodeKey);
mNodeRtx.moveTo(oldNodeKey);
boolean first = true;
for (final Axis axis = new DescendantAxis(mNodeRtx, IncludeSelf.YES); axis.hasNext(); ) {
axis.next();
if (first && type == OPType.SETNAME) {
first = false;
} else if (mNodeRtx.getNode() instanceof ImmutableNameNode) {
cloned.moveTo(((NameNode) mNodeRtx.getCurrentNode()).getPathNodeKey());
resetPath(newPathNodeKey, cloned.getLevel());
if (mNodeRtx.getNode().getKind() == Kind.ELEMENT) {
final ElementNode element = (ElementNode) mNodeRtx.getCurrentNode();
for (int i = 0, nspCount = element.getNamespaceCount(); i < nspCount; i++) {
mNodeRtx.moveToNamespace(i);
cloned.moveTo(((NameNode) mNodeRtx.getCurrentNode()).getPathNodeKey());
resetPath(newPathNodeKey, cloned.getLevel());
mNodeRtx.moveToParent();
}
for (int i = 0, attCount = element.getAttributeCount(); i < attCount; i++) {
mNodeRtx.moveToAttribute(i);
cloned.moveTo(((NameNode) mNodeRtx.getCurrentNode()).getPathNodeKey());
resetPath(newPathNodeKey, cloned.getLevel());
mNodeRtx.moveToParent();
}
}
}
}
// Then: Remove old nodes.
if (remove == Remove.YES) {
mPathSummaryReader.moveTo(oldPathNodeKey);
removePathSummaryNode(remove);
}
}
use of org.sirix.axis.filter.PathKindFilter in project sirix by sirixdb.
the class PathSummaryWriter method resetPath.
/**
* Reset the path node key of a node.
*
* @param newPathNodeKey path node key of new path node
* @param oldLevel old level of node
* @throws SirixIOException if an I/O error occurs
*/
private void resetPath(@Nonnegative final long newPathNodeKey, @Nonnegative final int oldLevel) throws SirixIOException {
// Search for new path entry.
mPathSummaryReader.moveTo(newPathNodeKey);
final Axis filterAxis = new FilterAxis(new LevelOrderAxis.Builder(mPathSummaryReader).includeSelf().build(), new NameFilter(mPathSummaryReader, Utils.buildName(mNodeRtx.getName())), new PathKindFilter(mPathSummaryReader, mNodeRtx.getKind()), new PathLevelFilter(mPathSummaryReader, oldLevel));
if (filterAxis.hasNext()) {
filterAxis.next();
// Set new path node.
final NameNode node = (NameNode) mPageWriteTrx.prepareEntryForModification(mNodeRtx.getNodeKey(), PageKind.RECORDPAGE, -1, Optional.<UnorderedKeyValuePage>empty());
node.setPathNodeKey(mPathSummaryReader.getNodeKey());
} else {
throw new IllegalStateException();
}
}
use of org.sirix.axis.filter.PathKindFilter in project sirix by sirixdb.
the class PathSummaryWriter method getPathNodeKey.
/**
* Insert a new path node or increment the counter of an existing node and return the path node
* key.
*
* @param name the name of the path node to search for
* @param pathKind the kind of the path node to search for
* @return a path node key of the found node, or the path node key of a new inserted node
* @throws SirixException if anything went wrong
*/
public long getPathNodeKey(final QNm name, final Kind pathKind) throws SirixException {
final Kind kind = mNodeRtx.getNode().getKind();
int level = 0;
if (kind == Kind.DOCUMENT) {
mPathSummaryReader.moveTo(Fixed.DOCUMENT_NODE_KEY.getStandardProperty());
} else {
movePathSummary();
level = mPathSummaryReader.getLevel();
}
final long nodeKey = mPathSummaryReader.getNodeKey();
final Axis axis = new FilterAxis(new ChildAxis(mPathSummaryReader), new NameFilter(mPathSummaryReader, pathKind == Kind.NAMESPACE ? name.getPrefix() : Utils.buildName(name)), new PathKindFilter(mPathSummaryReader, pathKind));
long retVal = nodeKey;
if (axis.hasNext()) {
axis.next();
retVal = mPathSummaryReader.getNodeKey();
final PathNode pathNode = (PathNode) mPageWriteTrx.prepareEntryForModification(retVal, PageKind.PATHSUMMARYPAGE, 0, Optional.<UnorderedKeyValuePage>empty());
pathNode.incrementReferenceCount();
} else {
assert nodeKey == mPathSummaryReader.getNodeKey();
insertPathAsFirstChild(name, pathKind, level + 1);
retVal = mPathSummaryReader.getNodeKey();
}
return retVal;
}
Aggregations