From: Maros Marsalek Date: Wed, 22 Apr 2015 07:34:42 +0000 (+0200) Subject: Use ImmutableNodes.fromInstanceId in restconf X-Git-Tag: release/lithium~222^2 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=c8023e980b7f421d0af06b99fd66380b72d3a8e0 Use ImmutableNodes.fromInstanceId in restconf Build normalized node strcuture from Yang Instance Id using new utilities from yang-data-impl. Change-Id: Iee74bc0a7529b0fe7b901c04d2e26f9e2e60fac1 Signed-off-by: Maros Marsalek --- diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/BrokerFacade.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/BrokerFacade.java index 346d54a773..0378ae40ee 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/BrokerFacade.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/BrokerFacade.java @@ -11,6 +11,7 @@ import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastor import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.OPERATIONAL; import com.google.common.base.Optional; +import com.google.common.base.Preconditions; import com.google.common.util.concurrent.CheckedFuture; import com.google.common.util.concurrent.ListenableFuture; import java.util.ArrayList; @@ -20,11 +21,7 @@ import java.util.concurrent.ExecutionException; import javax.ws.rs.core.Response.Status; import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; -import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; -import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationException; -import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationOperation; -import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer; import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker; import org.opendaylight.controller.md.sal.dom.api.DOMDataChangeListener; import org.opendaylight.controller.md.sal.dom.api.DOMDataReadTransaction; @@ -43,6 +40,8 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.opendaylight.yangtools.yang.model.api.SchemaPath; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -106,38 +105,34 @@ public class BrokerFacade { // PUT configuration public CheckedFuture commitConfigurationDataPut( - final YangInstanceIdentifier path, final NormalizedNode payload) { + final SchemaContext globalSchema, final YangInstanceIdentifier path, final NormalizedNode payload) { checkPreconditions(); - final DataNormalizationOperation rootOp = ControllerContext.getInstance().getRootOperation(); - return putDataViaTransaction(domDataBroker.newReadWriteTransaction(), CONFIGURATION, path, payload, rootOp); + return putDataViaTransaction(domDataBroker.newReadWriteTransaction(), CONFIGURATION, path, payload, globalSchema); } public CheckedFuture commitConfigurationDataPut( final DOMMountPoint mountPoint, final YangInstanceIdentifier path, final NormalizedNode payload) { final Optional domDataBrokerService = mountPoint.getService(DOMDataBroker.class); if (domDataBrokerService.isPresent()) { - final DataNormalizationOperation rootOp = new DataNormalizer(mountPoint.getSchemaContext()).getRootOperation(); return putDataViaTransaction(domDataBrokerService.get().newReadWriteTransaction(), CONFIGURATION, path, - payload, rootOp); + payload, mountPoint.getSchemaContext()); } throw new RestconfDocumentedException("DOM data broker service isn't available for mount point."); } // POST configuration public CheckedFuture commitConfigurationDataPost( - final YangInstanceIdentifier path, final NormalizedNode payload) { + final SchemaContext globalSchema, final YangInstanceIdentifier path, final NormalizedNode payload) { checkPreconditions(); - final DataNormalizationOperation rootOp = ControllerContext.getInstance().getRootOperation(); - return postDataViaTransaction(domDataBroker.newReadWriteTransaction(), CONFIGURATION, path, payload, rootOp); + return postDataViaTransaction(domDataBroker.newReadWriteTransaction(), CONFIGURATION, path, payload, globalSchema); } public CheckedFuture commitConfigurationDataPost( final DOMMountPoint mountPoint, final YangInstanceIdentifier path, final NormalizedNode payload) { final Optional domDataBrokerService = mountPoint.getService(DOMDataBroker.class); if (domDataBrokerService.isPresent()) { - final DataNormalizationOperation rootOp = new DataNormalizer(mountPoint.getSchemaContext()).getRootOperation(); return postDataViaTransaction(domDataBrokerService.get().newReadWriteTransaction(), CONFIGURATION, path, - payload, rootOp); + payload, mountPoint.getSchemaContext()); } throw new RestconfDocumentedException("DOM data broker service isn't available for mount point."); } @@ -206,7 +201,7 @@ public class BrokerFacade { private CheckedFuture postDataViaTransaction( final DOMDataReadWriteTransaction rWTransaction, final LogicalDatastoreType datastore, - final YangInstanceIdentifier parentPath, final NormalizedNode payload, final DataNormalizationOperation root) { + final YangInstanceIdentifier parentPath, final NormalizedNode payload, final SchemaContext schemaContext) { // FIXME: This is doing correct post for container and list children // not sure if this will work for choice case final YangInstanceIdentifier path; @@ -230,7 +225,7 @@ public class BrokerFacade { LOG.trace("It wasn't possible to get data loaded from datastore at path " + path); } - ensureParentsByMerge(datastore, path, rWTransaction, root); + ensureParentsByMerge(datastore, path, rWTransaction, schemaContext); rWTransaction.merge(datastore, path, payload); LOG.trace("Post " + datastore.name() + " via Restconf: {}", path); return rWTransaction.submit(); @@ -238,9 +233,9 @@ public class BrokerFacade { private CheckedFuture putDataViaTransaction( final DOMDataReadWriteTransaction writeTransaction, final LogicalDatastoreType datastore, - final YangInstanceIdentifier path, final NormalizedNode payload, final DataNormalizationOperation root) { + final YangInstanceIdentifier path, final NormalizedNode payload, final SchemaContext schemaContext) { LOG.trace("Put " + datastore.name() + " via Restconf: {}", path); - ensureParentsByMerge(datastore, path, writeTransaction, root); + ensureParentsByMerge(datastore, path, writeTransaction, schemaContext); writeTransaction.put(datastore, path, payload); return writeTransaction.submit(); } @@ -257,39 +252,34 @@ public class BrokerFacade { this.domDataBroker = domDataBroker; } - private final void ensureParentsByMerge(final LogicalDatastoreType store, - final YangInstanceIdentifier normalizedPath, final DOMDataReadWriteTransaction rwTx, - final DataNormalizationOperation root) { - final List currentArguments = new ArrayList<>(); - final Iterator iterator = normalizedPath.getPathArguments().iterator(); - DataNormalizationOperation currentOp = root; - while (iterator.hasNext()) { - final PathArgument currentArg = iterator.next(); - try { - currentOp = currentOp.getChild(currentArg); - } catch (final DataNormalizationException e) { - rwTx.cancel(); - throw new IllegalArgumentException( - String.format("Invalid child encountered in path %s", normalizedPath), e); - } - currentArguments.add(currentArg); - final YangInstanceIdentifier currentPath = YangInstanceIdentifier.create(currentArguments); + private void ensureParentsByMerge(final LogicalDatastoreType store, + final YangInstanceIdentifier normalizedPath, final DOMDataReadWriteTransaction rwTx, final SchemaContext schemaContext) { + final List normalizedPathWithoutChildArgs = new ArrayList<>(); + YangInstanceIdentifier rootNormalizedPath = null; - final Boolean exists; + final Iterator it = normalizedPath.getPathArguments().iterator(); - try { - - final CheckedFuture future = rwTx.exists(store, currentPath); - exists = future.checkedGet(); - } catch (final ReadFailedException e) { - LOG.error("Failed to read pre-existing data from store {} path {}", store, currentPath, e); - rwTx.cancel(); - throw new IllegalStateException("Failed to read pre-existing data", e); + while(it.hasNext()) { + final PathArgument pathArgument = it.next(); + if(rootNormalizedPath == null) { + rootNormalizedPath = YangInstanceIdentifier.create(pathArgument); } - if (!exists && iterator.hasNext()) { - rwTx.merge(store, currentPath, currentOp.createDefault(currentArg)); + // Skip last element, its not a parent + if(it.hasNext()) { + normalizedPathWithoutChildArgs.add(pathArgument); } } + + // No parent structure involved, no need to ensure parents + if(normalizedPathWithoutChildArgs.isEmpty()) { + return; + } + + Preconditions.checkArgument(rootNormalizedPath != null, "Empty path received"); + + final NormalizedNode parentStructure = + ImmutableNodes.fromInstanceId(schemaContext, YangInstanceIdentifier.create(normalizedPathWithoutChildArgs)); + rwTx.merge(store, rootNormalizedPath, parentStructure); } } diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.java index 33795889a1..6c44d26d35 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.java @@ -697,7 +697,7 @@ public class RestconfImpl implements RestconfService { if (mountPoint != null) { broker.commitConfigurationDataPut(mountPoint, normalizedII, payload.getData()).checkedGet(); } else { - broker.commitConfigurationDataPut(normalizedII, payload.getData()).checkedGet(); + broker.commitConfigurationDataPut(controllerContext.getGlobalSchema(), normalizedII, payload.getData()).checkedGet(); } break; @@ -842,7 +842,7 @@ public class RestconfImpl implements RestconfService { if (mountPoint != null) { broker.commitConfigurationDataPost(mountPoint, normalizedII, payload.getData()).checkedGet(); } else { - broker.commitConfigurationDataPost(normalizedII, payload.getData()).checkedGet(); + broker.commitConfigurationDataPost(controllerContext.getGlobalSchema(), normalizedII, payload.getData()).checkedGet(); } } catch(final RestconfDocumentedException e) { throw e; diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/input/to/cnsn/test/RestPutListDataTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/input/to/cnsn/test/RestPutListDataTest.java index b696854dbb..8ccd4a1f41 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/input/to/cnsn/test/RestPutListDataTest.java +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/input/to/cnsn/test/RestPutListDataTest.java @@ -71,7 +71,7 @@ public class RestPutListDataTest { restconfImpl = RestconfImpl.getInstance(); restconfImpl.setBroker(brokerFacade); restconfImpl.setControllerContext(controllerContext); - when(brokerFacade.commitConfigurationDataPut(any(YangInstanceIdentifier.class), any(NormalizedNode.class))) + when(brokerFacade.commitConfigurationDataPut(any(SchemaContext.class), any(YangInstanceIdentifier.class), any(NormalizedNode.class))) .thenReturn(mock(CheckedFuture.class)); } diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/BrokerFacadeTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/BrokerFacadeTest.java index dc1f968805..6542396612 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/BrokerFacadeTest.java +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/BrokerFacadeTest.java @@ -55,6 +55,7 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.opendaylight.yangtools.yang.data.impl.schema.Builders; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.opendaylight.yangtools.yang.model.api.SchemaPath; /** @@ -181,7 +182,7 @@ public class BrokerFacadeTest { when(wTransaction.submit()).thenReturn(expFuture); - final Future actualFuture = brokerFacade.commitConfigurationDataPut(instanceID, dummyNode); + final Future actualFuture = brokerFacade.commitConfigurationDataPut((SchemaContext)null, instanceID, dummyNode); assertSame("commitConfigurationDataPut", expFuture, actualFuture); @@ -208,7 +209,7 @@ public class BrokerFacadeTest { when(rwTransaction.submit()).thenReturn(expFuture); final CheckedFuture actualFuture = brokerFacade.commitConfigurationDataPost( - YangInstanceIdentifier.builder().build(), dummyNode); + (SchemaContext)null, YangInstanceIdentifier.builder().build(), dummyNode); assertSame("commitConfigurationDataPost", expFuture, actualFuture); @@ -223,7 +224,8 @@ public class BrokerFacadeTest { when(rwTransaction.read(eq(LogicalDatastoreType.CONFIGURATION), any(YangInstanceIdentifier.class))).thenReturn( dummyNodeInFuture); try { - brokerFacade.commitConfigurationDataPost(instanceID, dummyNode); + // Schema context is only necessary for ensuring parent structure + brokerFacade.commitConfigurationDataPost((SchemaContext)null, instanceID, dummyNode); } catch (final RestconfDocumentedException e) { assertEquals("getErrorTag", RestconfError.ErrorTag.DATA_EXISTS, e.getErrors().get(0).getErrorTag()); throw e; diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestPostOperationTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestPostOperationTest.java index 62a37ed147..bb731a32d0 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestPostOperationTest.java +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestPostOperationTest.java @@ -137,7 +137,7 @@ public class RestPostOperationTest extends JerseyTest { final RpcResult rpcResult = new DummyRpcResult.Builder().result( TransactionStatus.COMMITED).build(); - when(brokerFacade.commitConfigurationDataPost(any(YangInstanceIdentifier.class), any(NormalizedNode.class))) + when(brokerFacade.commitConfigurationDataPost((SchemaContext)null, any(YangInstanceIdentifier.class), any(NormalizedNode.class))) .thenReturn(mock(CheckedFuture.class)); final ArgumentCaptor instanceIdCaptor = ArgumentCaptor.forClass(YangInstanceIdentifier.class); @@ -157,7 +157,7 @@ public class RestPostOperationTest extends JerseyTest { // FIXME : NEVER test a nr. of call some service in complex test suite // verify(brokerFacade, times(2)) verify(brokerFacade, times(1)) - .commitConfigurationDataPost(instanceIdCaptor.capture(), compNodeCaptor.capture()); + .commitConfigurationDataPost((SchemaContext)null, instanceIdCaptor.capture(), compNodeCaptor.capture()); // identifier = "[(urn:ietf:params:xml:ns:yang:test-interface?revision=2014-07-01)interfaces, (urn:ietf:params:xml:ns:yang:test-interface?revision=2014-07-01)block]"; assertEquals(identifier, ImmutableList.copyOf(instanceIdCaptor.getValue().getPathArguments()).toString()); } @@ -166,7 +166,7 @@ public class RestPostOperationTest extends JerseyTest { public void createConfigurationDataNullTest() throws UnsupportedEncodingException { initMocking(); - when(brokerFacade.commitConfigurationDataPost(any(YangInstanceIdentifier.class),any(NormalizedNode.class))) + when(brokerFacade.commitConfigurationDataPost(any(SchemaContext.class), any(YangInstanceIdentifier.class),any(NormalizedNode.class))) .thenReturn(Futures.immediateCheckedFuture(null)); //FIXME : find who is set schemaContext diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestPutOperationTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestPutOperationTest.java index 39646f3ffd..f70af4e4f6 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestPutOperationTest.java +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestPutOperationTest.java @@ -171,13 +171,13 @@ public class RestPutOperationTest extends JerseyTest { doThrow(OptimisticLockFailedException.class). when(brokerFacade).commitConfigurationDataPut( - any(YangInstanceIdentifier.class), any(NormalizedNode.class)); + any(SchemaContext.class), any(YangInstanceIdentifier.class), any(NormalizedNode.class)); assertEquals(500, put(uri, MediaType.APPLICATION_XML, xmlData)); doThrow(OptimisticLockFailedException.class).doReturn(mock(CheckedFuture.class)). when(brokerFacade).commitConfigurationDataPut( - any(YangInstanceIdentifier.class), any(NormalizedNode.class)); + any(SchemaContext.class), any(YangInstanceIdentifier.class), any(NormalizedNode.class)); assertEquals(200, put(uri, MediaType.APPLICATION_XML, xmlData)); } @@ -190,7 +190,7 @@ public class RestPutOperationTest extends JerseyTest { doThrow(TransactionCommitFailedException.class). when(brokerFacade).commitConfigurationDataPut( - any(YangInstanceIdentifier.class), any(NormalizedNode.class)); + (SchemaContext)null, any(YangInstanceIdentifier.class), any(NormalizedNode.class)); assertEquals(500, put(uri, MediaType.APPLICATION_XML, xmlData)); } @@ -202,10 +202,10 @@ public class RestPutOperationTest extends JerseyTest { private void mockCommitConfigurationDataPutMethod(final boolean noErrors) { if (noErrors) { doReturn(mock(CheckedFuture.class)).when(brokerFacade).commitConfigurationDataPut( - any(YangInstanceIdentifier.class), any(NormalizedNode.class)); + any(SchemaContext.class), any(YangInstanceIdentifier.class), any(NormalizedNode.class)); } else { doThrow(RestconfDocumentedException.class).when(brokerFacade).commitConfigurationDataPut( - any(YangInstanceIdentifier.class), any(NormalizedNode.class)); + any(SchemaContext.class), any(YangInstanceIdentifier.class), any(NormalizedNode.class)); } }