use of org.sirix.page.UnorderedKeyValuePage 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.page.UnorderedKeyValuePage in project sirix by sirixdb.
the class XdmNodeWriterTrxImpl method rollingAdd.
/**
* Adapting the structure with a rolling hash for all ancestors only with insert.
*
* @throws SirixIOException if an I/O error occurs
*/
private void rollingAdd() throws SirixIOException {
// start with hash to add
final ImmutableNode startNode = mNodeReader.getCurrentNode();
final long oldDescendantCount = mNodeReader.getStructuralNode().getDescendantCount();
final long descendantCount = oldDescendantCount == 0 ? 1 : oldDescendantCount + 1;
long hashToAdd = startNode.getHash() == 0 ? mHash.hashLong(startNode.hashCode()).asLong() : startNode.getHash();
long newHash = 0;
long possibleOldHash = 0;
// go the path to the root
do {
final Node node = (Node) getPageTransaction().prepareEntryForModification(mNodeReader.getCurrentNode().getNodeKey(), PageKind.RECORDPAGE, -1, Optional.<UnorderedKeyValuePage>empty());
if (node.getNodeKey() == startNode.getNodeKey()) {
// at the beginning, take the hashcode of the node only
newHash = hashToAdd;
} else if (node.getNodeKey() == startNode.getParentKey()) {
// at the parent level, just add the node
possibleOldHash = node.getHash();
newHash = possibleOldHash + hashToAdd * PRIME;
hashToAdd = newHash;
setAddDescendants(startNode, node, descendantCount);
} else {
// at the rest, remove the existing old key for this element
// and add the new one
newHash = node.getHash() - possibleOldHash * PRIME;
newHash = newHash + hashToAdd * PRIME;
hashToAdd = newHash;
possibleOldHash = node.getHash();
setAddDescendants(startNode, node, descendantCount);
}
node.setHash(newHash);
} while (moveTo(mNodeReader.getCurrentNode().getParentKey()).hasMoved());
mNodeReader.setCurrentNode(startNode);
}
use of org.sirix.page.UnorderedKeyValuePage in project sirix by sirixdb.
the class XdmNodeWriterTrxImpl method insertAttribute.
@Override
public XdmNodeWriteTrx insertAttribute(final QNm name, final String value, final Movement move) throws SirixException {
checkNotNull(value);
if (!XMLToken.isValidQName(checkNotNull(name))) {
throw new IllegalArgumentException("The QName is not valid!");
}
acquireLock();
try {
if (getCurrentNode().getKind() == Kind.ELEMENT) {
checkAccessAndCommit();
/*
* Update value in case of the same attribute name is found but the attribute to insert has
* a different value (otherwise an exception is thrown because of a duplicate attribute
* which would otherwise be inserted!).
*/
final ElementNode element = (ElementNode) getCurrentNode();
final Optional<Long> attKey = element.getAttributeKeyByName(name);
if (attKey.isPresent()) {
moveTo(attKey.get());
final QNm qName = getName();
if (name.equals(qName)) {
if (getValue().equals(value)) {
throw new SirixUsageException("Duplicate attribute!");
} else {
setValue(value);
}
}
moveToParent();
}
// Get the path node key.
final long pathNodeKey = mNodeReader.mResourceManager.getResourceConfig().mPathSummary ? mPathSummaryWriter.getPathNodeKey(name, Kind.ATTRIBUTE) : 0;
final byte[] attValue = getBytes(value);
final Optional<SirixDeweyID> id = newAttributeID();
final long elementKey = getCurrentNode().getNodeKey();
final AttributeNode node = mNodeFactory.createAttributeNode(elementKey, name, attValue, pathNodeKey, id);
final Node parentNode = (Node) getPageTransaction().prepareEntryForModification(node.getParentKey(), PageKind.RECORDPAGE, -1, Optional.<UnorderedKeyValuePage>empty());
((ElementNode) parentNode).insertAttribute(node.getNodeKey(), node.getPrefixKey() + node.getLocalNameKey());
mNodeReader.setCurrentNode(node);
adaptHashesWithAdd();
// Index text value.
mIndexController.notifyChange(ChangeType.INSERT, node, pathNodeKey);
if (move == Movement.TOPARENT) {
moveToParent();
}
return this;
} else {
throw new SirixUsageException("Insert is not allowed if current node is not an ElementNode!");
}
} finally {
unLock();
}
}
use of org.sirix.page.UnorderedKeyValuePage in project sirix by sirixdb.
the class XdmNodeWriterTrxImpl method insertNamespace.
@Override
public XdmNodeWriteTrx insertNamespace(final QNm name, final Movement move) throws SirixException {
if (!XMLToken.isValidQName(checkNotNull(name))) {
throw new IllegalArgumentException("The QName is not valid!");
}
acquireLock();
try {
if (getCurrentNode().getKind() == Kind.ELEMENT) {
checkAccessAndCommit();
for (int i = 0, namespCount = ((ElementNode) getCurrentNode()).getNamespaceCount(); i < namespCount; i++) {
moveToNamespace(i);
final QNm qName = getName();
if (name.getPrefix().equals(qName.getPrefix())) {
throw new SirixUsageException("Duplicate namespace!");
}
moveToParent();
}
final long pathNodeKey = mBuildPathSummary ? mPathSummaryWriter.getPathNodeKey(name, Kind.NAMESPACE) : 0;
final long elementKey = getCurrentNode().getNodeKey();
final Optional<SirixDeweyID> id = newNamespaceID();
final NamespaceNode node = mNodeFactory.createNamespaceNode(elementKey, name, pathNodeKey, id);
final Node parentNode = (Node) getPageTransaction().prepareEntryForModification(node.getParentKey(), PageKind.RECORDPAGE, -1, Optional.<UnorderedKeyValuePage>empty());
((ElementNode) parentNode).insertNamespace(node.getNodeKey());
mNodeReader.setCurrentNode(node);
adaptHashesWithAdd();
if (move == Movement.TOPARENT) {
moveToParent();
}
return this;
} else {
throw new SirixUsageException("Insert is not allowed if current node is not an ElementNode!");
}
} finally {
unLock();
}
}
use of org.sirix.page.UnorderedKeyValuePage in project sirix by sirixdb.
the class XdmNodeWriterTrxImpl method remove.
@Override
public XdmNodeWriteTrx remove() throws SirixException {
checkAccessAndCommit();
acquireLock();
try {
if (getCurrentNode().getKind() == Kind.DOCUMENT) {
throw new SirixUsageException("Document root can not be removed.");
} else if (getCurrentNode() instanceof StructNode) {
final StructNode node = (StructNode) mNodeReader.getCurrentNode();
// Remove subtree.
for (final Axis axis = new PostOrderAxis(this); axis.hasNext(); ) {
axis.next();
// Remove name.
removeName();
// Remove namespaces and attributes.
removeNonStructural();
// Remove text value.
removeValue();
// Then remove node.
getPageTransaction().removeEntry(getCurrentNode().getNodeKey(), PageKind.RECORDPAGE, -1, Optional.<UnorderedKeyValuePage>empty());
}
// Adapt hashes and neighbour nodes as well as the name from the
// NamePage mapping if it's not a text node.
mNodeReader.setCurrentNode(node);
adaptHashesWithRemove();
adaptForRemove(node, PageKind.RECORDPAGE);
mNodeReader.setCurrentNode(node);
// Remove the name of subtree-root.
if (node.getKind() == Kind.ELEMENT) {
removeName();
}
// of text merges.
if (mNodeReader.hasRightSibling() && moveTo(node.getRightSiblingKey()).hasMoved()) {
} else if (node.hasLeftSibling()) {
moveTo(node.getLeftSiblingKey());
} else {
moveTo(node.getParentKey());
}
} else if (getCurrentNode().getKind() == Kind.ATTRIBUTE) {
final ImmutableNode node = mNodeReader.getCurrentNode();
final ElementNode parent = (ElementNode) getPageTransaction().prepareEntryForModification(node.getParentKey(), PageKind.RECORDPAGE, -1, Optional.<UnorderedKeyValuePage>empty());
parent.removeAttribute(node.getNodeKey());
adaptHashesWithRemove();
getPageTransaction().removeEntry(node.getNodeKey(), PageKind.RECORDPAGE, -1, Optional.<UnorderedKeyValuePage>empty());
removeName();
mIndexController.notifyChange(ChangeType.DELETE, getNode(), parent.getPathNodeKey());
moveToParent();
} else if (getCurrentNode().getKind() == Kind.NAMESPACE) {
final ImmutableNode node = mNodeReader.getCurrentNode();
final ElementNode parent = (ElementNode) getPageTransaction().prepareEntryForModification(node.getParentKey(), PageKind.RECORDPAGE, -1, Optional.<UnorderedKeyValuePage>empty());
parent.removeNamespace(node.getNodeKey());
adaptHashesWithRemove();
getPageTransaction().removeEntry(node.getNodeKey(), PageKind.RECORDPAGE, -1, Optional.<UnorderedKeyValuePage>empty());
removeName();
moveToParent();
}
return this;
} finally {
unLock();
}
}
Aggregations