use of org.sirix.node.ElementNode 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.node.ElementNode in project sirix by sirixdb.
the class NodePageTest method testSerializeDeserialize.
@Test
public void testSerializeDeserialize() throws IOException {
final UnorderedKeyValuePage page1 = new UnorderedKeyValuePage(0L, PageKind.RECORDPAGE, Constants.NULL_ID_LONG, mPageReadTrx);
assertEquals(0L, page1.getPageKey());
final NodeDelegate del = new NodeDelegate(0, 1, 0, 0, Optional.of(SirixDeweyID.newRootID()));
final StructNodeDelegate strucDel = new StructNodeDelegate(del, 12l, 4l, 3l, 1l, 0l);
final NameNodeDelegate nameDel = new NameNodeDelegate(del, 5, 6, 7, 1);
final ElementNode node1 = new ElementNode(strucDel, nameDel, new ArrayList<Long>(), HashBiMap.<Long, Long>create(), new ArrayList<Long>(), new QNm("a", "b", "c"));
node1.insertAttribute(88L, 100);
node1.insertAttribute(87L, 101);
node1.insertNamespace(99L);
node1.insertNamespace(98L);
assertEquals(0L, node1.getNodeKey());
page1.setEntry(node1.getNodeKey(), node1);
final ByteArrayOutputStream out = new ByteArrayOutputStream();
final DataOutputStream dataOut = new DataOutputStream(out);
PagePersistenter.serializePage(dataOut, page1, SerializationType.DATA);
final ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
final UnorderedKeyValuePage page2 = (UnorderedKeyValuePage) PagePersistenter.deserializePage(new DataInputStream(in), mPageReadTrx, SerializationType.DATA);
// assertEquals(position, out.position());
final ElementNode element = (ElementNode) page2.getValue(0l);
assertEquals(0L, page2.getValue(0l).getNodeKey());
assertEquals(1L, element.getParentKey());
assertEquals(12L, element.getFirstChildKey());
assertEquals(3L, element.getLeftSiblingKey());
assertEquals(4L, element.getRightSiblingKey());
assertEquals(1, element.getChildCount());
assertEquals(2, element.getAttributeCount());
assertEquals(2, element.getNamespaceCount());
assertEquals(88L, element.getAttributeKey(0));
assertEquals(87L, element.getAttributeKey(1));
assertEquals(99L, element.getNamespaceKey(0));
assertEquals(98L, element.getNamespaceKey(1));
assertEquals(5, ((NameNode) page2.getValue(0l)).getURIKey());
assertEquals(6, ((NameNode) page2.getValue(0l)).getPrefixKey());
assertEquals(7, ((NameNode) page2.getValue(0l)).getLocalNameKey());
assertEquals(NamePageHash.generateHashForString("xs:untyped"), element.getTypeKey());
}
use of org.sirix.node.ElementNode in project sirix by sirixdb.
the class XdmNodeReadTrxImpl method moveToAttributeByName.
@Override
public Move<? extends XdmNodeReadTrx> moveToAttributeByName(final QNm name) {
assertNotClosed();
if (mCurrentNode.getKind() == Kind.ELEMENT) {
final ElementNode element = ((ElementNode) mCurrentNode);
final Optional<Long> attrKey = element.getAttributeKeyByName(name);
if (attrKey.isPresent()) {
final Move<? extends XdmNodeReadTrx> moved = moveTo(attrKey.get());
return moved;
}
}
return Move.notMoved();
}
use of org.sirix.node.ElementNode in project sirix by sirixdb.
the class XdmNodeWriterTrxImpl method insertElementAsLeftSibling.
@Override
public XdmNodeWriteTrx insertElementAsLeftSibling(final QNm name) throws SirixException {
if (!XMLToken.isValidQName(checkNotNull(name))) {
throw new IllegalArgumentException("The QName is not valid!");
}
acquireLock();
try {
if (getCurrentNode() instanceof StructNode && getCurrentNode().getKind() != Kind.DOCUMENT) {
checkAccessAndCommit();
final long key = getCurrentNode().getNodeKey();
moveToParent();
final long pathNodeKey = mBuildPathSummary ? mPathSummaryWriter.getPathNodeKey(name, Kind.ELEMENT) : 0;
moveTo(key);
final long parentKey = getCurrentNode().getParentKey();
final long leftSibKey = ((StructNode) getCurrentNode()).getLeftSiblingKey();
final long rightSibKey = getCurrentNode().getNodeKey();
final Optional<SirixDeweyID> id = newLeftSiblingID();
final ElementNode node = mNodeFactory.createElementNode(parentKey, leftSibKey, rightSibKey, 0, name, pathNodeKey, id);
mNodeReader.setCurrentNode(node);
adaptForInsert(node, InsertPos.ASLEFTSIBLING, PageKind.RECORDPAGE);
mNodeReader.setCurrentNode(node);
adaptHashesWithAdd();
return this;
} else {
throw new SirixUsageException("Insert is not allowed if current node is not an StructuralNode (either Text or Element)!");
}
} finally {
unLock();
}
}
use of org.sirix.node.ElementNode 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);
}
Aggregations