From: Ivan Hrasko Date: Mon, 25 Jul 2016 10:43:38 +0000 (+0200) Subject: Bug 5897 - PATCH merge operation does nothing X-Git-Tag: release/boron~23 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=8eca810b3c00e7936c47537665fd9c10f4f22963;p=netconf.git Bug 5897 - PATCH merge operation does nothing - added merge patch operation processing Change-Id: Ic3f5908c5f016a0680779ed12b4bc26b7b840d9a Signed-off-by: Ivan Hrasko --- diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/restconf/impl/BrokerFacade.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/restconf/impl/BrokerFacade.java index 37c90515ab..bb69bacc31 100644 --- a/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/restconf/impl/BrokerFacade.java +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/restconf/impl/BrokerFacade.java @@ -202,6 +202,20 @@ public class BrokerFacade { } } break; + case MERGE: + if (errorCounter == 0) { + try { + mergeDataWithinTransaction(patchTransaction, CONFIGURATION, patchEntity.getTargetNode(), + patchEntity.getNode(), globalSchema); + editCollection.add(new PATCHStatusEntity(patchEntity.getEditId(), true, null)); + } catch (RestconfDocumentedException e) { + editErrors = new ArrayList<>(); + editErrors.addAll(e.getErrors()); + editCollection.add(new PATCHStatusEntity(patchEntity.getEditId(), false, editErrors)); + errorCounter++; + } + } + break; } } @@ -396,6 +410,20 @@ public class BrokerFacade { writeTransaction.delete(datastore, path); } + private void mergeDataWithinTransaction( + final DOMDataReadWriteTransaction writeTransaction, final LogicalDatastoreType datastore, + final YangInstanceIdentifier path, final NormalizedNode payload, final SchemaContext schemaContext) { + LOG.trace("Merge {} within Restconf PATCH: {} with payload {}", datastore.name(), path, payload); + ensureParentsByMerge(datastore, path, writeTransaction, schemaContext); + + // merging is necessary only for lists otherwise we can call put method + if (payload instanceof MapNode) { + writeTransaction.merge(datastore, path, payload); + } else { + writeTransaction.put(datastore, path, payload); + } + } + public void setDomDataBroker(final DOMDataBroker domDataBroker) { this.domDataBroker = domDataBroker; } diff --git a/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestJsonPATCHBodyReader.java b/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestJsonPATCHBodyReader.java index ab48d5a02f..b999c036cc 100644 --- a/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestJsonPATCHBodyReader.java +++ b/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestJsonPATCHBodyReader.java @@ -126,4 +126,36 @@ public class TestJsonPATCHBodyReader extends AbstractBodyReaderTest { .readFrom(null, null, null, mediaType, null, inputStream); checkPATCHContext(returnValue); } + + /** + * Test of Yang PATCH merge operation on list. Test consists of two edit operations - replace and merge. + */ + @Test + public void modulePATCHMergeOperationOnListTest() throws Exception { + final String uri = "instance-identifier-patch-module:patch-cont/my-list1/leaf1"; + mockBodyReader(uri, jsonPATCHBodyReader, false); + + final InputStream inputStream = TestJsonBodyReader.class + .getResourceAsStream("/instanceidentifier/json/jsonPATCHMergeOperationOnList.json"); + + final PATCHContext returnValue = jsonPATCHBodyReader + .readFrom(null, null, null, mediaType, null, inputStream); + checkPATCHContext(returnValue); + } + + /** + * Test of Yang PATCH merge operation on container. Test consists of two edit operations - create and merge. + */ + @Test + public void modulePATCHMergeOperationOnContainerTest() throws Exception { + final String uri = "instance-identifier-patch-module:patch-cont"; + mockBodyReader(uri, jsonPATCHBodyReader, false); + + final InputStream inputStream = TestJsonBodyReader.class + .getResourceAsStream("/instanceidentifier/json/jsonPATCHMergeOperationOnContainer.json"); + + final PATCHContext returnValue = jsonPATCHBodyReader + .readFrom(null, null, null, mediaType, null, inputStream); + checkPATCHContext(returnValue); + } } diff --git a/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestXmlPATCHBodyReader.java b/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestXmlPATCHBodyReader.java index 3eef699171..4768a0c9e8 100644 --- a/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestXmlPATCHBodyReader.java +++ b/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestXmlPATCHBodyReader.java @@ -115,4 +115,32 @@ public class TestXmlPATCHBodyReader extends AbstractBodyReaderTest { .readFrom(null, null, null, mediaType, null, inputStream); checkPATCHContext(returnValue); } + + /** + * Test of Yang PATCH merge operation on list. Test consists of two edit operations - replace and merge. + */ + @Test + public void moduleDataMergeOperationOnListTest() throws Exception { + final String uri = "instance-identifier-patch-module:patch-cont/my-list1/leaf1"; + mockBodyReader(uri, xmlPATCHBodyReader, false); + final InputStream inputStream = TestXmlBodyReader.class + .getResourceAsStream("/instanceidentifier/xml/xmlPATCHdataMergeOperationOnList.xml"); + final PATCHContext returnValue = xmlPATCHBodyReader + .readFrom(null, null, null, mediaType, null, inputStream); + checkPATCHContext(returnValue); + } + + /** + * Test of Yang PATCH merge operation on container. Test consists of two edit operations - create and merge. + */ + @Test + public void moduleDataMergeOperationOnContainerTest() throws Exception { + final String uri = "instance-identifier-patch-module:patch-cont"; + mockBodyReader(uri, xmlPATCHBodyReader, false); + final InputStream inputStream = TestXmlBodyReader.class + .getResourceAsStream("/instanceidentifier/xml/xmlPATCHdataMergeOperationOnContainer.xml"); + final PATCHContext returnValue = xmlPATCHBodyReader + .readFrom(null, null, null, mediaType, null, inputStream); + checkPATCHContext(returnValue); + } } diff --git a/restconf/sal-rest-connector/src/test/resources/instanceidentifier/json/jsonPATCHMergeOperationOnContainer.json b/restconf/sal-rest-connector/src/test/resources/instanceidentifier/json/jsonPATCHMergeOperationOnContainer.json new file mode 100644 index 0000000000..14839201c7 --- /dev/null +++ b/restconf/sal-rest-connector/src/test/resources/instanceidentifier/json/jsonPATCHMergeOperationOnContainer.json @@ -0,0 +1,43 @@ +{ + "ietf-yang-patch:yang-patch" : { + "patch-id" : "Test merge operation", + "comment" : "This is test patch for merge operation on container", + "edit" : [ + { + "edit-id": "edit1", + "operation": "create", + "target": "/", + "value": { + "patch-cont": { + "my-list1": [ + { + "name": "my-list1 - A", + "my-leaf11": "I am leaf11-0", + "my-leaf12": "I am leaf12-1" + }, + { + "name": "my-list1 - B", + "my-leaf11": "I am leaf11-0", + "my-leaf12": "I am leaf12-1" + } + ] + } + } + }, + { + "edit-id": "edit2", + "operation": "merge", + "target": "/", + "value": { + "patch-cont": { + "my-list1": { + "name": "my-list1 - Merged", + "my-leaf11": "I am leaf11-0", + "my-leaf12": "I am leaf12-1" + } + } + } + } + ] + } +} \ No newline at end of file diff --git a/restconf/sal-rest-connector/src/test/resources/instanceidentifier/json/jsonPATCHMergeOperationOnList.json b/restconf/sal-rest-connector/src/test/resources/instanceidentifier/json/jsonPATCHMergeOperationOnList.json new file mode 100644 index 0000000000..3b809e0061 --- /dev/null +++ b/restconf/sal-rest-connector/src/test/resources/instanceidentifier/json/jsonPATCHMergeOperationOnList.json @@ -0,0 +1,32 @@ +{ + "ietf-yang-patch:yang-patch" : { + "patch-id" : "Test merge operation", + "comment" : "This is test patch for merge operation on list", + "edit" : [ + { + "edit-id": "edit1", + "operation": "replace", + "target": "/instance-identifier-patch-module:my-list2[instance-identifier-patch-module:name='my-leaf20']", + "value": { + "my-list2": { + "name": "my-leaf20", + "my-leaf21": "I am leaf21-0", + "my-leaf22": "I am leaf22-0" + } + } + }, + { + "edit-id": "edit2", + "operation": "merge", + "target": "/instance-identifier-patch-module:my-list2[instance-identifier-patch-module:name='my-leaf21']", + "value": { + "my-list2": { + "name": "my-leaf21", + "my-leaf21": "I am leaf21-1", + "my-leaf22": "I am leaf22-1" + } + } + } + ] + } +} \ No newline at end of file diff --git a/restconf/sal-rest-connector/src/test/resources/instanceidentifier/xml/xmlPATCHdataMergeOperationOnContainer.xml b/restconf/sal-rest-connector/src/test/resources/instanceidentifier/xml/xmlPATCHdataMergeOperationOnContainer.xml new file mode 100644 index 0000000000..afa35bdb49 --- /dev/null +++ b/restconf/sal-rest-connector/src/test/resources/instanceidentifier/xml/xmlPATCHdataMergeOperationOnContainer.xml @@ -0,0 +1,44 @@ + + + Test merge operation + This is test patch for merge operation on container + + edit1 + create + / + + + + my-list1 - A + I am leaf11-0 + I am leaf12-1 + + + my-list1 - B + I am leaf11-0 + I am leaf12-1 + + + + + + edit2 + merge + / + + + + my-list1 - Merged + I am leaf11-0 + I am leaf12-1 + + + + + \ No newline at end of file diff --git a/restconf/sal-rest-connector/src/test/resources/instanceidentifier/xml/xmlPATCHdataMergeOperationOnList.xml b/restconf/sal-rest-connector/src/test/resources/instanceidentifier/xml/xmlPATCHdataMergeOperationOnList.xml new file mode 100644 index 0000000000..ad130413a4 --- /dev/null +++ b/restconf/sal-rest-connector/src/test/resources/instanceidentifier/xml/xmlPATCHdataMergeOperationOnList.xml @@ -0,0 +1,35 @@ + + + Test merge operation + This is test patch for merge operation on list + + edit1 + replace + /my-list2 + + + my-leaf20 + I am leaf21-0 + I am leaf22-0 + + + + + edit2 + merge + /my-list2 + + + my-leaf21 + I am leaf21-1 + I am leaf22-1 + + + + \ No newline at end of file