Auto create mixin list-parent nodes from netconf northbound 80/35580/2
authorMaros Marsalek <mmarsale@cisco.com>
Tue, 1 Mar 2016 14:00:24 +0000 (15:00 +0100)
committerMaros Marsalek <mmarsale@cisco.com>
Tue, 1 Mar 2016 15:19:00 +0000 (16:19 +0100)
Change-Id: I61ecccc0631bb3a2fbaea4611fad37de6dc8a7f4
Signed-off-by: Maros Marsalek <mmarsale@cisco.com>
opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/netconf/mdsal/connector/ops/EditOperationStrategyProvider.java
opendaylight/netconf/mdsal-netconf-connector/src/test/java/org/opendaylight/netconf/mdsal/connector/ops/NetconfMDSalMappingTest.java
opendaylight/netconf/mdsal-netconf-connector/src/test/resources/messages/mapping/editConfigs/editConfig_delete-root.xml
opendaylight/netconf/mdsal-netconf-connector/src/test/resources/messages/mapping/editConfigs/editConfig_merge_n1.xml
opendaylight/netconf/mdsal-netconf-connector/src/test/resources/messages/mapping/editConfigs/editConfig_merge_n2.xml [new file with mode: 0644]
opendaylight/netconf/mdsal-netconf-connector/src/test/resources/messages/mapping/editConfigs/editConfig_merge_n3.xml [new file with mode: 0644]
opendaylight/netconf/mdsal-netconf-connector/src/test/resources/messages/mapping/editConfigs/editConfig_merge_n4.xml [new file with mode: 0644]
opendaylight/netconf/mdsal-netconf-connector/src/test/resources/messages/mapping/editConfigs/editConfig_merge_n5.xml [new file with mode: 0644]
opendaylight/netconf/mdsal-netconf-connector/src/test/resources/messages/mapping/editConfigs/editConfig_merge_n6.xml [new file with mode: 0644]
opendaylight/netconf/mdsal-netconf-connector/src/test/resources/yang/mdsal-netconf-mapping-test.yang

index 541c0b288eac9a288aae3054234dac60a81eea98..7d118e1cf046709404826ffe530e0bd9b94237cf 100644 (file)
@@ -29,6 +29,7 @@ import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode;
 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.AttributesBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.ExtensibleParser;
@@ -95,22 +96,49 @@ class EditOperationStrategyProvider extends DomToNormalizedNodeParserFactory.Bui
     }
 
     private static class NetconfOperationCollectionStrategy<N extends NormalizedNode<YangInstanceIdentifier.NodeIdentifier, ?>> implements ExtensibleParser.BuildingStrategy<YangInstanceIdentifier.NodeIdentifier, N> {
-        private final DataTreeChangeTracker changeTracker;
+        private final DataTreeChangeTracker dataTreeChangeTracker;
 
         public NetconfOperationCollectionStrategy(final DataTreeChangeTracker changeTracker) {
-            this.changeTracker = changeTracker;
+            this.dataTreeChangeTracker = changeTracker;
         }
 
         @Nullable
         @Override
         public N build(final NormalizedNodeBuilder<YangInstanceIdentifier.NodeIdentifier, ?, N> builder) {
-            changeTracker.popPath();
-            return builder.build();
+            final N node = builder.build();
+
+            // Try to auto create list-parent, mixin nodes to prevent exception from data tree
+
+            // Not under DELETE/REMOVE subtree
+            if (dataTreeChangeTracker.getDeleteOperationTracker() == 0 &&
+                dataTreeChangeTracker.getRemoveOperationTracker() == 0) {
+
+                // Artificial list-parent, mixin, empty node
+                final NormalizedNode<?, ?> mixinParent = getEmptyCollectionParent(node);
+
+                // Make sure to merge list-parent, mixin empty node to prevent missing parent node ex
+                dataTreeChangeTracker.addDataTreeChange(new DataTreeChangeTracker.DataTreeChange(
+                            mixinParent, ModifyAction.MERGE, new ArrayList<>(dataTreeChangeTracker.getCurrentPath())));
+            }
+
+            dataTreeChangeTracker.popPath();
+            return node;
+        }
+
+        private NormalizedNode<?, ?> getEmptyCollectionParent(final N node) {
+            if(node instanceof OrderedMapNode) {
+                return Builders.orderedMapBuilder().withNodeIdentifier(node.getIdentifier()).build();
+            } else if(node instanceof MapNode) {
+                return Builders.mapBuilder().withNodeIdentifier(node.getIdentifier()).build();
+            }
+
+            throw new IllegalArgumentException("Unexpected node type " + node.getClass() +
+                " while auto creating list like mixin node");
         }
 
         @Override
         public void prepareAttributes(final Map<QName, String> attributes, final NormalizedNodeBuilder<YangInstanceIdentifier.NodeIdentifier, ?, N> containerBuilder) {
-            changeTracker.pushPath(containerBuilder.build().getIdentifier());
+            dataTreeChangeTracker.pushPath(containerBuilder.build().getIdentifier());
         }
     }
 
index 4bf2a2b2738decd223b18b53e43c5b043b0d6132..b37626c6a844168a0951a862d97b098923a6eecd 100644 (file)
@@ -15,6 +15,7 @@ import static org.junit.Assert.fail;
 import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.doAnswer;
 
+import com.google.common.io.ByteSource;
 import com.google.common.util.concurrent.Futures;
 import java.io.IOException;
 import java.io.InputStream;
@@ -26,7 +27,6 @@ import java.util.Collections;
 import java.util.EnumMap;
 import java.util.List;
 import java.util.concurrent.ExecutorService;
-
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.transform.OutputKeys;
 import javax.xml.transform.Transformer;
@@ -34,7 +34,6 @@ import javax.xml.transform.TransformerException;
 import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.stream.StreamResult;
-
 import org.custommonkey.xmlunit.DetailedDiff;
 import org.custommonkey.xmlunit.Diff;
 import org.custommonkey.xmlunit.XMLUnit;
@@ -84,8 +83,6 @@ import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 import org.xml.sax.SAXException;
 
-import com.google.common.io.ByteSource;
-
 public class NetconfMDSalMappingTest {
 
     private static final Logger LOG = LoggerFactory.getLogger(NetconfMDSalMappingTest.class);
@@ -244,6 +241,37 @@ public class NetconfMDSalMappingTest {
 
     }
 
+    @Test
+    public void testListParentAutoCreation() throws Exception {
+        verifyResponse(edit("messages/mapping/editConfigs/editConfig_merge_n2.xml"), RPC_REPLY_OK);
+        verifyResponse(commit(), RPC_REPLY_OK);
+        getConfigRunning();
+        deleteDatastore();
+
+        verifyResponse(edit("messages/mapping/editConfigs/editConfig_merge_n3.xml"), RPC_REPLY_OK);
+        verifyResponse(commit(), RPC_REPLY_OK);
+        getConfigRunning();
+        deleteDatastore();
+
+        verifyResponse(edit("messages/mapping/editConfigs/editConfig_merge_n4.xml"), RPC_REPLY_OK);
+        verifyResponse(commit(), RPC_REPLY_OK);
+        getConfigRunning();
+        deleteDatastore();
+
+        verifyResponse(edit("messages/mapping/editConfigs/editConfig_merge_n5.xml"), RPC_REPLY_OK);
+        verifyResponse(commit(), RPC_REPLY_OK);
+        getConfigRunning();
+        deleteDatastore();
+
+        // The last test should fail because the netconf edit tries to create nested list entry without touching the
+        // parent structure (indicated by NONE operation). So the edit should fail. However thanks to our auto-create
+        // list parent mechanics, parent structure will be created.
+        verifyResponse(edit("messages/mapping/editConfigs/editConfig_merge_n6.xml"), RPC_REPLY_OK);
+        verifyResponse(commit(), RPC_REPLY_OK);
+        getConfigRunning();
+        deleteDatastore();
+    }
+
     @Test
     public void testKeyOrder() throws Exception {
         verifyResponse(edit("messages/mapping/editConfigs/editConfig_merge_multiple_keys_1.xml"), RPC_REPLY_OK);
index aea9ee0c4889951a8b7d69b07bdd51430f4cad49..ca9bb3da70795df171fff6091c0a31a30e1b3876 100644 (file)
@@ -20,6 +20,9 @@
         </mapping-nodes>
         <top xmlns="urn:opendaylight:mdsal:mapping:test" xmlns:a="urn:ietf:params:xml:ns:netconf:base:1.0" a:operation="remove">
         </top>
+        <top-list xmlns="urn:opendaylight:mdsal:mapping:test" xmlns:a="urn:ietf:params:xml:ns:netconf:base:1.0" a:operation="remove">
+            <id>1</id>
+        </top-list>
     </config>
 </edit-config>
 </rpc>
\ No newline at end of file
index f007fbada078343ad064ab61cef6d789d9c26eac..4fafa849e99d40f0003db97db7723fb4d139d290 100644 (file)
@@ -16,7 +16,7 @@
         </test-option>
         <default-operation>merge</default-operation>
         <config>
-            <mapping-nodes xmlns="urn:opendaylight:mdsal:mapping:test">
+            <mapping-nodes xmlns="urn:opendaylight:mdsal:mapping:test" >
                 <mapping-node>
                     <id>node1-put</id>
                     <content>put content</content>
diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/test/resources/messages/mapping/editConfigs/editConfig_merge_n2.xml b/opendaylight/netconf/mdsal-netconf-connector/src/test/resources/messages/mapping/editConfigs/editConfig_merge_n2.xml
new file mode 100644 (file)
index 0000000..ba44b84
--- /dev/null
@@ -0,0 +1,25 @@
+<!--
+  ~ Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+  ~
+  ~ This program and the accompanying materials are made available under the
+  ~ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+  ~ and is available at http://www.eclipse.org/legal/epl-v10.html
+  -->
+
+<rpc message-id="a" a="64" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+    <edit-config>
+        <target>
+            <candidate/>
+        </target>
+        <test-option>
+            set
+        </test-option>
+        <default-operation>none</default-operation>
+        <config>
+            <top-list xmlns="urn:opendaylight:mdsal:mapping:test" xmlns:a="urn:ietf:params:xml:ns:netconf:base:1.0"
+                      a:operation="replace">
+                <id>1</id>
+            </top-list>
+        </config>
+    </edit-config>
+</rpc>
\ No newline at end of file
diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/test/resources/messages/mapping/editConfigs/editConfig_merge_n3.xml b/opendaylight/netconf/mdsal-netconf-connector/src/test/resources/messages/mapping/editConfigs/editConfig_merge_n3.xml
new file mode 100644 (file)
index 0000000..044e79f
--- /dev/null
@@ -0,0 +1,25 @@
+<!--
+  ~ Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+  ~
+  ~ This program and the accompanying materials are made available under the
+  ~ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+  ~ and is available at http://www.eclipse.org/legal/epl-v10.html
+  -->
+
+<rpc message-id="a" a="64" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+    <edit-config>
+        <target>
+            <candidate/>
+        </target>
+        <test-option>
+            set
+        </test-option>
+        <default-operation>merge</default-operation>
+        <config>
+            <top-list xmlns="urn:opendaylight:mdsal:mapping:test" xmlns:a="urn:ietf:params:xml:ns:netconf:base:1.0"
+                      a:operation="replace">
+                <id>1</id>
+            </top-list>
+        </config>
+    </edit-config>
+</rpc>
\ No newline at end of file
diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/test/resources/messages/mapping/editConfigs/editConfig_merge_n4.xml b/opendaylight/netconf/mdsal-netconf-connector/src/test/resources/messages/mapping/editConfigs/editConfig_merge_n4.xml
new file mode 100644 (file)
index 0000000..921879c
--- /dev/null
@@ -0,0 +1,23 @@
+<!--
+  ~ Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+  ~
+  ~ This program and the accompanying materials are made available under the
+  ~ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+  ~ and is available at http://www.eclipse.org/legal/epl-v10.html
+  -->
+
+<rpc message-id="a" a="64" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+    <edit-config>
+        <target>
+            <candidate/>
+        </target>
+        <test-option>
+            set
+        </test-option>
+        <config>
+            <top-list xmlns="urn:opendaylight:mdsal:mapping:test">
+                <id>1</id>
+            </top-list>
+        </config>
+    </edit-config>
+</rpc>
\ No newline at end of file
diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/test/resources/messages/mapping/editConfigs/editConfig_merge_n5.xml b/opendaylight/netconf/mdsal-netconf-connector/src/test/resources/messages/mapping/editConfigs/editConfig_merge_n5.xml
new file mode 100644 (file)
index 0000000..1b0ab27
--- /dev/null
@@ -0,0 +1,27 @@
+<!--
+  ~ Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+  ~
+  ~ This program and the accompanying materials are made available under the
+  ~ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+  ~ and is available at http://www.eclipse.org/legal/epl-v10.html
+  -->
+
+<rpc message-id="a" a="64" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+    <edit-config>
+        <target>
+            <candidate/>
+        </target>
+        <test-option>
+            set
+        </test-option>
+        <config>
+            <mapping-nodes xmlns="urn:opendaylight:mdsal:mapping:test" >
+                <mapping-node xmlns:a="urn:ietf:params:xml:ns:netconf:base:1.0"
+                              a:operation="replace">
+                    <id>node1-put</id>
+                    <content>put content</content>
+                </mapping-node>
+            </mapping-nodes>
+        </config>
+    </edit-config>
+</rpc>
\ No newline at end of file
diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/test/resources/messages/mapping/editConfigs/editConfig_merge_n6.xml b/opendaylight/netconf/mdsal-netconf-connector/src/test/resources/messages/mapping/editConfigs/editConfig_merge_n6.xml
new file mode 100644 (file)
index 0000000..ac745af
--- /dev/null
@@ -0,0 +1,28 @@
+<!--
+  ~ Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+  ~
+  ~ This program and the accompanying materials are made available under the
+  ~ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+  ~ and is available at http://www.eclipse.org/legal/epl-v10.html
+  -->
+
+<rpc message-id="a" a="64" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+    <edit-config>
+        <target>
+            <candidate/>
+        </target>
+        <test-option>
+            set
+        </test-option>
+        <default-operation>none</default-operation>
+        <config>
+            <mapping-nodes xmlns="urn:opendaylight:mdsal:mapping:test">
+                <mapping-node xmlns:a="urn:ietf:params:xml:ns:netconf:base:1.0"
+                              a:operation="replace">
+                    <id>node1-put</id>
+                    <content>put content</content>
+                </mapping-node>
+            </mapping-nodes>
+        </config>
+    </edit-config>
+</rpc>
\ No newline at end of file
index 50c975e0b37efccd7cab639b4c10d319ed19329d..72b7dd7fafd14b65bb9402f3161051722fe99f0f 100644 (file)
@@ -5,6 +5,15 @@ module config {
 
     revision "2015-02-26";
 
+    list top-list {
+        key "id";
+
+        leaf id {
+            type string;
+        }
+    }
+
+
     container mapping-nodes {
 
         list multiple-keys {
@@ -30,7 +39,7 @@ module config {
                 type string;
             }
         }
-        
+
         list mapping-node{
             key "id";
             leaf id {