Merge "Improve TypeProviderImpl.sortTypeDefinitionAccordingDepth()"
[yangtools.git] / yang / yang-data-impl / src / main / java / org / opendaylight / yangtools / yang / data / impl / schema / tree / NormalizedNodeContainerModificationStrategy.java
index e868dc92aca62a7d7c4726169cbed9622df48cfd..03b7c3ee23d8eb76033e644d2d79a8a173f0ec04 100644 (file)
@@ -10,11 +10,7 @@ package org.opendaylight.yangtools.yang.data.impl.schema.tree;
 import com.google.common.base.Optional;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeWithValue;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
@@ -23,6 +19,7 @@ import org.opendaylight.yangtools.yang.data.api.schema.OrderedLeafSetNode;
 import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.ModifiedNodeDoesNotExistException;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.MutableTreeNode;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNodeFactory;
@@ -62,14 +59,6 @@ abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareAp
         }
     }
 
-    @Override
-    protected void checkWriteApplicable(final InstanceIdentifier path, final NodeModification modification,
-            final Optional<TreeNode> current) throws DataValidationFailedException {
-        // FIXME: Implement proper write check for replacement of node container
-        //        prerequisite is to have transaction chain available for clients
-        //        otherwise this will break chained writes to same node.
-    }
-
     @SuppressWarnings("rawtypes")
     @Override
     protected void verifyWrittenStructure(final NormalizedNode<?, ?> writtenValue) {
@@ -119,12 +108,22 @@ abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareAp
         return mutateChildren(mutable, dataBuilder, version, modification.getChildren());
     }
 
+    /**
+     * Applies write/remove diff operation for each modification child in modification subtree.
+     * Operation also sets the Data tree references for each Tree Node (Index Node) in meta (MutableTreeNode) structure.
+     *
+     * @param meta MutableTreeNode (IndexTreeNode)
+     * @param data DataBuilder
+     * @param nodeVersion Version of TreeNode
+     * @param modifications modification operations to apply
+     * @return Sealed immutable copy of TreeNode structure with all Data Node references set.
+     */
     @SuppressWarnings({ "rawtypes", "unchecked" })
     private TreeNode mutateChildren(final MutableTreeNode meta, final NormalizedNodeContainerBuilder data,
             final Version nodeVersion, final Iterable<ModifiedNode> modifications) {
 
         for (ModifiedNode mod : modifications) {
-            final PathArgument id = mod.getIdentifier();
+            final YangInstanceIdentifier.PathArgument id = mod.getIdentifier();
             final Optional<TreeNode> cm = meta.getChild(id);
 
             Optional<TreeNode> result = resolveChildOperation(id).apply(mod, cm, nodeVersion);
@@ -162,25 +161,29 @@ abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareAp
     }
 
     @Override
-    protected void checkSubtreeModificationApplicable(final InstanceIdentifier path, final NodeModification modification,
+    protected void checkSubtreeModificationApplicable(final YangInstanceIdentifier path, final NodeModification modification,
             final Optional<TreeNode> current) throws DataValidationFailedException {
+        if (!modification.getOriginal().isPresent() && !current.isPresent()) {
+            throw new ModifiedNodeDoesNotExistException(path, String.format("Node %s does not exist. Cannot apply modification to its children.", path));
+        }
+
         SchemaAwareApplyOperation.checkConflicting(path, current.isPresent(), "Node was deleted by other transaction.");
         checkChildPreconditions(path, modification, current);
     }
 
-    private void checkChildPreconditions(final InstanceIdentifier path, final NodeModification modification, final Optional<TreeNode> current) throws DataValidationFailedException {
+    private void checkChildPreconditions(final YangInstanceIdentifier path, final NodeModification modification, final Optional<TreeNode> current) throws DataValidationFailedException {
         final TreeNode currentMeta = current.get();
         for (NodeModification childMod : modification.getChildren()) {
-            final PathArgument childId = childMod.getIdentifier();
+            final YangInstanceIdentifier.PathArgument childId = childMod.getIdentifier();
             final Optional<TreeNode> childMeta = currentMeta.getChild(childId);
 
-            InstanceIdentifier childPath = path.node(childId);
+            YangInstanceIdentifier childPath = path.node(childId);
             resolveChildOperation(childId).checkApplicable(childPath, childMod, childMeta);
         }
     }
 
     @Override
-    protected void checkMergeApplicable(final InstanceIdentifier path, final NodeModification modification,
+    protected void checkMergeApplicable(final YangInstanceIdentifier path, final NodeModification modification,
             final Optional<TreeNode> current) throws DataValidationFailedException {
         if(current.isPresent()) {
             checkChildPreconditions(path, modification,current);
@@ -192,23 +195,23 @@ abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareAp
 
     public static class ChoiceModificationStrategy extends NormalizedNodeContainerModificationStrategy {
 
-        private final Map<PathArgument, ModificationApplyOperation> childNodes;
+        private final Map<YangInstanceIdentifier.PathArgument, ModificationApplyOperation> childNodes;
 
         public ChoiceModificationStrategy(final ChoiceNode schemaNode) {
             super(org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode.class);
-            ImmutableMap.Builder<PathArgument, ModificationApplyOperation> child = ImmutableMap.builder();
+            ImmutableMap.Builder<YangInstanceIdentifier.PathArgument, ModificationApplyOperation> child = ImmutableMap.builder();
 
             for (ChoiceCaseNode caze : schemaNode.getCases()) {
                 for (DataSchemaNode cazeChild : caze.getChildNodes()) {
                     SchemaAwareApplyOperation childNode = SchemaAwareApplyOperation.from(cazeChild);
-                    child.put(new NodeIdentifier(cazeChild.getQName()), childNode);
+                    child.put(new YangInstanceIdentifier.NodeIdentifier(cazeChild.getQName()), childNode);
                 }
             }
             childNodes = child.build();
         }
 
         @Override
-        public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
+        public Optional<ModificationApplyOperation> getChild(final YangInstanceIdentifier.PathArgument child) {
             return Optional.fromNullable(childNodes.get(child));
         }
 
@@ -230,6 +233,11 @@ abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareAp
             entryStrategy = Optional.<ModificationApplyOperation> of(new ValueNodeModificationStrategy.LeafSetEntryModificationStrategy(schema));
         }
 
+        @Override
+        boolean isOrdered() {
+            return true;
+        }
+
         @SuppressWarnings("rawtypes")
         @Override
         protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
@@ -238,8 +246,8 @@ abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareAp
         }
 
         @Override
-        public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
-            if (identifier instanceof NodeWithValue) {
+        public Optional<ModificationApplyOperation> getChild(final YangInstanceIdentifier.PathArgument identifier) {
+            if (identifier instanceof YangInstanceIdentifier.NodeWithValue) {
                 return entryStrategy;
             }
             return Optional.absent();
@@ -255,6 +263,11 @@ abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareAp
             entryStrategy = Optional.<ModificationApplyOperation> of(new DataNodeContainerModificationStrategy.ListEntryModificationStrategy(schema));
         }
 
+        @Override
+        boolean isOrdered() {
+            return true;
+        }
+
         @SuppressWarnings("rawtypes")
         @Override
         protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
@@ -263,8 +276,8 @@ abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareAp
         }
 
         @Override
-        public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
-            if (identifier instanceof NodeIdentifierWithPredicates) {
+        public Optional<ModificationApplyOperation> getChild(final YangInstanceIdentifier.PathArgument identifier) {
+            if (identifier instanceof YangInstanceIdentifier.NodeIdentifierWithPredicates) {
                 return entryStrategy;
             }
             return Optional.absent();
@@ -294,8 +307,8 @@ abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareAp
         }
 
         @Override
-        public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
-            if (identifier instanceof NodeWithValue) {
+        public Optional<ModificationApplyOperation> getChild(final YangInstanceIdentifier.PathArgument identifier) {
+            if (identifier instanceof YangInstanceIdentifier.NodeWithValue) {
                 return entryStrategy;
             }
             return Optional.absent();
@@ -319,8 +332,8 @@ abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareAp
         }
 
         @Override
-        public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
-            if (identifier instanceof NodeIdentifierWithPredicates) {
+        public Optional<ModificationApplyOperation> getChild(final YangInstanceIdentifier.PathArgument identifier) {
+            if (identifier instanceof YangInstanceIdentifier.NodeIdentifierWithPredicates) {
                 return entryStrategy;
             }
             return Optional.absent();