use of org.sirix.node.interfaces.StructNode in project sirix by sirixdb.
the class XdmNodeWriterTrxImpl method postorderAdd.
/**
* Adapting the structure with a rolling hash for all ancestors only with insert.
*
* @throws SirixIOException if anything weird happened
*/
private void postorderAdd() throws SirixIOException {
// start with hash to add
final ImmutableNode startNode = getCurrentNode();
// long for adapting the hash of the parent
long hashCodeForParent = 0;
// adapting the parent if the current node is no structural one.
if (!(startNode instanceof StructNode)) {
final Node node = (Node) getPageTransaction().prepareEntryForModification(mNodeReader.getCurrentNode().getNodeKey(), PageKind.RECORDPAGE, -1, Optional.<UnorderedKeyValuePage>empty());
node.setHash(mHash.hashLong(mNodeReader.getCurrentNode().hashCode()).asLong());
moveTo(mNodeReader.getCurrentNode().getParentKey());
}
// Cursor to root
StructNode cursorToRoot;
do {
cursorToRoot = (StructNode) getPageTransaction().prepareEntryForModification(mNodeReader.getCurrentNode().getNodeKey(), PageKind.RECORDPAGE, -1, Optional.<UnorderedKeyValuePage>empty());
hashCodeForParent = mNodeReader.getCurrentNode().hashCode() + hashCodeForParent * PRIME;
// Caring about attributes and namespaces if node is an element.
if (cursorToRoot.getKind() == Kind.ELEMENT) {
final ElementNode currentElement = (ElementNode) cursorToRoot;
// setting the attributes and namespaces
final int attCount = ((ElementNode) cursorToRoot).getAttributeCount();
for (int i = 0; i < attCount; i++) {
moveTo(currentElement.getAttributeKey(i));
hashCodeForParent = mNodeReader.getCurrentNode().hashCode() + hashCodeForParent * PRIME;
}
final int nspCount = ((ElementNode) cursorToRoot).getNamespaceCount();
for (int i = 0; i < nspCount; i++) {
moveTo(currentElement.getNamespaceKey(i));
hashCodeForParent = mNodeReader.getCurrentNode().hashCode() + hashCodeForParent * PRIME;
}
moveTo(cursorToRoot.getNodeKey());
}
// Caring about the children of a node
if (moveTo(mNodeReader.getStructuralNode().getFirstChildKey()).hasMoved()) {
do {
hashCodeForParent = mNodeReader.getCurrentNode().getHash() + hashCodeForParent * PRIME;
} while (moveTo(mNodeReader.getStructuralNode().getRightSiblingKey()).hasMoved());
moveTo(mNodeReader.getStructuralNode().getParentKey());
}
// setting hash and resetting hash
cursorToRoot.setHash(hashCodeForParent);
hashCodeForParent = 0;
} while (moveTo(cursorToRoot.getParentKey()).hasMoved());
mNodeReader.setCurrentNode(startNode);
}
use of org.sirix.node.interfaces.StructNode in project sirix by sirixdb.
the class XdmNodeWriterTrxImpl method adaptForMove.
/**
* Adapting everything for move operations.
*
* @param fromNode root {@link StructNode} of the subtree to be moved
* @param toNode the {@link StructNode} which is the anchor of the new subtree
* @param insertPos determines if it has to be inserted as a first child or a right sibling
* @throws SirixException if removing a node fails after merging text nodes
*/
private void adaptForMove(final StructNode fromNode, final StructNode toNode, final InsertPos insertPos) throws SirixException {
assert fromNode != null;
assert toNode != null;
assert insertPos != null;
// Modify nodes where the subtree has been moved from.
// ==============================================================================
final StructNode parent = (StructNode) getPageTransaction().prepareEntryForModification(fromNode.getParentKey(), PageKind.RECORDPAGE, -1, Optional.<UnorderedKeyValuePage>empty());
switch(insertPos) {
case ASRIGHTSIBLING:
if (fromNode.getParentKey() != toNode.getParentKey()) {
parent.decrementChildCount();
}
break;
case ASFIRSTCHILD:
if (fromNode.getParentKey() != toNode.getNodeKey()) {
parent.decrementChildCount();
}
break;
case ASNONSTRUCTURAL:
// Do not decrement child count.
break;
default:
}
// Adapt first child key of former parent.
if (parent.getFirstChildKey() == fromNode.getNodeKey()) {
parent.setFirstChildKey(fromNode.getRightSiblingKey());
}
// Adapt left sibling key of former right sibling.
if (fromNode.hasRightSibling()) {
final StructNode rightSibling = (StructNode) getPageTransaction().prepareEntryForModification(fromNode.getRightSiblingKey(), PageKind.RECORDPAGE, -1, Optional.<UnorderedKeyValuePage>empty());
rightSibling.setLeftSiblingKey(fromNode.getLeftSiblingKey());
}
// Adapt right sibling key of former left sibling.
if (fromNode.hasLeftSibling()) {
final StructNode leftSibling = (StructNode) getPageTransaction().prepareEntryForModification(fromNode.getLeftSiblingKey(), PageKind.RECORDPAGE, -1, Optional.<UnorderedKeyValuePage>empty());
leftSibling.setRightSiblingKey(fromNode.getRightSiblingKey());
}
// Merge text nodes.
if (fromNode.hasLeftSibling() && fromNode.hasRightSibling()) {
moveTo(fromNode.getLeftSiblingKey());
if (getCurrentNode() != null && getCurrentNode().getKind() == Kind.TEXT) {
final StringBuilder builder = new StringBuilder(getValue());
moveTo(fromNode.getRightSiblingKey());
if (getCurrentNode() != null && getCurrentNode().getKind() == Kind.TEXT) {
builder.append(getValue());
if (fromNode.getRightSiblingKey() == toNode.getNodeKey()) {
moveTo(fromNode.getLeftSiblingKey());
if (mNodeReader.getStructuralNode().hasLeftSibling()) {
final StructNode leftSibling = (StructNode) getPageTransaction().prepareEntryForModification(mNodeReader.getStructuralNode().getLeftSiblingKey(), PageKind.RECORDPAGE, -1, Optional.<UnorderedKeyValuePage>empty());
leftSibling.setRightSiblingKey(fromNode.getRightSiblingKey());
}
final long leftSiblingKey = mNodeReader.getStructuralNode().hasLeftSibling() == true ? mNodeReader.getStructuralNode().getLeftSiblingKey() : getCurrentNode().getNodeKey();
moveTo(fromNode.getRightSiblingKey());
final StructNode rightSibling = (StructNode) getPageTransaction().prepareEntryForModification(getCurrentNode().getNodeKey(), PageKind.RECORDPAGE, -1, Optional.<UnorderedKeyValuePage>empty());
rightSibling.setLeftSiblingKey(leftSiblingKey);
moveTo(fromNode.getLeftSiblingKey());
remove();
moveTo(fromNode.getRightSiblingKey());
} else {
if (mNodeReader.getStructuralNode().hasRightSibling()) {
final StructNode rightSibling = (StructNode) getPageTransaction().prepareEntryForModification(mNodeReader.getStructuralNode().getRightSiblingKey(), PageKind.RECORDPAGE, -1, Optional.<UnorderedKeyValuePage>empty());
rightSibling.setLeftSiblingKey(fromNode.getLeftSiblingKey());
}
final long rightSiblingKey = mNodeReader.getStructuralNode().hasRightSibling() == true ? mNodeReader.getStructuralNode().getRightSiblingKey() : getCurrentNode().getNodeKey();
moveTo(fromNode.getLeftSiblingKey());
final StructNode leftSibling = (StructNode) getPageTransaction().prepareEntryForModification(getCurrentNode().getNodeKey(), PageKind.RECORDPAGE, -1, Optional.<UnorderedKeyValuePage>empty());
leftSibling.setRightSiblingKey(rightSiblingKey);
moveTo(fromNode.getRightSiblingKey());
remove();
moveTo(fromNode.getLeftSiblingKey());
}
setValue(builder.toString());
}
}
}
// Modify nodes where the subtree has been moved to.
// ==============================================================================
insertPos.processMove(fromNode, toNode, this);
}
use of org.sirix.node.interfaces.StructNode in project sirix by sirixdb.
the class XdmNodeWriterTrxImpl method insertTextAsRightSibling.
@Override
public XdmNodeWriteTrx insertTextAsRightSibling(final String value) throws SirixException {
checkNotNull(value);
acquireLock();
try {
if (getCurrentNode() instanceof StructNode && getCurrentNode().getKind() != Kind.DOCUMENT && !value.isEmpty()) {
checkAccessAndCommit();
final long parentKey = getCurrentNode().getParentKey();
final long leftSibKey = getCurrentNode().getNodeKey();
final long rightSibKey = ((StructNode) getCurrentNode()).getRightSiblingKey();
// Update value in case of adjacent text nodes.
final StringBuilder builder = new StringBuilder();
if (getCurrentNode().getKind() == Kind.TEXT) {
builder.append(getValue());
}
builder.append(value);
if (!value.equals(builder.toString())) {
setValue(builder.toString());
return this;
}
if (hasNode(rightSibKey)) {
moveTo(rightSibKey);
if (getCurrentNode().getKind() == Kind.TEXT) {
builder.append(getValue());
}
if (!value.equals(builder.toString())) {
setValue(builder.toString());
return this;
}
}
// Insert new text node if no adjacent text nodes are found.
moveTo(leftSibKey);
final byte[] textValue = getBytes(builder.toString());
final Optional<SirixDeweyID> id = newRightSiblingID();
final TextNode node = mNodeFactory.createTextNode(parentKey, leftSibKey, rightSibKey, textValue, mCompression, id);
// Adapt local nodes and hashes.
mNodeReader.setCurrentNode(node);
adaptForInsert(node, InsertPos.ASRIGHTSIBLING, PageKind.RECORDPAGE);
mNodeReader.setCurrentNode(node);
adaptHashesWithAdd();
// Get the path node key.
final long pathNodeKey = moveToParent().get().isElement() ? getNameNode().getPathNodeKey() : -1;
mNodeReader.setCurrentNode(node);
// Index text value.
mIndexController.notifyChange(ChangeType.INSERT, node, pathNodeKey);
return this;
} else {
throw new SirixUsageException("Insert is not allowed if current node is not an Element- or Text-node or value is empty!");
}
} finally {
unLock();
}
}
use of org.sirix.node.interfaces.StructNode in project sirix by sirixdb.
the class XdmNodeWriterTrxImpl method replaceWithTextNode.
/**
* Replace current node with a {@link TextNode}.
*
* @param value text value
* @return inserted node
* @throws SirixException if anything fails
*/
private ImmutableNode replaceWithTextNode(final String value) throws SirixException {
assert value != null;
final StructNode currentNode = mNodeReader.getStructuralNode();
long key = currentNode.getNodeKey();
if (currentNode.hasLeftSibling()) {
moveToLeftSibling();
key = insertTextAsRightSibling(value).getNodeKey();
} else {
moveToParent();
key = insertTextAsFirstChild(value).getNodeKey();
moveTo(key);
}
moveTo(currentNode.getNodeKey());
remove();
moveTo(key);
return mNodeReader.getCurrentNode();
}
use of org.sirix.node.interfaces.StructNode in project sirix by sirixdb.
the class XdmNodeWriterTrxImpl method postOrderTraversalHashes.
/**
* Modifying hashes in a postorder-traversal.
*
* @throws SirixIOException if an I/O error occurs
*/
private void postOrderTraversalHashes() throws SirixIOException {
new PostOrderAxis(this, IncludeSelf.YES).forEach((unused) -> {
final StructNode node = mNodeReader.getStructuralNode();
if (node.getKind() == Kind.ELEMENT) {
final ElementNode element = (ElementNode) node;
for (int i = 0, nspCount = element.getNamespaceCount(); i < nspCount; i++) {
moveToNamespace(i);
addHashAndDescendantCount();
moveToParent();
}
for (int i = 0, attCount = element.getAttributeCount(); i < attCount; i++) {
moveToAttribute(i);
addHashAndDescendantCount();
moveToParent();
}
}
addHashAndDescendantCount();
});
}
Aggregations