use of org.sirix.node.interfaces.Node in project sirix by sirixdb.
the class XdmNodeWriterTrxImpl method moveSubtreeToFirstChild.
@Override
public XdmNodeWriteTrx moveSubtreeToFirstChild(@Nonnegative final long fromKey) throws SirixException, IllegalArgumentException {
acquireLock();
try {
Preconditions.checkArgument(fromKey >= 0 && fromKey <= getMaxNodeKey(), "Argument must be a valid node key!");
Preconditions.checkArgument(fromKey != getCurrentNode().getNodeKey(), "Can't move itself to right sibling of itself!");
@SuppressWarnings("unchecked") final Optional<? extends Node> node = (Optional<? extends Node>) getPageTransaction().getRecord(fromKey, PageKind.RECORDPAGE, -1);
if (!node.isPresent()) {
throw new IllegalStateException("Node to move must exist!");
}
final Node nodeToMove = node.get();
if (nodeToMove instanceof StructNode && getCurrentNode().getKind() == Kind.ELEMENT) {
// Safe to cast (because IStructNode is a subtype of INode).
checkAncestors(nodeToMove);
checkAccessAndCommit();
final ElementNode nodeAnchor = (ElementNode) getCurrentNode();
// Check that it's not already the first child.
if (nodeAnchor.getFirstChildKey() != nodeToMove.getNodeKey()) {
final StructNode toMove = (StructNode) nodeToMove;
// Adapt index-structures (before move).
adaptSubtreeForMove(toMove, ChangeType.DELETE);
// Adapt hashes.
adaptHashesForMove(toMove);
// Adapt pointers and merge sibling text nodes.
adaptForMove(toMove, nodeAnchor, InsertPos.ASFIRSTCHILD);
mNodeReader.moveTo(toMove.getNodeKey());
adaptHashesWithAdd();
// Adapt path summary.
if (mBuildPathSummary && toMove instanceof NameNode) {
final NameNode moved = (NameNode) toMove;
mPathSummaryWriter.adaptPathForChangedNode(moved, getName(), moved.getURIKey(), moved.getPrefixKey(), moved.getLocalNameKey(), OPType.MOVED);
}
// Adapt index-structures (after move).
adaptSubtreeForMove(toMove, ChangeType.INSERT);
// Compute and assign new DeweyIDs.
if (mDeweyIDsStored) {
computeNewDeweyIDs();
}
}
return this;
} else {
throw new SirixUsageException("Move is not allowed if moved node is not an ElementNode and the node isn't inserted at an element node!");
}
} finally {
unLock();
}
}
use of org.sirix.node.interfaces.Node in project sirix by sirixdb.
the class XdmNodeWriterTrxImpl method computeNewDeweyIDs.
/**
* Compute the new DeweyIDs.
*
* @throws SirixException if anything went wrong
*/
private void computeNewDeweyIDs() throws SirixException {
SirixDeweyID id = null;
if (hasLeftSibling() && hasRightSibling()) {
id = SirixDeweyID.newBetween(getLeftSiblingDeweyID().get(), getRightSiblingDeweyID().get());
} else if (hasLeftSibling()) {
id = SirixDeweyID.newBetween(getLeftSiblingDeweyID().get(), null);
} else if (hasRightSibling()) {
id = SirixDeweyID.newBetween(null, getRightSiblingDeweyID().get());
} else {
id = mNodeReader.getParentDeweyID().get().getNewChildID();
}
assert id != null;
final long nodeKey = mNodeReader.getCurrentNode().getNodeKey();
final StructNode root = (StructNode) getPageTransaction().prepareEntryForModification(nodeKey, PageKind.RECORDPAGE, -1, Optional.<UnorderedKeyValuePage>empty());
root.setDeweyID(Optional.of(id));
if (root.hasFirstChild()) {
final Node firstChild = (Node) getPageTransaction().prepareEntryForModification(root.getFirstChildKey(), PageKind.RECORDPAGE, -1, Optional.<UnorderedKeyValuePage>empty());
firstChild.setDeweyID(Optional.of(id.getNewChildID()));
int previousLevel = getDeweyID().get().getLevel();
mNodeReader.moveTo(firstChild.getNodeKey());
int attributeNr = 0;
int nspNr = 0;
for (@SuppressWarnings("unused") final long key : LevelOrderAxis.newBuilder(this).includeNonStructuralNodes().build()) {
Optional<SirixDeweyID> deweyID = Optional.<SirixDeweyID>empty();
if (isAttribute()) {
final long attNodeKey = mNodeReader.getNodeKey();
if (attributeNr == 0) {
deweyID = Optional.of(mNodeReader.getParentDeweyID().get().getNewAttributeID());
} else {
mNodeReader.moveTo(attributeNr - 1);
deweyID = Optional.of(SirixDeweyID.newBetween(mNodeReader.getNode().getDeweyID().get(), null));
}
mNodeReader.moveTo(attNodeKey);
attributeNr++;
} else if (isNamespace()) {
final long nspNodeKey = mNodeReader.getNodeKey();
if (nspNr == 0) {
deweyID = Optional.of(mNodeReader.getParentDeweyID().get().getNewNamespaceID());
} else {
mNodeReader.moveTo(nspNr - 1);
deweyID = Optional.of(SirixDeweyID.newBetween(mNodeReader.getNode().getDeweyID().get(), null));
}
mNodeReader.moveTo(nspNodeKey);
nspNr++;
} else {
attributeNr = 0;
nspNr = 0;
if (previousLevel + 1 == getDeweyID().get().getLevel()) {
if (mNodeReader.hasLeftSibling()) {
deweyID = Optional.of(SirixDeweyID.newBetween(getLeftSiblingDeweyID().get(), null));
} else {
deweyID = Optional.of(getParentDeweyID().get().getNewChildID());
}
} else {
previousLevel++;
deweyID = Optional.of(getParentDeweyID().get().getNewChildID());
}
}
final Node node = (Node) getPageTransaction().prepareEntryForModification(mNodeReader.getCurrentNode().getNodeKey(), PageKind.RECORDPAGE, -1, Optional.<UnorderedKeyValuePage>empty());
node.setDeweyID(deweyID);
}
mNodeReader.moveTo(nodeKey);
}
}
use of org.sirix.node.interfaces.Node in project sirix by sirixdb.
the class XdmNodeWriterTrxImpl method rollingRemove.
/**
* Adapting the structure with a rolling hash for all ancestors only with remove.
*
* @throws SirixIOException if anything weird happened
*/
private void rollingRemove() throws SirixIOException {
final ImmutableNode startNode = getCurrentNode();
long hashToRemove = startNode.getHash();
long hashToAdd = 0;
long newHash = 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()) {
// the begin node is always null
newHash = 0;
} else if (node.getNodeKey() == startNode.getParentKey()) {
// the parent node is just removed
newHash = node.getHash() - hashToRemove * PRIME;
hashToRemove = node.getHash();
setRemoveDescendants(startNode);
} else {
// the ancestors are all touched regarding the modification
newHash = node.getHash() - hashToRemove * PRIME;
newHash = newHash + hashToAdd * PRIME;
hashToRemove = node.getHash();
setRemoveDescendants(startNode);
}
node.setHash(newHash);
hashToAdd = newHash;
} while (moveTo(mNodeReader.getCurrentNode().getParentKey()).hasMoved());
mNodeReader.setCurrentNode(startNode);
}
use of org.sirix.node.interfaces.Node in project sirix by sirixdb.
the class XdmNodeWriterTrxImpl method moveSubtreeToRightSibling.
@Override
public XdmNodeWriteTrx moveSubtreeToRightSibling(@Nonnegative final long fromKey) throws SirixException {
acquireLock();
try {
if (fromKey < 0 || fromKey > getMaxNodeKey()) {
throw new IllegalArgumentException("Argument must be a valid node key!");
}
if (fromKey == getCurrentNode().getNodeKey()) {
throw new IllegalArgumentException("Can't move itself to first child of itself!");
}
// Save: Every node in the "usual" node page is of type Node.
@SuppressWarnings("unchecked") final Optional<? extends Node> node = (Optional<? extends Node>) getPageTransaction().getRecord(fromKey, PageKind.RECORDPAGE, -1);
if (!node.isPresent()) {
throw new IllegalStateException("Node to move must exist!");
}
final Node nodeToMove = node.get();
if (nodeToMove instanceof StructNode && getCurrentNode() instanceof StructNode) {
final StructNode toMove = (StructNode) nodeToMove;
checkAncestors(toMove);
checkAccessAndCommit();
final StructNode nodeAnchor = (StructNode) getCurrentNode();
if (nodeAnchor.getRightSiblingKey() != nodeToMove.getNodeKey()) {
final long parentKey = toMove.getParentKey();
// Adapt hashes.
adaptHashesForMove(toMove);
// Adapt pointers and merge sibling text nodes.
adaptForMove(toMove, nodeAnchor, InsertPos.ASRIGHTSIBLING);
mNodeReader.moveTo(toMove.getNodeKey());
adaptHashesWithAdd();
// Adapt path summary.
if (mBuildPathSummary && toMove instanceof NameNode) {
final NameNode moved = (NameNode) toMove;
final OPType type = moved.getParentKey() == parentKey ? OPType.MOVEDSAMELEVEL : OPType.MOVED;
mPathSummaryWriter.adaptPathForChangedNode(moved, getName(), moved.getURIKey(), moved.getPrefixKey(), moved.getLocalNameKey(), type);
}
// Recompute DeweyIDs if they are used.
if (mDeweyIDsStored) {
computeNewDeweyIDs();
}
}
return this;
} else {
throw new SirixUsageException("Move is not allowed if moved node is not an ElementNode or TextNode and the node isn't inserted at an ElementNode or TextNode!");
}
} finally {
unLock();
}
}
use of org.sirix.node.interfaces.Node in project sirix by sirixdb.
the class XdmResourceManager method beginNodeReadTrx.
@Override
public synchronized XdmNodeReadTrx beginNodeReadTrx(@Nonnegative final int revisionKey) {
assertAccess(revisionKey);
// Make sure not to exceed available number of read transactions.
try {
if (!mReadSemaphore.tryAcquire(20, TimeUnit.SECONDS)) {
throw new SirixUsageException("No read transactions available, please close at least one read transaction at first!");
}
} catch (final InterruptedException e) {
throw new SirixThreadedException(e);
}
final PageReadTrx pageReadTrx = beginPageReadTrx(revisionKey);
final Node documentNode = getDocumentNode(pageReadTrx);
// Create new reader.
final XdmNodeReadTrx reader = new XdmNodeReadTrxImpl(this, mNodeTrxIDCounter.incrementAndGet(), pageReadTrx, documentNode);
// Remember reader for debugging and safe close.
if (mNodeReaderMap.put(reader.getId(), reader) != null) {
throw new SirixUsageException("ID generation is bogus because of duplicate ID.");
}
return reader;
}
Aggregations