BUG-4295: fix merge callsite
[yangtools.git] / yang / yang-data-impl / src / main / java / org / opendaylight / yangtools / yang / data / impl / schema / tree / ModifiedNode.java
index cae3e94d1c7bdd7aa2dc5a5550cb2e2b0d8166dd..49a7873ac7b27e3290b20b0bdb82b5abf8b81b65 100644 (file)
@@ -66,6 +66,11 @@ final class ModifiedNode extends NodeModification implements StoreTreeNode<Modif
     // Alternative history introduced in WRITE nodes. Instantiated when we touch any child underneath such a node.
     private TreeNode writtenOriginal;
 
+    // Internal cache for TreeNodes created as part of validation
+    private SchemaAwareApplyOperation validatedOp;
+    private Optional<TreeNode> validatedCurrent;
+    private TreeNode validatedNode;
+
     private ModifiedNode(final PathArgument identifier, final Optional<TreeNode> original, final ChildTrackingPolicy childPolicy) {
         this.identifier = identifier;
         this.original = original;
@@ -162,12 +167,12 @@ final class ModifiedNode extends NodeModification implements StoreTreeNode<Modif
      * changes modification type to {@link ModificationType#SUBTREE_MODIFIED}
      *
      * @param child child identifier, may not be null
-     * @param childPolicy child tracking policy for the node we are looking for
+     * @param childOper Child operation
      * @param modVersion Version allocated by the calling {@link InMemoryDataTreeModification}
      * @return {@link ModifiedNode} for specified child, with {@link #getOriginal()}
      *         containing child metadata if child was present in original data.
      */
-    ModifiedNode modifyChild(@Nonnull final PathArgument child, @Nonnull final ChildTrackingPolicy childPolicy,
+    ModifiedNode modifyChild(@Nonnull final PathArgument child, @Nonnull final ModificationApplyOperation childOper,
             @Nonnull final Version modVersion) {
         clearSnapshot();
         if (operation == LogicalOperation.NONE) {
@@ -181,7 +186,7 @@ final class ModifiedNode extends NodeModification implements StoreTreeNode<Modif
         final Optional<TreeNode> currentMetadata = findOriginalMetadata(child, modVersion);
 
 
-        final ModifiedNode newlyCreated = new ModifiedNode(child, currentMetadata, childPolicy);
+        final ModifiedNode newlyCreated = new ModifiedNode(child, currentMetadata, childOper.getChildPolicy());
         if (operation == LogicalOperation.MERGE && value != null) {
             /*
              * We are attempting to modify a previously-unmodified part of a MERGE node. If the
@@ -190,7 +195,7 @@ final class ModifiedNode extends NodeModification implements StoreTreeNode<Modif
             @SuppressWarnings({ "rawtypes", "unchecked" })
             final Optional<NormalizedNode<?, ?>> childData = ((NormalizedNodeContainer)value).getChild(child);
             if (childData.isPresent()) {
-                newlyCreated.updateValue(LogicalOperation.MERGE, childData.get());
+                childOper.mergeIntoModifiedNode(newlyCreated, childData.get(), modVersion);
             }
         }
 
@@ -221,6 +226,11 @@ final class ModifiedNode extends NodeModification implements StoreTreeNode<Modif
             newType = LogicalOperation.DELETE;
             break;
         case MERGE:
+                // In case of merge - delete needs to be recored and must not to be changed into
+                // NONE, because lazy expansion of parent MERGE node would reintroduce it
+                // again.
+                newType = LogicalOperation.DELETE;
+                break;
         case TOUCH:
         case WRITE:
             /*
@@ -341,4 +351,14 @@ final class ModifiedNode extends NodeModification implements StoreTreeNode<Modif
     public static ModifiedNode createUnmodified(final TreeNode metadataTree, final ChildTrackingPolicy childPolicy) {
         return new ModifiedNode(metadataTree.getIdentifier(), Optional.of(metadataTree), childPolicy);
     }
+
+    void setValidatedNode(final SchemaAwareApplyOperation op, final Optional<TreeNode> current, final TreeNode node) {
+        this.validatedOp = Preconditions.checkNotNull(op);
+        this.validatedCurrent = Preconditions.checkNotNull(current);
+        this.validatedNode = Preconditions.checkNotNull(node);
+    }
+
+    TreeNode getValidatedNode(final SchemaAwareApplyOperation op, final Optional<TreeNode> current) {
+        return op.equals(validatedOp) && current.equals(validatedCurrent) ? validatedNode : null;
+    }
 }