- @SuppressWarnings("rawtypes")
- NormalizedNodeContainerBuilder dataBuilder = createBuilder(newValue);
- StoreNodeCompositeBuilder builder = StoreNodeCompositeBuilder.create(nodeVersion, dataBuilder) //
- .setSubtreeVersion(subtreeVersion);
-
- return mutateChildren(modification.getModifications(), newValueMeta, builder, nodeVersion);
- }
-
- @Override
- protected StoreMetadataNode applyMerge(final NodeModification modification, final StoreMetadataNode currentMeta,
- final UnsignedLong subtreeVersion) {
- // For Node Containers - merge is same as subtree change - we only replace children.
- return applySubtreeChange(modification, currentMeta, subtreeVersion);
- }
-
- @Override
- public StoreMetadataNode applySubtreeChange(final NodeModification modification,
- final StoreMetadataNode currentMeta, final UnsignedLong subtreeVersion) {
- // Bump subtree version to its new target
- final UnsignedLong updatedSubtreeVersion = StoreUtils.increase(currentMeta.getSubtreeVersion());
+ /*
+ * This is where things get interesting. The user has performed a write and
+ * then she applied some more modifications to it. So we need to make sense
+ * of that an apply the operations on top of the written value. We could have
+ * done it during the write, but this operation is potentially expensive, so
+ * we have left it out of the fast path.
+ *
+ * As it turns out, once we materialize the written data, we can share the
+ * code path with the subtree change. So let's create an unsealed TreeNode
+ * and run the common parts on it -- which end with the node being sealed.
+ */
+ final MutableTreeNode mutable = newValueMeta.mutable();
+ mutable.setSubtreeVersion(version);