X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=restconf%2Fsal-rest-connector%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fnetconf%2Fsal%2Frestconf%2Fimpl%2FBrokerFacade.java;h=6b4787064c1dc2e2e572c8aa818c49ab28d8032c;hb=8e02a3899e5069ce40ad3c070a911402c78fe24e;hp=5ff0cf07b2db20d37d17187b5372402bfe93d33c;hpb=65edc80d49f0899a48a64311a0899a79e9daabe4;p=netconf.git 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 5ff0cf07b2..6b4787064c 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 @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the @@ -20,6 +20,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; +import java.util.Map.Entry; import java.util.concurrent.CountDownLatch; import javax.annotation.Nullable; import javax.ws.rs.core.Response.Status; @@ -39,7 +40,6 @@ import org.opendaylight.controller.md.sal.dom.api.DOMNotificationService; import org.opendaylight.controller.md.sal.dom.api.DOMRpcException; import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult; import org.opendaylight.controller.md.sal.dom.api.DOMRpcService; -import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession; import org.opendaylight.netconf.sal.restconf.impl.RestconfError.ErrorTag; import org.opendaylight.netconf.sal.restconf.impl.RestconfError.ErrorType; import org.opendaylight.netconf.sal.streams.listeners.ListenerAdapter; @@ -79,11 +79,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class BrokerFacade { - private final static Logger LOG = LoggerFactory.getLogger(BrokerFacade.class); + private static final Logger LOG = LoggerFactory.getLogger(BrokerFacade.class); + private static final BrokerFacade INSTANCE = new BrokerFacade(); - private final static BrokerFacade INSTANCE = new BrokerFacade(); private volatile DOMRpcService rpcService; - private volatile ConsumerSession context; + private DOMDataBroker domDataBroker; private DOMNotificationService domNotification; @@ -97,25 +97,21 @@ public class BrokerFacade { this.domNotification = domNotification; } - public void setContext(final ConsumerSession context) { - this.context = context; - } - public static BrokerFacade getInstance() { return BrokerFacade.INSTANCE; } private void checkPreconditions() { - if (this.context == null || this.domDataBroker == null) { + if (this.domDataBroker == null) { throw new RestconfDocumentedException(Status.SERVICE_UNAVAILABLE); } } /** - * Read config data by path + * Read config data by path. * * @param path - * - path of data + * path of data * @return read date */ public NormalizedNode readConfigurationData(final YangInstanceIdentifier path) { @@ -123,12 +119,12 @@ public class BrokerFacade { } /** - * Read config data by path + * Read config data by path. * * @param path - * - path of data + * path of data * @param withDefa - * - value of with-defaults parameter + * value of with-defaults parameter * @return read date */ public NormalizedNode readConfigurationData(final YangInstanceIdentifier path, final String withDefa) { @@ -142,9 +138,9 @@ public class BrokerFacade { * Read config data from mount point by path. * * @param mountPoint - * - mount point for reading data + * mount point for reading data * @param path - * - path of data + * path of data * @return read data */ public NormalizedNode readConfigurationData(final DOMMountPoint mountPoint, @@ -156,11 +152,11 @@ public class BrokerFacade { * Read config data from mount point by path. * * @param mountPoint - * - mount point for reading data + * mount point for reading data * @param path - * - path of data + * path of data * @param withDefa - * - value of with-defaults parameter + * value of with-defaults parameter * @return read data */ public NormalizedNode readConfigurationData(final DOMMountPoint mountPoint, final YangInstanceIdentifier path, @@ -180,7 +176,7 @@ public class BrokerFacade { * Read operational data by path. * * @param path - * - path of data + * path of data * @return read data */ public NormalizedNode readOperationalData(final YangInstanceIdentifier path) { @@ -195,9 +191,9 @@ public class BrokerFacade { * Read operational data from mount point by path. * * @param mountPoint - * - mount point for reading data + * mount point for reading data * @param path - * - path of data + * path of data * @return read data */ public NormalizedNode readOperationalData(final DOMMountPoint mountPoint, final YangInstanceIdentifier path) { @@ -215,17 +211,20 @@ public class BrokerFacade { /** * PUT configuration data * + *

* Prepare result(status) for PUT operation and PUT data via transaction. * Return wrapped status and future from PUT. * * @param globalSchema - * - used by merge parents (if contains list) + * used by merge parents (if contains list) * @param path - * - path of node + * path of node * @param payload - * - input data + * input data * @param point + * point * @param insert + * insert * @return wrapper of status and future of PUT */ public PutResult commitConfigurationDataPut( @@ -248,18 +247,21 @@ public class BrokerFacade { /** * PUT configuration data (Mount point) * + *

* Prepare result(status) for PUT operation and PUT data via transaction. * Return wrapped status and future from PUT. * * @param mountPoint - * - mount point for getting transaction for operation and schema + * mount point for getting transaction for operation and schema * context for merging parents(if contains list) * @param path - * - path of node + * path of node * @param payload - * - input data + * input data * @param point + * point * @param insert + * insert * @return wrapper of status and future of PUT */ public PutResult commitMountPointDataPut( @@ -271,7 +273,8 @@ public class BrokerFacade { final Optional domDataBrokerService = mountPoint.getService(DOMDataBroker.class); if (domDataBrokerService.isPresent()) { - final DOMDataReadWriteTransaction newReadWriteTransaction = domDataBrokerService.get().newReadWriteTransaction(); + final DOMDataReadWriteTransaction newReadWriteTransaction = + domDataBrokerService.get().newReadWriteTransaction(); final Status status = readDataViaTransaction(newReadWriteTransaction, CONFIGURATION, path) != null ? Status.OK : Status.CREATED; final CheckedFuture future = putDataViaTransaction( @@ -284,7 +287,8 @@ public class BrokerFacade { throw new RestconfDocumentedException(errMsg); } - public PATCHStatusContext patchConfigurationDataWithinTransaction(final PATCHContext patchContext) throws Exception { + public PatchStatusContext patchConfigurationDataWithinTransaction(final PatchContext patchContext) + throws Exception { final DOMMountPoint mountPoint = patchContext.getInstanceIdentifierContext().getMountPoint(); // get new transaction and schema context on server or on mounted device @@ -302,9 +306,9 @@ public class BrokerFacade { patchTransaction = optional.get().newReadWriteTransaction(); } else { // if mount point does not have broker it is not possible to continue and global error is reported - LOG.error("Http PATCH {} has failed - device {} does not support broker service", + LOG.error("Http Patch {} has failed - device {} does not support broker service", patchContext.getPatchId(), mountPoint.getIdentifier()); - return new PATCHStatusContext( + return new PatchStatusContext( patchContext.getPatchId(), null, false, @@ -317,28 +321,27 @@ public class BrokerFacade { } } - final List editCollection = new ArrayList<>(); + final List editCollection = new ArrayList<>(); List editErrors; boolean withoutError = true; - for (final PATCHEntity patchEntity : patchContext.getData()) { - final PATCHEditOperation operation = PATCHEditOperation.valueOf(patchEntity.getOperation().toUpperCase()); - + for (final PatchEntity patchEntity : patchContext.getData()) { + final PatchEditOperation operation = patchEntity.getOperation(); switch (operation) { case CREATE: if (withoutError) { try { postDataWithinTransaction(patchTransaction, CONFIGURATION, patchEntity.getTargetNode(), patchEntity.getNode(), schemaContext); - editCollection.add(new PATCHStatusEntity(patchEntity.getEditId(), true, null)); + editCollection.add(new PatchStatusEntity(patchEntity.getEditId(), true, null)); } catch (final RestconfDocumentedException e) { - LOG.error("Error call http PATCH operation {} on target {}", + LOG.error("Error call http Patch operation {} on target {}", operation, patchEntity.getTargetNode().toString()); editErrors = new ArrayList<>(); editErrors.addAll(e.getErrors()); - editCollection.add(new PATCHStatusEntity(patchEntity.getEditId(), false, editErrors)); + editCollection.add(new PatchStatusEntity(patchEntity.getEditId(), false, editErrors)); withoutError = false; } } @@ -348,15 +351,15 @@ public class BrokerFacade { try { putDataWithinTransaction(patchTransaction, CONFIGURATION, patchEntity .getTargetNode(), patchEntity.getNode(), schemaContext); - editCollection.add(new PATCHStatusEntity(patchEntity.getEditId(), true, null)); + editCollection.add(new PatchStatusEntity(patchEntity.getEditId(), true, null)); } catch (final RestconfDocumentedException e) { - LOG.error("Error call http PATCH operation {} on target {}", + LOG.error("Error call http Patch operation {} on target {}", operation, patchEntity.getTargetNode().toString()); editErrors = new ArrayList<>(); editErrors.addAll(e.getErrors()); - editCollection.add(new PATCHStatusEntity(patchEntity.getEditId(), false, editErrors)); + editCollection.add(new PatchStatusEntity(patchEntity.getEditId(), false, editErrors)); withoutError = false; } } @@ -366,15 +369,15 @@ public class BrokerFacade { try { deleteDataWithinTransaction(patchTransaction, CONFIGURATION, patchEntity .getTargetNode()); - editCollection.add(new PATCHStatusEntity(patchEntity.getEditId(), true, null)); + editCollection.add(new PatchStatusEntity(patchEntity.getEditId(), true, null)); } catch (final RestconfDocumentedException e) { - LOG.error("Error call http PATCH operation {} on target {}", + LOG.error("Error call http Patch operation {} on target {}", operation, patchEntity.getTargetNode().toString()); editErrors = new ArrayList<>(); editErrors.addAll(e.getErrors()); - editCollection.add(new PATCHStatusEntity(patchEntity.getEditId(), false, editErrors)); + editCollection.add(new PatchStatusEntity(patchEntity.getEditId(), false, editErrors)); withoutError = false; } } @@ -384,15 +387,15 @@ public class BrokerFacade { try { deleteDataWithinTransaction(patchTransaction, CONFIGURATION, patchEntity .getTargetNode()); - editCollection.add(new PATCHStatusEntity(patchEntity.getEditId(), true, null)); + editCollection.add(new PatchStatusEntity(patchEntity.getEditId(), true, null)); } catch (final RestconfDocumentedException e) { - LOG.error("Error call http PATCH operation {} on target {}", + LOG.error("Error call http Patch operation {} on target {}", operation, patchEntity.getTargetNode().toString()); editErrors = new ArrayList<>(); editErrors.addAll(e.getErrors()); - editCollection.add(new PATCHStatusEntity(patchEntity.getEditId(), false, editErrors)); + editCollection.add(new PatchStatusEntity(patchEntity.getEditId(), false, editErrors)); withoutError = false; } } @@ -402,21 +405,21 @@ public class BrokerFacade { try { mergeDataWithinTransaction(patchTransaction, CONFIGURATION, patchEntity.getTargetNode(), patchEntity.getNode(), schemaContext); - editCollection.add(new PATCHStatusEntity(patchEntity.getEditId(), true, null)); + editCollection.add(new PatchStatusEntity(patchEntity.getEditId(), true, null)); } catch (final RestconfDocumentedException e) { - LOG.error("Error call http PATCH operation {} on target {}", + LOG.error("Error call http Patch operation {} on target {}", operation, patchEntity.getTargetNode().toString()); editErrors = new ArrayList<>(); editErrors.addAll(e.getErrors()); - editCollection.add(new PATCHStatusEntity(patchEntity.getEditId(), false, editErrors)); + editCollection.add(new PatchStatusEntity(patchEntity.getEditId(), false, editErrors)); withoutError = false; } } break; default: - LOG.error("Unsupported http PATCH operation {} on target {}", + LOG.error("Unsupported http Patch operation {} on target {}", operation, patchEntity.getTargetNode().toString()); break; @@ -426,29 +429,29 @@ public class BrokerFacade { // if errors then cancel transaction and return error status if (!withoutError) { patchTransaction.cancel(); - return new PATCHStatusContext(patchContext.getPatchId(), ImmutableList.copyOf(editCollection), false, null); + return new PatchStatusContext(patchContext.getPatchId(), ImmutableList.copyOf(editCollection), false, null); } // if no errors commit transaction final CountDownLatch waiter = new CountDownLatch(1); final CheckedFuture future = patchTransaction.submit(); - final PATCHStatusContextHelper status = new PATCHStatusContextHelper(); + final PatchStatusContextHelper status = new PatchStatusContextHelper(); Futures.addCallback(future, new FutureCallback() { @Override public void onSuccess(@Nullable final Void result) { - status.setStatus(new PATCHStatusContext(patchContext.getPatchId(), ImmutableList.copyOf(editCollection), + status.setStatus(new PatchStatusContext(patchContext.getPatchId(), ImmutableList.copyOf(editCollection), true, null)); waiter.countDown(); } @Override - public void onFailure(final Throwable t) { + public void onFailure(final Throwable throwable) { // if commit failed it is global error - LOG.error("Http PATCH {} transaction commit has failed", patchContext.getPatchId()); - status.setStatus(new PATCHStatusContext(patchContext.getPatchId(), ImmutableList.copyOf(editCollection), + LOG.error("Http Patch {} transaction commit has failed", patchContext.getPatchId()); + status.setStatus(new PatchStatusContext(patchContext.getPatchId(), ImmutableList.copyOf(editCollection), false, ImmutableList.of( - new RestconfError(ErrorType.APPLICATION, ErrorTag.OPERATION_FAILED, t.getMessage())))); + new RestconfError(ErrorType.APPLICATION, ErrorTag.OPERATION_FAILED, throwable.getMessage())))); waiter.countDown(); } }); @@ -498,7 +501,8 @@ public class BrokerFacade { } // RPC - public CheckedFuture invokeRpc(final SchemaPath type, final NormalizedNode input) { + public CheckedFuture invokeRpc(final SchemaPath type, + final NormalizedNode input) { checkPreconditions(); if (this.rpcService == null) { throw new RestconfDocumentedException(Status.SERVICE_UNAVAILABLE); @@ -581,7 +585,8 @@ public class BrokerFacade { return builder.build(); } - private void buildMapEntryBuilder(final DataContainerNodeAttrBuilder builder, + private void buildMapEntryBuilder( + final DataContainerNodeAttrBuilder builder, final MapEntryNode result, final DataSchemaContextTree baseSchemaCtxTree, final YangInstanceIdentifier actualPath, final boolean trim, final List keys) { for (final DataContainerChild child : result.getValue()) { @@ -604,17 +609,17 @@ public class BrokerFacade { final NormalizedNodeAttrBuilder> leafBuilder = Builders.leafBuilder((LeafSchemaNode) childSchema); if (keys.contains(child.getNodeType())) { - leafBuilder.withValue(((LeafNode) child).getValue()); + leafBuilder.withValue(((LeafNode) child).getValue()); builder.withChild(leafBuilder.build()); } else { if (trim) { if (defaultVal == null || !defaultVal.equals(nodeVal)) { - leafBuilder.withValue(((LeafNode) child).getValue()); + leafBuilder.withValue(((LeafNode) child).getValue()); builder.withChild(leafBuilder.build()); } } else { if (defaultVal != null && defaultVal.equals(nodeVal)) { - leafBuilder.withValue(((LeafNode) child).getValue()); + leafBuilder.withValue(((LeafNode) child).getValue()); builder.withChild(leafBuilder.build()); } } @@ -642,7 +647,7 @@ public class BrokerFacade { for (final DataContainerChild child : result.getValue()) { final YangInstanceIdentifier path = actualPath.node(child.getIdentifier()); final DataSchemaNode childSchema = baseSchemaCtxTree.getChild(path).getDataSchemaNode(); - if(child instanceof ContainerNode){ + if (child instanceof ContainerNode) { final DataContainerNodeAttrBuilder builderChild = Builders.containerBuilder((ContainerSchemaNode) childSchema); buildCont(builderChild, result, baseSchemaCtxTree, actualPath, trim); @@ -660,12 +665,12 @@ public class BrokerFacade { Builders.leafBuilder((LeafSchemaNode) childSchema); if (trim) { if (defaultVal == null || !defaultVal.equals(nodeVal)) { - leafBuilder.withValue(((LeafNode) child).getValue()); + leafBuilder.withValue(((LeafNode) child).getValue()); builder.withChild(leafBuilder.build()); } } else { if (defaultVal != null && defaultVal.equals(nodeVal)) { - leafBuilder.withValue(((LeafNode) child).getValue()); + leafBuilder.withValue(((LeafNode) child).getValue()); builder.withChild(leafBuilder.build()); } } @@ -674,74 +679,74 @@ public class BrokerFacade { } /** - * POST data and submit transaction {@link DOMDataReadWriteTransaction} + * POST data and submit transaction {@link DOMDataReadWriteTransaction}. */ private CheckedFuture postDataViaTransaction( - final DOMDataReadWriteTransaction rWTransaction, final LogicalDatastoreType datastore, + final DOMDataReadWriteTransaction rwTransaction, final LogicalDatastoreType datastore, final YangInstanceIdentifier path, final NormalizedNode payload, final SchemaContext schemaContext, final String insert, final String point) { LOG.trace("POST {} via Restconf: {} with payload {}", datastore.name(), path, payload); - postData(rWTransaction, datastore, path, payload, schemaContext, insert, point); - return rWTransaction.submit(); + postData(rwTransaction, datastore, path, payload, schemaContext, insert, point); + return rwTransaction.submit(); } /** - * POST data and do NOT submit transaction {@link DOMDataReadWriteTransaction} + * POST data and do NOT submit transaction {@link DOMDataReadWriteTransaction}. */ private void postDataWithinTransaction( - final DOMDataReadWriteTransaction rWTransaction, final LogicalDatastoreType datastore, + final DOMDataReadWriteTransaction rwTransaction, final LogicalDatastoreType datastore, final YangInstanceIdentifier path, final NormalizedNode payload, final SchemaContext schemaContext) { - LOG.trace("POST {} within Restconf PATCH: {} with payload {}", datastore.name(), path, payload); - postData(rWTransaction, datastore, path, payload, schemaContext, null, null); + LOG.trace("POST {} within Restconf Patch: {} with payload {}", datastore.name(), path, payload); + postData(rwTransaction, datastore, path, payload, schemaContext, null, null); } - private void postData(final DOMDataReadWriteTransaction rWTransaction, final LogicalDatastoreType datastore, + private void postData(final DOMDataReadWriteTransaction rwTransaction, final LogicalDatastoreType datastore, final YangInstanceIdentifier path, final NormalizedNode payload, final SchemaContext schemaContext, final String insert, final String point) { if (insert == null) { - makeNormalPost(rWTransaction, datastore, path, payload, schemaContext); + makeNormalPost(rwTransaction, datastore, path, payload, schemaContext); return; } final DataSchemaNode schemaNode = checkListAndOrderedType(schemaContext, path); - checkItemDoesNotExists(rWTransaction, datastore, path); + checkItemDoesNotExists(rwTransaction, datastore, path); switch (insert) { case "first": - if(schemaNode instanceof ListSchemaNode){ + if (schemaNode instanceof ListSchemaNode) { final OrderedMapNode readList = (OrderedMapNode) this.readConfigurationData(path.getParent().getParent()); if (readList == null || readList.getValue().isEmpty()) { - simplePostPut(rWTransaction, datastore, path, payload, schemaContext); + simplePostPut(rwTransaction, datastore, path, payload, schemaContext); } else { - rWTransaction.delete(datastore, path.getParent().getParent()); - simplePostPut(rWTransaction, datastore, path, payload, schemaContext); - makeNormalPost(rWTransaction, datastore, path.getParent().getParent(), readList, + rwTransaction.delete(datastore, path.getParent().getParent()); + simplePostPut(rwTransaction, datastore, path, payload, schemaContext); + makeNormalPost(rwTransaction, datastore, path.getParent().getParent(), readList, schemaContext); } } else { final OrderedLeafSetNode readLeafList = (OrderedLeafSetNode) readConfigurationData(path.getParent()); if (readLeafList == null || readLeafList.getValue().isEmpty()) { - simplePostPut(rWTransaction, datastore, path, payload, schemaContext); + simplePostPut(rwTransaction, datastore, path, payload, schemaContext); } else { - rWTransaction.delete(datastore, path.getParent()); - simplePostPut(rWTransaction, datastore, path, payload, schemaContext); - makeNormalPost(rWTransaction, datastore, path.getParent().getParent(), readLeafList, + rwTransaction.delete(datastore, path.getParent()); + simplePostPut(rwTransaction, datastore, path, payload, schemaContext); + makeNormalPost(rwTransaction, datastore, path.getParent().getParent(), readLeafList, schemaContext); } } break; case "last": - simplePostPut(rWTransaction, datastore, path, payload, schemaContext); + simplePostPut(rwTransaction, datastore, path, payload, schemaContext); break; case "before": - if(schemaNode instanceof ListSchemaNode){ + if (schemaNode instanceof ListSchemaNode) { final OrderedMapNode readList = (OrderedMapNode) this.readConfigurationData(path.getParent().getParent()); if (readList == null || readList.getValue().isEmpty()) { - simplePostPut(rWTransaction, datastore, path, payload, schemaContext); + simplePostPut(rwTransaction, datastore, path, payload, schemaContext); } else { - insertWithPointListPost(rWTransaction, datastore, path, payload, schemaContext, point, + insertWithPointListPost(rwTransaction, datastore, path, payload, schemaContext, point, readList, true); } @@ -749,9 +754,9 @@ public class BrokerFacade { final OrderedLeafSetNode readLeafList = (OrderedLeafSetNode) readConfigurationData(path.getParent()); if (readLeafList == null || readLeafList.getValue().isEmpty()) { - simplePostPut(rWTransaction, datastore, path, payload, schemaContext); + simplePostPut(rwTransaction, datastore, path, payload, schemaContext); } else { - insertWithPointLeafListPost(rWTransaction, datastore, path, payload, schemaContext, point, + insertWithPointLeafListPost(rwTransaction, datastore, path, payload, schemaContext, point, readLeafList, true); } } @@ -761,9 +766,9 @@ public class BrokerFacade { final OrderedMapNode readList = (OrderedMapNode) this.readConfigurationData(path.getParent().getParent()); if (readList == null || readList.getValue().isEmpty()) { - simplePostPut(rWTransaction, datastore, path, payload, schemaContext); + simplePostPut(rwTransaction, datastore, path, payload, schemaContext); } else { - insertWithPointListPost(rWTransaction, datastore, path, payload, schemaContext, point, + insertWithPointListPost(rwTransaction, datastore, path, payload, schemaContext, point, readList, false); } @@ -771,9 +776,9 @@ public class BrokerFacade { final OrderedLeafSetNode readLeafList = (OrderedLeafSetNode) readConfigurationData(path.getParent()); if (readLeafList == null || readLeafList.getValue().isEmpty()) { - simplePostPut(rWTransaction, datastore, path, payload, schemaContext); + simplePostPut(rwTransaction, datastore, path, payload, schemaContext); } else { - insertWithPointLeafListPost(rWTransaction, datastore, path, payload, schemaContext, point, + insertWithPointLeafListPost(rwTransaction, datastore, path, payload, schemaContext, point, readLeafList, false); } } @@ -785,70 +790,70 @@ public class BrokerFacade { } } - private static void insertWithPointLeafListPost(final DOMDataReadWriteTransaction rWTransaction, + private static void insertWithPointLeafListPost(final DOMDataReadWriteTransaction rwTransaction, final LogicalDatastoreType datastore, final YangInstanceIdentifier path, final NormalizedNode payload, final SchemaContext schemaContext, final String point, final OrderedLeafSetNode readLeafList, final boolean before) { - rWTransaction.delete(datastore, path.getParent().getParent()); + rwTransaction.delete(datastore, path.getParent().getParent()); final InstanceIdentifierContext instanceIdentifier = ControllerContext.getInstance().toInstanceIdentifier(point); - int p = 0; + int lastItemPosition = 0; for (final LeafSetEntryNode nodeChild : readLeafList.getValue()) { if (nodeChild.getIdentifier().equals(instanceIdentifier.getInstanceIdentifier().getLastPathArgument())) { break; } - p++; + lastItemPosition++; } if (!before) { - p++; + lastItemPosition++; } - int h = 0; + int lastInsertedPosition = 0; final NormalizedNode emptySubtree = ImmutableNodes.fromInstanceId(schemaContext, path.getParent().getParent()); - rWTransaction.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree); + rwTransaction.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree); for (final LeafSetEntryNode nodeChild : readLeafList.getValue()) { - if (h == p) { - checkItemDoesNotExists(rWTransaction, datastore, path); - simplePostPut(rWTransaction, datastore, path, payload, schemaContext); + if (lastInsertedPosition == lastItemPosition) { + checkItemDoesNotExists(rwTransaction, datastore, path); + simplePostPut(rwTransaction, datastore, path, payload, schemaContext); } final YangInstanceIdentifier childPath = path.getParent().getParent().node(nodeChild.getIdentifier()); - checkItemDoesNotExists(rWTransaction, datastore, childPath); - rWTransaction.put(datastore, childPath, nodeChild); - h++; + checkItemDoesNotExists(rwTransaction, datastore, childPath); + rwTransaction.put(datastore, childPath, nodeChild); + lastInsertedPosition++; } } - private static void insertWithPointListPost(final DOMDataReadWriteTransaction rWTransaction, + private static void insertWithPointListPost(final DOMDataReadWriteTransaction rwTransaction, final LogicalDatastoreType datastore, final YangInstanceIdentifier path, final NormalizedNode payload, final SchemaContext schemaContext, final String point, final MapNode readList, final boolean before) { - rWTransaction.delete(datastore, path.getParent().getParent()); + rwTransaction.delete(datastore, path.getParent().getParent()); final InstanceIdentifierContext instanceIdentifier = ControllerContext.getInstance().toInstanceIdentifier(point); - int p = 0; + int lastItemPosition = 0; for (final MapEntryNode mapEntryNode : readList.getValue()) { if (mapEntryNode.getIdentifier() .equals(instanceIdentifier.getInstanceIdentifier().getLastPathArgument())) { break; } - p++; + lastItemPosition++; } if (!before) { - p++; + lastItemPosition++; } - int h = 0; + int lastInsertedPosition = 0; final NormalizedNode emptySubtree = ImmutableNodes.fromInstanceId(schemaContext, path.getParent().getParent()); - rWTransaction.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree); + rwTransaction.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree); for (final MapEntryNode mapEntryNode : readList.getValue()) { - if (h == p) { - checkItemDoesNotExists(rWTransaction, datastore, path); - simplePostPut(rWTransaction, datastore, path, payload, schemaContext); + if (lastInsertedPosition == lastItemPosition) { + checkItemDoesNotExists(rwTransaction, datastore, path); + simplePostPut(rwTransaction, datastore, path, payload, schemaContext); } final YangInstanceIdentifier childPath = path.getParent().getParent().node(mapEntryNode.getIdentifier()); - checkItemDoesNotExists(rWTransaction, datastore, childPath); - rWTransaction.put(datastore, childPath, mapEntryNode); - h++; + checkItemDoesNotExists(rwTransaction, datastore, childPath); + rwTransaction.put(datastore, childPath, mapEntryNode); + lastInsertedPosition++; } } @@ -858,21 +863,22 @@ public class BrokerFacade { final DataSchemaNode dataSchemaNode = node.getDataSchemaNode(); if (dataSchemaNode instanceof ListSchemaNode) { - if(!((ListSchemaNode) dataSchemaNode).isUserOrdered()) { + if (!((ListSchemaNode) dataSchemaNode).isUserOrdered()) { throw new RestconfDocumentedException("Insert parameter can be used only with ordered-by user list."); } return dataSchemaNode; } if (dataSchemaNode instanceof LeafListSchemaNode) { - if(!((LeafListSchemaNode) dataSchemaNode).isUserOrdered()) { - throw new RestconfDocumentedException("Insert parameter can be used only with ordered-by user leaf-list."); + if (!((LeafListSchemaNode) dataSchemaNode).isUserOrdered()) { + throw new RestconfDocumentedException( + "Insert parameter can be used only with ordered-by user leaf-list."); } return dataSchemaNode; } throw new RestconfDocumentedException("Insert parameter can be used only with list or leaf-list"); } - private static void makeNormalPost(final DOMDataReadWriteTransaction rWTransaction, + private static void makeNormalPost(final DOMDataReadWriteTransaction rwTransaction, final LogicalDatastoreType datastore, final YangInstanceIdentifier path, final NormalizedNode payload, final SchemaContext schemaContext) { final Collection> children; @@ -881,38 +887,66 @@ public class BrokerFacade { } else if (payload instanceof LeafSetNode) { children = ((LeafSetNode) payload).getValue(); } else { - simplePostPut(rWTransaction, datastore, path, payload, schemaContext); + simplePostPut(rwTransaction, datastore, path, payload, schemaContext); return; } - // We are putting multiple children, we really need a create() operation, but until we have that we make do - // with a two-step process of verifying if the children exist and then putting them in. - for (final NormalizedNode child : children) { - checkItemDoesNotExists(rWTransaction, datastore, path.node(child.getIdentifier())); + final NormalizedNode emptySubtree = ImmutableNodes.fromInstanceId(schemaContext, path); + if (children.isEmpty()) { + rwTransaction.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree); + ensureParentsByMerge(datastore, path, rwTransaction, schemaContext); + return; } - final NormalizedNode emptySubtree = ImmutableNodes.fromInstanceId(schemaContext, path); - rWTransaction.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree); - ensureParentsByMerge(datastore, path, rWTransaction, schemaContext); + // Kick off batch existence check first... + final BatchedExistenceCheck check = BatchedExistenceCheck.start(rwTransaction, datastore, path, children); + + // ... now enqueue modifications. This relies on proper ordering of requests, i.e. these will not affect the + // result of the existence checks... + rwTransaction.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree); + ensureParentsByMerge(datastore, path, rwTransaction, schemaContext); for (final NormalizedNode child : children) { - rWTransaction.put(datastore, path.node(child.getIdentifier()), child); + // FIXME: we really want a create(YangInstanceIdentifier, NormalizedNode) method in the transaction, + // as that would allow us to skip the existence checks + rwTransaction.put(datastore, path.node(child.getIdentifier()), child); + } + + // ... finally collect existence checks and abort the transaction if any of them failed. + final Entry failure; + try { + failure = check.getFailure(); + } catch (InterruptedException e) { + rwTransaction.cancel(); + throw new RestconfDocumentedException("Could not determine the existence of path " + path, e); + } + + if (failure != null) { + rwTransaction.cancel(); + final ReadFailedException e = failure.getValue(); + if (e == null) { + throw new RestconfDocumentedException("Data already exists for path: " + failure.getKey(), + ErrorType.PROTOCOL, ErrorTag.DATA_EXISTS); + } + + throw new RestconfDocumentedException("Could not determine the existence of path " + failure.getKey(), e, + e.getErrorList()); } } - private static void simplePostPut(final DOMDataReadWriteTransaction rWTransaction, + private static void simplePostPut(final DOMDataReadWriteTransaction rwTransaction, final LogicalDatastoreType datastore, final YangInstanceIdentifier path, final NormalizedNode payload, final SchemaContext schemaContext) { - checkItemDoesNotExists(rWTransaction, datastore, path); - ensureParentsByMerge(datastore, path, rWTransaction, schemaContext); - rWTransaction.put(datastore, path, payload); + checkItemDoesNotExists(rwTransaction, datastore, path); + ensureParentsByMerge(datastore, path, rwTransaction, schemaContext); + rwTransaction.put(datastore, path, payload); } - private static boolean doesItemExist(final DOMDataReadWriteTransaction rWTransaction, + private static boolean doesItemExist(final DOMDataReadWriteTransaction rwTransaction, final LogicalDatastoreType store, final YangInstanceIdentifier path) { try { - return rWTransaction.exists(store, path).checkedGet(); + return rwTransaction.exists(store, path).checkedGet(); } catch (ReadFailedException e) { - rWTransaction.cancel(); + rwTransaction.cancel(); throw new RestconfDocumentedException("Could not determine the existence of path " + path, e, e.getErrorList()); } @@ -920,16 +954,16 @@ public class BrokerFacade { /** * Check if item already exists. Throws error if it does NOT already exist. - * @param rWTransaction Current transaction + * @param rwTransaction Current transaction * @param store Used datastore * @param path Path to item to verify its existence */ - private static void checkItemExists(final DOMDataReadWriteTransaction rWTransaction, + private static void checkItemExists(final DOMDataReadWriteTransaction rwTransaction, final LogicalDatastoreType store, final YangInstanceIdentifier path) { - if (!doesItemExist(rWTransaction, store, path)) { + if (!doesItemExist(rwTransaction, store, path)) { final String errMsg = "Operation via Restconf was not executed because data does not exist"; LOG.trace("{}:{}", errMsg, path); - rWTransaction.cancel(); + rwTransaction.cancel(); throw new RestconfDocumentedException("Data does not exist for path: " + path, ErrorType.PROTOCOL, ErrorTag.DATA_MISSING); } @@ -937,26 +971,28 @@ public class BrokerFacade { /** * Check if item does NOT already exist. Throws error if it already exists. - * @param rWTransaction Current transaction + * @param rwTransaction Current transaction * @param store Used datastore * @param path Path to item to verify its existence */ - private static void checkItemDoesNotExists(final DOMDataReadWriteTransaction rWTransaction, + private static void checkItemDoesNotExists(final DOMDataReadWriteTransaction rwTransaction, final LogicalDatastoreType store, final YangInstanceIdentifier path) { - if (doesItemExist(rWTransaction, store, path)) { + if (doesItemExist(rwTransaction, store, path)) { final String errMsg = "Operation via Restconf was not executed because data already exists"; LOG.trace("{}:{}", errMsg, path); - rWTransaction.cancel(); + rwTransaction.cancel(); throw new RestconfDocumentedException("Data already exists for path: " + path, ErrorType.PROTOCOL, ErrorTag.DATA_EXISTS); } } /** - * PUT data and submit {@link DOMDataReadWriteTransaction} + * PUT data and submit {@link DOMDataReadWriteTransaction}. * * @param point + * point * @param insert + * insert */ private CheckedFuture putDataViaTransaction( final DOMDataReadWriteTransaction readWriteTransaction, final LogicalDatastoreType datastore, @@ -968,188 +1004,183 @@ public class BrokerFacade { } /** - * PUT data and do NOT submit {@link DOMDataReadWriteTransaction} - * - * @param insert - * @param point + * PUT data and do NOT submit {@link DOMDataReadWriteTransaction}. */ private void putDataWithinTransaction( final DOMDataReadWriteTransaction writeTransaction, final LogicalDatastoreType datastore, final YangInstanceIdentifier path, final NormalizedNode payload, final SchemaContext schemaContext) { - LOG.trace("Put {} within Restconf PATCH: {} with payload {}", datastore.name(), path, payload); + LOG.trace("Put {} within Restconf Patch: {} with payload {}", datastore.name(), path, payload); putData(writeTransaction, datastore, path, payload, schemaContext, null, null); } // FIXME: This is doing correct put for container and list children, not sure if this will work for choice case - private void putData(final DOMDataReadWriteTransaction rWTransaction, final LogicalDatastoreType datastore, + private void putData(final DOMDataReadWriteTransaction rwTransaction, final LogicalDatastoreType datastore, final YangInstanceIdentifier path, final NormalizedNode payload, final SchemaContext schemaContext, final String insert, final String point) { if (insert == null) { - makePut(rWTransaction, datastore, path, payload, schemaContext); - } else { - final DataSchemaNode schemaNode = checkListAndOrderedType(schemaContext, path); - checkItemDoesNotExists(rWTransaction, datastore, path); - switch (insert) { - case "first": - if (schemaNode instanceof ListSchemaNode) { - final OrderedMapNode readList = - (OrderedMapNode) this.readConfigurationData(path.getParent()); - if (readList == null || readList.getValue().isEmpty()) { - simplePut(datastore, path, rWTransaction, schemaContext, payload); - } else { - rWTransaction.delete(datastore, path.getParent()); - simplePut(datastore, path, rWTransaction, schemaContext, payload); - makePut(rWTransaction, datastore, path.getParent(), readList, schemaContext); - } + makePut(rwTransaction, datastore, path, payload, schemaContext); + return; + } + + final DataSchemaNode schemaNode = checkListAndOrderedType(schemaContext, path); + checkItemDoesNotExists(rwTransaction, datastore, path); + switch (insert) { + case "first": + if (schemaNode instanceof ListSchemaNode) { + final OrderedMapNode readList = + (OrderedMapNode) this.readConfigurationData(path.getParent()); + if (readList == null || readList.getValue().isEmpty()) { + simplePut(datastore, path, rwTransaction, schemaContext, payload); } else { - final OrderedLeafSetNode readLeafList = - (OrderedLeafSetNode) readConfigurationData(path.getParent()); - if (readLeafList == null || readLeafList.getValue().isEmpty()) { - simplePut(datastore, path, rWTransaction, schemaContext, payload); - } else { - rWTransaction.delete(datastore, path.getParent()); - simplePut(datastore, path, rWTransaction, schemaContext, payload); - makePut(rWTransaction, datastore, path.getParent(), readLeafList, - schemaContext); - } + rwTransaction.delete(datastore, path.getParent()); + simplePut(datastore, path, rwTransaction, schemaContext, payload); + makePut(rwTransaction, datastore, path.getParent(), readList, schemaContext); } - break; - case "last": - simplePut(datastore, path, rWTransaction, schemaContext, payload); - break; - case "before": - if (schemaNode instanceof ListSchemaNode) { - final OrderedMapNode readList = - (OrderedMapNode) this.readConfigurationData(path.getParent()); - if (readList == null || readList.getValue().isEmpty()) { - simplePut(datastore, path, rWTransaction, schemaContext, payload); - } else { - insertWithPointListPut(rWTransaction, datastore, path, payload, schemaContext, point, - readList, true); - } + } else { + final OrderedLeafSetNode readLeafList = + (OrderedLeafSetNode) readConfigurationData(path.getParent()); + if (readLeafList == null || readLeafList.getValue().isEmpty()) { + simplePut(datastore, path, rwTransaction, schemaContext, payload); } else { - final OrderedLeafSetNode readLeafList = - (OrderedLeafSetNode) readConfigurationData(path.getParent()); - if (readLeafList == null || readLeafList.getValue().isEmpty()) { - simplePut(datastore, path, rWTransaction, schemaContext, payload); - } else { - insertWithPointLeafListPut(rWTransaction, datastore, path, payload, schemaContext, point, - readLeafList, true); - } + rwTransaction.delete(datastore, path.getParent()); + simplePut(datastore, path, rwTransaction, schemaContext, payload); + makePut(rwTransaction, datastore, path.getParent(), readLeafList, + schemaContext); } - break; - case "after": - if (schemaNode instanceof ListSchemaNode) { - final OrderedMapNode readList = - (OrderedMapNode) this.readConfigurationData(path.getParent()); - if (readList == null || readList.getValue().isEmpty()) { - simplePut(datastore, path, rWTransaction, schemaContext, payload); - } else { - insertWithPointListPut(rWTransaction, datastore, path, payload, schemaContext, point, - readList, false); - } + } + break; + case "last": + simplePut(datastore, path, rwTransaction, schemaContext, payload); + break; + case "before": + if (schemaNode instanceof ListSchemaNode) { + final OrderedMapNode readList = + (OrderedMapNode) this.readConfigurationData(path.getParent()); + if (readList == null || readList.getValue().isEmpty()) { + simplePut(datastore, path, rwTransaction, schemaContext, payload); } else { - final OrderedLeafSetNode readLeafList = - (OrderedLeafSetNode) readConfigurationData(path.getParent()); - if (readLeafList == null || readLeafList.getValue().isEmpty()) { - simplePut(datastore, path, rWTransaction, schemaContext, payload); - } else { - insertWithPointLeafListPut(rWTransaction, datastore, path, payload, schemaContext, point, - readLeafList, false); - } + insertWithPointListPut(rwTransaction, datastore, path, payload, schemaContext, point, + readList, true); } - break; - default: - throw new RestconfDocumentedException( - "Used bad value of insert parameter. Possible values are first, last, before or after, " - + "but was: " + insert); - } + } else { + final OrderedLeafSetNode readLeafList = + (OrderedLeafSetNode) readConfigurationData(path.getParent()); + if (readLeafList == null || readLeafList.getValue().isEmpty()) { + simplePut(datastore, path, rwTransaction, schemaContext, payload); + } else { + insertWithPointLeafListPut(rwTransaction, datastore, path, payload, schemaContext, point, + readLeafList, true); + } + } + break; + case "after": + if (schemaNode instanceof ListSchemaNode) { + final OrderedMapNode readList = + (OrderedMapNode) this.readConfigurationData(path.getParent()); + if (readList == null || readList.getValue().isEmpty()) { + simplePut(datastore, path, rwTransaction, schemaContext, payload); + } else { + insertWithPointListPut(rwTransaction, datastore, path, payload, schemaContext, point, + readList, false); + } + } else { + final OrderedLeafSetNode readLeafList = + (OrderedLeafSetNode) readConfigurationData(path.getParent()); + if (readLeafList == null || readLeafList.getValue().isEmpty()) { + simplePut(datastore, path, rwTransaction, schemaContext, payload); + } else { + insertWithPointLeafListPut(rwTransaction, datastore, path, payload, schemaContext, point, + readLeafList, false); + } + } + break; + default: + throw new RestconfDocumentedException( + "Used bad value of insert parameter. Possible values are first, last, before or after, but was: " + + insert); } } - private static void insertWithPointLeafListPut(final DOMDataReadWriteTransaction rWTransaction, + private static void insertWithPointLeafListPut(final DOMDataWriteTransaction tx, final LogicalDatastoreType datastore, final YangInstanceIdentifier path, final NormalizedNode payload, final SchemaContext schemaContext, final String point, final OrderedLeafSetNode readLeafList, final boolean before) { - rWTransaction.delete(datastore, path.getParent()); + tx.delete(datastore, path.getParent()); final InstanceIdentifierContext instanceIdentifier = ControllerContext.getInstance().toInstanceIdentifier(point); - int p = 0; + int index1 = 0; for (final LeafSetEntryNode nodeChild : readLeafList.getValue()) { if (nodeChild.getIdentifier().equals(instanceIdentifier.getInstanceIdentifier().getLastPathArgument())) { break; } - p++; + index1++; } if (!before) { - p++; + index1++; } - int h = 0; + int index2 = 0; final NormalizedNode emptySubtree = ImmutableNodes.fromInstanceId(schemaContext, path.getParent()); - rWTransaction.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree); + tx.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree); for (final LeafSetEntryNode nodeChild : readLeafList.getValue()) { - if (h == p) { - simplePut(datastore, path, rWTransaction, schemaContext, payload); + if (index2 == index1) { + simplePut(datastore, path, tx, schemaContext, payload); } final YangInstanceIdentifier childPath = path.getParent().node(nodeChild.getIdentifier()); - rWTransaction.put(datastore, childPath, nodeChild); - h++; + tx.put(datastore, childPath, nodeChild); + index2++; } } - private static void insertWithPointListPut(final DOMDataReadWriteTransaction rWTransaction, - final LogicalDatastoreType datastore, final YangInstanceIdentifier path, final NormalizedNode payload, - final SchemaContext schemaContext, final String point, final OrderedMapNode readList, - final boolean before) { - rWTransaction.delete(datastore, path.getParent()); + private static void insertWithPointListPut(final DOMDataWriteTransaction tx, final LogicalDatastoreType datastore, + final YangInstanceIdentifier path, final NormalizedNode payload, final SchemaContext schemaContext, + final String point, final OrderedMapNode readList, final boolean before) { + tx.delete(datastore, path.getParent()); final InstanceIdentifierContext instanceIdentifier = ControllerContext.getInstance().toInstanceIdentifier(point); - int p = 0; + int index1 = 0; for (final MapEntryNode mapEntryNode : readList.getValue()) { if (mapEntryNode.getIdentifier().equals(instanceIdentifier.getInstanceIdentifier().getLastPathArgument())) { break; } - p++; + index1++; } if (!before) { - p++; + index1++; } - int h = 0; + int index2 = 0; final NormalizedNode emptySubtree = ImmutableNodes.fromInstanceId(schemaContext, path.getParent()); - rWTransaction.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree); + tx.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree); for (final MapEntryNode mapEntryNode : readList.getValue()) { - if (h == p) { - simplePut(datastore, path, rWTransaction, schemaContext, payload); + if (index2 == index1) { + simplePut(datastore, path, tx, schemaContext, payload); } final YangInstanceIdentifier childPath = path.getParent().node(mapEntryNode.getIdentifier()); - rWTransaction.put(datastore, childPath, mapEntryNode); - h++; + tx.put(datastore, childPath, mapEntryNode); + index2++; } } - private static void makePut(final DOMDataReadWriteTransaction writeTransaction, - final LogicalDatastoreType datastore, final YangInstanceIdentifier path, final NormalizedNode payload, - final SchemaContext schemaContext) { + private static void makePut(final DOMDataWriteTransaction tx, final LogicalDatastoreType datastore, + final YangInstanceIdentifier path, final NormalizedNode payload, final SchemaContext schemaContext) { if (payload instanceof MapNode) { final NormalizedNode emptySubtree = ImmutableNodes.fromInstanceId(schemaContext, path); - writeTransaction.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree); - ensureParentsByMerge(datastore, path, writeTransaction, schemaContext); + tx.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree); + ensureParentsByMerge(datastore, path, tx, schemaContext); for (final MapEntryNode child : ((MapNode) payload).getValue()) { final YangInstanceIdentifier childPath = path.node(child.getIdentifier()); - writeTransaction.put(datastore, childPath, child); + tx.put(datastore, childPath, child); } } else { - simplePut(datastore, path, writeTransaction, schemaContext, payload); + simplePut(datastore, path, tx, schemaContext, payload); } } private static void simplePut(final LogicalDatastoreType datastore, final YangInstanceIdentifier path, - final DOMDataReadWriteTransaction writeTransaction, final SchemaContext schemaContext, - final NormalizedNode payload) { - ensureParentsByMerge(datastore, path, writeTransaction, schemaContext); - writeTransaction.put(datastore, path, payload); + final DOMDataWriteTransaction tx, final SchemaContext schemaContext, final NormalizedNode payload) { + ensureParentsByMerge(datastore, path, tx, schemaContext); + tx.put(datastore, path, payload); } private static CheckedFuture deleteDataViaTransaction( @@ -1161,21 +1192,21 @@ public class BrokerFacade { return readWriteTransaction.submit(); } - private static void deleteDataWithinTransaction(final DOMDataWriteTransaction writeTransaction, + private static void deleteDataWithinTransaction(final DOMDataWriteTransaction tx, final LogicalDatastoreType datastore, final YangInstanceIdentifier path) { - LOG.trace("Delete {} within Restconf PATCH: {}", datastore.name(), path); - writeTransaction.delete(datastore, path); + LOG.trace("Delete {} within Restconf Patch: {}", datastore.name(), path); + tx.delete(datastore, path); } - private static 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); + private static void mergeDataWithinTransaction(final DOMDataWriteTransaction tx, + 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, tx, schemaContext); // Since YANG Patch provides the option to specify what kind of operation for each edit, // OpenDaylight should not change it. - writeTransaction.merge(datastore, path, payload); + tx.merge(datastore, path, payload); } public void setDomDataBroker(final DOMDataBroker domDataBroker) { @@ -1196,20 +1227,8 @@ public class BrokerFacade { listener.setRegistration(registration); } - private final class PATCHStatusContextHelper { - PATCHStatusContext status; - - public PATCHStatusContext getStatus() { - return this.status; - } - - public void setStatus(final PATCHStatusContext status) { - this.status = status; - } - } - private static void ensureParentsByMerge(final LogicalDatastoreType store, - final YangInstanceIdentifier normalizedPath, final DOMDataReadWriteTransaction rwTx, + final YangInstanceIdentifier normalizedPath, final DOMDataWriteTransaction tx, final SchemaContext schemaContext) { final List normalizedPathWithoutChildArgs = new ArrayList<>(); YangInstanceIdentifier rootNormalizedPath = null; @@ -1235,6 +1254,18 @@ public class BrokerFacade { final NormalizedNode parentStructure = ImmutableNodes.fromInstanceId(schemaContext, YangInstanceIdentifier.create(normalizedPathWithoutChildArgs)); - rwTx.merge(store, rootNormalizedPath, parentStructure); + tx.merge(store, rootNormalizedPath, parentStructure); + } + + private static final class PatchStatusContextHelper { + PatchStatusContext status; + + public PatchStatusContext getStatus() { + return this.status; + } + + public void setStatus(final PatchStatusContext status) { + this.status = status; + } } }