From 2945350314dfc6309d5aaf3bc5c08b6e7abaff95 Mon Sep 17 00:00:00 2001 From: Jakub Toth Date: Thu, 4 Aug 2016 09:26:41 -0400 Subject: [PATCH] Bug 6325 - upgrade draft11 to draft15 - added timestamp & etag *fixed read of data from datastore Change-Id: I629c909ba05f93f4d662199a86637e966cb6d8e1 Signed-off-by: Jakub Toth --- .../restconf/RestConnectorProvider.java | 27 +++++---- .../services/Draft15ServicesWrapperImpl.java | 2 +- .../services/api/RestconfDataService.java | 2 +- .../impl/RestconfDataServiceImpl.java | 47 +++++++++------ .../transaction/TransactionVarsWrapper.java | 23 ++++---- .../utils/DeleteDataTransactionUtil.java | 3 +- .../utils/PatchDataTransactionUtil.java | 25 ++++---- .../utils/PostDataTransactionUtil.java | 2 +- .../restful/utils/PutDataTransactionUtil.java | 2 +- .../utils/ReadDataTransactionUtil.java | 57 +++++++++++++++---- .../utils/DeleteDataTransactionUtilTest.java | 25 +++++--- 11 files changed, 135 insertions(+), 80 deletions(-) diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/RestConnectorProvider.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/RestConnectorProvider.java index dedea9b0a6..7c7ae377e1 100644 --- a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/RestConnectorProvider.java +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/RestConnectorProvider.java @@ -41,12 +41,11 @@ public class RestConnectorProvider implements Provider, RestConnector, AutoClose private static final Logger LOG = LoggerFactory.getLogger(RestConnectorProvider.class); - private final TransactionChainListener transactionListener = new TransactionChainListener() { + public static final TransactionChainListener transactionListener = new TransactionChainListener() { @Override public void onTransactionChainFailed(final TransactionChain chain, final AsyncTransaction transaction, final Throwable cause) { LOG.warn("TransactionChain({}) {} FAILED!", chain, transaction.getIdentifier(), cause); - chain.close(); resetTransactionChainForAdapaters(chain); throw new RestconfDocumentedException("TransactionChain(" + chain + ") not committed correctly", cause); } @@ -58,8 +57,8 @@ public class RestConnectorProvider implements Provider, RestConnector, AutoClose }; private ListenerRegistration listenerRegistration; - private DOMDataBroker dataBroker; - private DOMTransactionChain transactionChain; + private static DOMDataBroker dataBroker; + private static DOMTransactionChain transactionChain; @Override public void onSessionInitiated(final ProviderSession session) { @@ -73,11 +72,11 @@ public class RestConnectorProvider implements Provider, RestConnector, AutoClose final DOMMountPointServiceHandler domMountPointServiceHandler = new DOMMountPointServiceHandler( session.getService(DOMMountPointService.class)); - this.dataBroker = session.getService(DOMDataBroker.class); - final DOMDataBrokerHandler brokerHandler = new DOMDataBrokerHandler(this.dataBroker); + dataBroker = session.getService(DOMDataBroker.class); + final DOMDataBrokerHandler brokerHandler = new DOMDataBrokerHandler(dataBroker); - this.transactionChain = this.dataBroker.createTransactionChain(this.transactionListener); - final TransactionChainHandler transactionChainHandler = new TransactionChainHandler(this.transactionChain); + transactionChain = dataBroker.createTransactionChain(transactionListener); + final TransactionChainHandler transactionChainHandler = new TransactionChainHandler(transactionChain); final DOMRpcService rpcService = session.getService(DOMRpcService.class); final RpcServiceHandler rpcServiceHandler = new RpcServiceHandler(rpcService); @@ -93,10 +92,10 @@ public class RestConnectorProvider implements Provider, RestConnector, AutoClose * @param chain * - old {@link TransactionChain} */ - private void resetTransactionChainForAdapaters(final TransactionChain chain) { - LOG.trace("Resetting TransactionChain({}) to {}", chain, this.transactionChain); - this.transactionChain = Preconditions.checkNotNull(this.dataBroker) - .createTransactionChain(this.transactionListener); + public static void resetTransactionChainForAdapaters(final TransactionChain chain) { + LOG.trace("Resetting TransactionChain({}) to {}", chain, transactionChain); + chain.close(); + transactionChain = Preconditions.checkNotNull(dataBroker).createTransactionChain(transactionListener); } @Override @@ -109,8 +108,8 @@ public class RestConnectorProvider implements Provider, RestConnector, AutoClose if (this.listenerRegistration != null) { this.listenerRegistration.close(); } - if (this.transactionChain != null) { - this.transactionChain.close(); + if (transactionChain != null) { + transactionChain.close(); } } } diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/common/wrapper/services/Draft15ServicesWrapperImpl.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/common/wrapper/services/Draft15ServicesWrapperImpl.java index 713bea1b5f..507914b6cb 100644 --- a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/common/wrapper/services/Draft15ServicesWrapperImpl.java +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/common/wrapper/services/Draft15ServicesWrapperImpl.java @@ -102,7 +102,7 @@ public class Draft15ServicesWrapperImpl implements Draft15BaseServicesWrapper, D } @Override - public NormalizedNodeContext readData(final String identifier, final UriInfo uriInfo) { + public Response readData(final String identifier, final UriInfo uriInfo) { return this.delegRestconfDataService.readData(identifier, uriInfo); } diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/services/api/RestconfDataService.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/services/api/RestconfDataService.java index 12bbf9f78e..f1f3b7e348 100644 --- a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/services/api/RestconfDataService.java +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/services/api/RestconfDataService.java @@ -47,7 +47,7 @@ public interface RestconfDataService { @Path("/data/{identifier:.+}") @Produces({ Draft15.MediaTypes.DATA + RestconfConstants.JSON, Draft15.MediaTypes.DATA, MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML }) - NormalizedNodeContext readData(@Encoded @PathParam("identifier") String identifier, + Response readData(@Encoded @PathParam("identifier") String identifier, @Context UriInfo uriInfo); /** diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/services/impl/RestconfDataServiceImpl.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/services/impl/RestconfDataServiceImpl.java index a6187f5fa3..95645334cb 100644 --- a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/services/impl/RestconfDataServiceImpl.java +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/services/impl/RestconfDataServiceImpl.java @@ -9,16 +9,20 @@ package org.opendaylight.restconf.restful.services.impl; import com.google.common.base.Optional; import com.google.common.base.Preconditions; +import java.text.SimpleDateFormat; +import java.util.TimeZone; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker; import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction; import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint; +import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain; import org.opendaylight.netconf.sal.restconf.impl.InstanceIdentifierContext; import org.opendaylight.netconf.sal.restconf.impl.NormalizedNodeContext; import org.opendaylight.netconf.sal.restconf.impl.PATCHContext; import org.opendaylight.netconf.sal.restconf.impl.PATCHStatusContext; import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException; +import org.opendaylight.restconf.RestConnectorProvider; import org.opendaylight.restconf.common.references.SchemaContextRef; import org.opendaylight.restconf.handlers.SchemaContextHandler; import org.opendaylight.restconf.handlers.TransactionChainHandler; @@ -53,25 +57,36 @@ public class RestconfDataServiceImpl implements RestconfDataService { } @Override - public NormalizedNodeContext readData(final String identifier, final UriInfo uriInfo) { + public Response readData(final String identifier, final UriInfo uriInfo) { Preconditions.checkNotNull(identifier); final SchemaContextRef schemaContextRef = new SchemaContextRef(this.schemaContextHandler.get()); - final InstanceIdentifierContext instanceIdentifier = ParserIdentifier.toInstanceIdentifier(identifier, schemaContextRef.get()); + final InstanceIdentifierContext instanceIdentifier = ParserIdentifier.toInstanceIdentifier(identifier, + schemaContextRef.get()); final DOMMountPoint mountPoint = instanceIdentifier.getMountPoint(); final String value = uriInfo.getQueryParameters().getFirst(RestconfDataServiceConstant.CONTENT); - DOMDataReadWriteTransaction transaction = null; + DOMTransactionChain transaction = null; if (mountPoint == null) { - transaction = this.transactionChainHandler.get().newReadWriteTransaction(); + transaction = this.transactionChainHandler.get(); } else { transaction = transactionOfMountPoint(mountPoint); } final TransactionVarsWrapper transactionNode = new TransactionVarsWrapper(instanceIdentifier, mountPoint, transaction); final NormalizedNode node = ReadDataTransactionUtil.readData(value, transactionNode); - - return new NormalizedNodeContext(instanceIdentifier, node); + final SimpleDateFormat dateFormatGmt = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss"); + dateFormatGmt.setTimeZone(TimeZone.getTimeZone("GMT")); + final String etag = '"' + node.getNodeType().getModule().getFormattedRevision() + + node.getNodeType().getLocalName() + '"'; + Response resp = null; + if ((value == null) || value.contains(RestconfDataServiceConstant.ReadData.CONFIG)) { + resp = Response.status(200).entity(new NormalizedNodeContext(instanceIdentifier, node)).header("ETag", etag) + .header("Last-Modified", dateFormatGmt.toString()).build(); + } else { + resp = Response.status(200).entity(new NormalizedNodeContext(instanceIdentifier, node)).build(); + } + return resp; } @Override @@ -87,10 +102,10 @@ public class RestconfDataServiceImpl implements RestconfDataService { PutDataTransactionUtil.validateListKeysEqualityInPayloadAndUri(payload); final DOMMountPoint mountPoint = payload.getInstanceIdentifierContext().getMountPoint(); - DOMDataReadWriteTransaction transaction = null; + DOMTransactionChain transaction = null; SchemaContextRef ref = null; if (mountPoint == null) { - transaction = this.transactionChainHandler.get().newReadWriteTransaction(); + transaction = this.transactionChainHandler.get(); ref = new SchemaContextRef(this.schemaContextHandler.get()); } else { transaction = transactionOfMountPoint(mountPoint); @@ -112,10 +127,10 @@ public class RestconfDataServiceImpl implements RestconfDataService { Preconditions.checkNotNull(payload); final DOMMountPoint mountPoint = payload.getInstanceIdentifierContext().getMountPoint(); - DOMDataReadWriteTransaction transaction = null; + DOMTransactionChain transaction = null; SchemaContextRef ref = null; if (mountPoint == null) { - transaction = this.transactionChainHandler.get().newReadWriteTransaction(); + transaction = this.transactionChainHandler.get(); ref = new SchemaContextRef(this.schemaContextHandler.get()); } else { transaction = transactionOfMountPoint(mountPoint); @@ -133,9 +148,9 @@ public class RestconfDataServiceImpl implements RestconfDataService { schemaContextRef.get()); final DOMMountPoint mountPoint = instanceIdentifier.getMountPoint(); - final DOMDataReadWriteTransaction transaction; + final DOMTransactionChain transaction; if (mountPoint == null) { - transaction = this.transactionChainHandler.get().newReadWriteTransaction(); + transaction = this.transactionChainHandler.get(); } else { transaction = transactionOfMountPoint(mountPoint); } @@ -156,10 +171,10 @@ public class RestconfDataServiceImpl implements RestconfDataService { Preconditions.checkNotNull(context); final DOMMountPoint mountPoint = context.getInstanceIdentifierContext().getMountPoint(); - final DOMDataReadWriteTransaction transaction; + final DOMTransactionChain transaction; final SchemaContextRef ref; if (mountPoint == null) { - transaction = this.transactionChainHandler.get().newReadWriteTransaction(); + transaction = this.transactionChainHandler.get(); ref = new SchemaContextRef(this.schemaContextHandler.get()); } else { transaction = transactionOfMountPoint(mountPoint); @@ -178,10 +193,10 @@ public class RestconfDataServiceImpl implements RestconfDataService { * @param mountPoint * @return {@link DOMDataReadWriteTransaction} */ - private static DOMDataReadWriteTransaction transactionOfMountPoint(final DOMMountPoint mountPoint) { + private static DOMTransactionChain transactionOfMountPoint(final DOMMountPoint mountPoint) { final Optional domDataBrokerService = mountPoint.getService(DOMDataBroker.class); if (domDataBrokerService.isPresent()) { - return domDataBrokerService.get().newReadWriteTransaction(); + return domDataBrokerService.get().createTransactionChain(RestConnectorProvider.transactionListener); } else { final String errMsg = "DOM data broker service isn't available for mount point " + mountPoint.getIdentifier(); diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/transaction/TransactionVarsWrapper.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/transaction/TransactionVarsWrapper.java index 1789d30933..23b3875f86 100644 --- a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/transaction/TransactionVarsWrapper.java +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/transaction/TransactionVarsWrapper.java @@ -8,8 +8,8 @@ package org.opendaylight.restconf.restful.transaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; -import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction; import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint; +import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain; import org.opendaylight.netconf.sal.restconf.impl.InstanceIdentifierContext; /** @@ -21,7 +21,7 @@ public final class TransactionVarsWrapper { private final InstanceIdentifierContext instanceIdentifier; private final DOMMountPoint mountPoint; private LogicalDatastoreType configuration = null; - private final DOMDataReadWriteTransaction transaction; + private final DOMTransactionChain transactionChain; /** * Set base type of variables, which ones we need for transaction. @@ -32,15 +32,15 @@ public final class TransactionVarsWrapper { * - {@link InstanceIdentifierContext} of data for transaction * @param mountPoint * - mount point if is present - * @param transaction - * - {@link DOMDataReadWriteTransaction} transaction for - * operations + * @param transactionChain + * - transaction chain for creating specific type of transaction + * in specific operation */ public TransactionVarsWrapper(final InstanceIdentifierContext instanceIdentifier, final DOMMountPoint mountPoint, - final DOMDataReadWriteTransaction transaction) { + final DOMTransactionChain transactionChain) { this.instanceIdentifier = instanceIdentifier; this.mountPoint = mountPoint; - this.transaction = transaction; + this.transactionChain = transactionChain; } /** @@ -82,11 +82,12 @@ public final class TransactionVarsWrapper { } /** - * Get specific type of transaction + * Get transaction chain for creating specific transaction for specific + * operation * - * @return specific type transaction + * @return transaction chain */ - public DOMDataReadWriteTransaction getTransaction() { - return this.transaction; + public DOMTransactionChain getTransactionChain() { + return this.transactionChain; } } diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/DeleteDataTransactionUtil.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/DeleteDataTransactionUtil.java index 53c19c5fe9..15d1f1c95d 100644 --- a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/DeleteDataTransactionUtil.java +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/DeleteDataTransactionUtil.java @@ -34,7 +34,8 @@ public final class DeleteDataTransactionUtil { */ public static Response deleteData(final TransactionVarsWrapper transactionNode) { final CheckedFuture future = submitData( - transactionNode.getTransaction(), transactionNode.getInstanceIdentifier().getInstanceIdentifier()); + transactionNode.getTransactionChain().newReadWriteTransaction(), + transactionNode.getInstanceIdentifier().getInstanceIdentifier()); final ResponseFactory response = new ResponseFactory(); FutureCallbackTx.addCallback(future, RestconfDataServiceConstant.DeleteData.DELETE_TX_TYPE, response); return response.build(); diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/PatchDataTransactionUtil.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/PatchDataTransactionUtil.java index 09cdf6a6e2..0b350a7667 100644 --- a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/PatchDataTransactionUtil.java +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/PatchDataTransactionUtil.java @@ -26,6 +26,7 @@ import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException; import org.opendaylight.netconf.sal.restconf.impl.RestconfError; import org.opendaylight.netconf.sal.restconf.impl.RestconfError.ErrorTag; import org.opendaylight.netconf.sal.restconf.impl.RestconfError.ErrorType; +import org.opendaylight.restconf.RestConnectorProvider; import org.opendaylight.restconf.common.references.SchemaContextRef; import org.opendaylight.restconf.restful.transaction.TransactionVarsWrapper; import org.opendaylight.restconf.restful.utils.RestconfDataServiceConstant.PatchData; @@ -56,6 +57,7 @@ public final class PatchDataTransactionUtil { final SchemaContextRef schemaContextRef) { final List editCollection = new ArrayList<>(); int errorCounter = 0; + final DOMDataReadWriteTransaction tx = transactionNode.getTransactionChain().newReadWriteTransaction(); for (final PATCHEntity patchEntity : context.getData()) { final PATCHEditOperation operation = PATCHEditOperation.valueOf(patchEntity.getOperation().toUpperCase()); @@ -65,8 +67,7 @@ public final class PatchDataTransactionUtil { if (errorCounter == 0) { try { createDataWithinTransaction(LogicalDatastoreType.CONFIGURATION, - patchEntity.getTargetNode(), patchEntity.getNode(), - transactionNode.getTransaction(), schemaContextRef); + patchEntity.getTargetNode(), patchEntity.getNode(), tx, schemaContextRef); editCollection.add(new PATCHStatusEntity(patchEntity.getEditId(), true, null)); } catch (final RestconfDocumentedException e) { editCollection.add(new PATCHStatusEntity(patchEntity.getEditId(), @@ -78,8 +79,8 @@ public final class PatchDataTransactionUtil { case DELETE: if (errorCounter == 0) { try { - deleteDataWithinTransaction(LogicalDatastoreType.CONFIGURATION, - patchEntity.getTargetNode(), transactionNode.getTransaction()); + deleteDataWithinTransaction(LogicalDatastoreType.CONFIGURATION, patchEntity.getTargetNode(), + tx); editCollection.add(new PATCHStatusEntity(patchEntity.getEditId(), true, null)); } catch (final RestconfDocumentedException e) { editCollection.add(new PATCHStatusEntity(patchEntity.getEditId(), @@ -92,8 +93,7 @@ public final class PatchDataTransactionUtil { if (errorCounter == 0) { try { mergeDataWithinTransaction(LogicalDatastoreType.CONFIGURATION, - patchEntity.getTargetNode(), patchEntity.getNode(), transactionNode.getTransaction(), - schemaContextRef); + patchEntity.getTargetNode(), patchEntity.getNode(), tx, schemaContextRef); editCollection.add(new PATCHStatusEntity(patchEntity.getEditId(), true, null)); } catch (final RestconfDocumentedException e) { editCollection.add(new PATCHStatusEntity(patchEntity.getEditId(), @@ -106,8 +106,7 @@ public final class PatchDataTransactionUtil { if (errorCounter == 0) { try { replaceDataWithinTransaction(LogicalDatastoreType.CONFIGURATION, - patchEntity.getTargetNode(), patchEntity.getNode(), schemaContextRef, - transactionNode.getTransaction()); + patchEntity.getTargetNode(), patchEntity.getNode(), schemaContextRef, tx); editCollection.add(new PATCHStatusEntity(patchEntity.getEditId(), true, null)); } catch (final RestconfDocumentedException e) { editCollection.add(new PATCHStatusEntity(patchEntity.getEditId(), @@ -119,8 +118,8 @@ public final class PatchDataTransactionUtil { case REMOVE: if (errorCounter == 0) { try { - removeDataWithinTransaction(LogicalDatastoreType.CONFIGURATION, - patchEntity.getTargetNode(), transactionNode.getTransaction()); + removeDataWithinTransaction(LogicalDatastoreType.CONFIGURATION, patchEntity.getTargetNode(), + tx); editCollection.add(new PATCHStatusEntity(patchEntity.getEditId(), true, null)); } catch (final RestconfDocumentedException e) { editCollection.add(new PATCHStatusEntity(patchEntity.getEditId(), @@ -141,8 +140,7 @@ public final class PatchDataTransactionUtil { // if no errors then submit transaction, otherwise cancel if (errorCounter == 0) { final ResponseFactory response = new ResponseFactory(); - final CheckedFuture future = transactionNode - .getTransaction().submit(); + final CheckedFuture future = tx.submit(); try { FutureCallbackTx.addCallback(future, PatchData.PATCH_TX_TYPE, response); @@ -154,7 +152,8 @@ public final class PatchDataTransactionUtil { return new PATCHStatusContext(context.getPatchId(), ImmutableList.copyOf(editCollection), true, null); } else { - transactionNode.getTransaction().cancel(); + tx.cancel(); + RestConnectorProvider.resetTransactionChainForAdapaters(transactionNode.getTransactionChain()); return new PATCHStatusContext(context.getPatchId(), ImmutableList.copyOf(editCollection), false, null); } } diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/PostDataTransactionUtil.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/PostDataTransactionUtil.java index 778acd9734..bc464069e0 100644 --- a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/PostDataTransactionUtil.java +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/PostDataTransactionUtil.java @@ -89,7 +89,7 @@ public final class PostDataTransactionUtil { private static CheckedFuture submitData(final YangInstanceIdentifier path, final NormalizedNode data, final TransactionVarsWrapper transactionNode, final SchemaContext schemaContext) { - final DOMDataReadWriteTransaction transaction = transactionNode.getTransaction(); + final DOMDataReadWriteTransaction transaction = transactionNode.getTransactionChain().newReadWriteTransaction(); final NormalizedNode node = ImmutableNodes.fromInstanceId(schemaContext, path); transaction.put(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.create(node.getIdentifier()), node); TransactionUtil.ensureParentsByMerge(path, schemaContext, transaction); diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/PutDataTransactionUtil.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/PutDataTransactionUtil.java index d0302cfcd3..8db0b433f4 100644 --- a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/PutDataTransactionUtil.java +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/PutDataTransactionUtil.java @@ -139,7 +139,7 @@ public final class PutDataTransactionUtil { final ResponseFactory responseFactory = new ResponseFactory( ReadDataTransactionUtil.readData(RestconfDataServiceConstant.ReadData.CONFIG, transactionNode)); final CheckedFuture submitData = submitData(path, schemaCtxRef.get(), - transactionNode.getTransaction(), payload.getData()); + transactionNode.getTransactionChain().newWriteOnlyTransaction(), payload.getData()); FutureCallbackTx.addCallback(submitData, RestconfDataServiceConstant.PutData.PUT_TX_TYPE, responseFactory); return responseFactory.build(); } diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/ReadDataTransactionUtil.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/ReadDataTransactionUtil.java index 425f23bf70..5f0d995b00 100644 --- a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/ReadDataTransactionUtil.java +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/ReadDataTransactionUtil.java @@ -10,6 +10,7 @@ package org.opendaylight.restconf.restful.utils; import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.util.concurrent.CheckedFuture; +import java.util.Collection; import javax.annotation.Nonnull; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; @@ -18,6 +19,7 @@ import org.opendaylight.netconf.sal.restconf.impl.RestconfError.ErrorTag; import org.opendaylight.netconf.sal.restconf.impl.RestconfError.ErrorType; import org.opendaylight.restconf.restful.transaction.TransactionVarsWrapper; import org.opendaylight.yangtools.yang.common.QNameModule; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode; @@ -30,7 +32,9 @@ import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode; import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode; import org.opendaylight.yangtools.yang.data.api.schema.MapNode; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import org.opendaylight.yangtools.yang.data.impl.schema.Builders; import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder; import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder; import org.opendaylight.yangtools.yang.model.api.RpcDefinition; @@ -90,7 +94,7 @@ public final class ReadDataTransactionUtil { private static NormalizedNode readDataViaTransaction(final TransactionVarsWrapper transactionNode) { if (transactionNode.getLogicalDatastoreType() != null) { final CheckedFuture>, ReadFailedException> listenableFuture = transactionNode - .getTransaction().read(transactionNode.getLogicalDatastoreType(), + .getTransactionChain().newReadOnlyTransaction().read(transactionNode.getLogicalDatastoreType(), transactionNode.getInstanceIdentifier().getInstanceIdentifier()); final NormalizedNodeFactory dataFactory = new NormalizedNodeFactory(); FutureCallbackTx.addCallback(listenableFuture, RestconfDataServiceConstant.ReadData.READ_TYPE_TX, @@ -118,7 +122,7 @@ public final class ReadDataTransactionUtil { final NormalizedNode configDataNode = readDataViaTransaction(transactionNode); // if no data exists - if (stateDataNode == null && configDataNode == null) { + if ((stateDataNode == null) && (configDataNode == null)) { throw new RestconfDocumentedException( "Request could not be completed because the relevant data model content does not exist", ErrorType.PROTOCOL, @@ -209,21 +213,50 @@ public final class ReadDataTransactionUtil { */ private static NormalizedNode prepareData(final NormalizedNode configDataNode, final NormalizedNode stateDataNode) { - final MapNode immutableStateData = ImmutableNodes.mapNodeBuilder(stateDataNode.getNodeType()) + + if (configDataNode instanceof MapNode) { // part for lists mapping + final MapNode immutableStateData = ImmutableNodes.mapNodeBuilder(stateDataNode.getNodeType()) .addChild((MapEntryNode) stateDataNode).build(); - final MapNode immutableConfigData = ImmutableNodes.mapNodeBuilder(configDataNode.getNodeType()) + final MapNode immutableConfigData = ImmutableNodes.mapNodeBuilder(configDataNode.getNodeType()) .addChild((MapEntryNode) configDataNode).build(); - - final DataContainerNodeBuilder mapEntryBuilder = ImmutableNodes + final DataContainerNodeBuilder mapEntryBuilder = ImmutableNodes .mapEntryBuilder(); - mapEntryBuilder.withNodeIdentifier((NodeIdentifierWithPredicates) configDataNode.getIdentifier()); + mapEntryBuilder.withNodeIdentifier((NodeIdentifierWithPredicates) configDataNode.getIdentifier()); - // MAP CONFIG DATA - mapDataNode(immutableConfigData, mapEntryBuilder); - // MAP STATE DATA - mapDataNode(immutableStateData, mapEntryBuilder); + // MAP CONFIG DATA + mapDataNode(immutableConfigData, mapEntryBuilder); + // MAP STATE DATA + mapDataNode(immutableStateData, mapEntryBuilder); + return ImmutableNodes.mapNodeBuilder(configDataNode.getNodeType()).addChild(mapEntryBuilder.build()).build(); + } else if (configDataNode instanceof ContainerNode) { // part for + // containers + // mapping + final DataContainerNodeAttrBuilder containerBuilder = Builders + .containerBuilder((ContainerNode) configDataNode); + // MAP CONFIG DATA + mapCont(containerBuilder, ((ContainerNode) configDataNode).getValue()); + // MAP STATE DATA + mapCont(containerBuilder, ((ContainerNode) stateDataNode).getValue()); - return ImmutableNodes.mapNodeBuilder(configDataNode.getNodeType()).addChild(mapEntryBuilder.build()).build(); + return containerBuilder.build(); + } else { + throw new RestconfDocumentedException("Bad type of node."); + } + } + + /** + * Map data to builder + * + * @param containerBuilder + * - builder for mapping data + * @param childs + * - childs of data (container) + */ + private static void mapCont(final DataContainerNodeAttrBuilder containerBuilder, + final Collection> childs) { + for (final DataContainerChild child : childs) { + containerBuilder.addChild(child); + } } /** diff --git a/restconf/sal-rest-connector/src/test/java/org/opendaylight/restconf/restful/utils/DeleteDataTransactionUtilTest.java b/restconf/sal-rest-connector/src/test/java/org/opendaylight/restconf/restful/utils/DeleteDataTransactionUtilTest.java index f867ab1d1a..f38923d952 100644 --- a/restconf/sal-rest-connector/src/test/java/org/opendaylight/restconf/restful/utils/DeleteDataTransactionUtilTest.java +++ b/restconf/sal-rest-connector/src/test/java/org/opendaylight/restconf/restful/utils/DeleteDataTransactionUtilTest.java @@ -10,7 +10,6 @@ package org.opendaylight.restconf.restful.utils; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; - import com.google.common.util.concurrent.Futures; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; @@ -21,6 +20,7 @@ import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction; +import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain; import org.opendaylight.netconf.sal.restconf.impl.InstanceIdentifierContext; import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException; import org.opendaylight.netconf.sal.restconf.impl.RestconfError.ErrorTag; @@ -29,14 +29,19 @@ import org.opendaylight.restconf.restful.transaction.TransactionVarsWrapper; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; public class DeleteDataTransactionUtilTest { - @Mock DOMDataReadWriteTransaction transaction; - @Mock InstanceIdentifierContext context; + @Mock + private DOMTransactionChain transactionChain; + @Mock + private InstanceIdentifierContext context; + @Mock + private DOMDataReadWriteTransaction readWrite; @Before public void init() throws Exception { MockitoAnnotations.initMocks(this); - Mockito.when(this.transaction.submit()).thenReturn(Futures.immediateCheckedFuture(null)); - Mockito.when(context.getInstanceIdentifier()).thenReturn(YangInstanceIdentifier.EMPTY); + Mockito.when(this.transactionChain.newReadWriteTransaction()).thenReturn(this.readWrite); + Mockito.when(this.readWrite.submit()).thenReturn(Futures.immediateCheckedFuture(null)); + Mockito.when(this.context.getInstanceIdentifier()).thenReturn(YangInstanceIdentifier.EMPTY); } /** @@ -45,12 +50,13 @@ public class DeleteDataTransactionUtilTest { @Test public void deleteData() throws Exception { // assert that data to delete exists - Mockito.when(this.transaction.exists(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.EMPTY)) + Mockito.when(this.transactionChain.newReadWriteTransaction().exists(LogicalDatastoreType.CONFIGURATION, + YangInstanceIdentifier.EMPTY)) .thenReturn(Futures.immediateCheckedFuture(Boolean.TRUE)); // test final Response response = DeleteDataTransactionUtil.deleteData( - new TransactionVarsWrapper(this.context, null, this.transaction)); + new TransactionVarsWrapper(this.context, null, this.transactionChain)); // assert success assertEquals("Not expected response received", Status.OK.getStatusCode(), response.getStatus()); @@ -62,12 +68,13 @@ public class DeleteDataTransactionUtilTest { @Test public void deleteDataNegativeTest() throws Exception { // assert that data to delete does NOT exist - Mockito.when(this.transaction.exists(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.EMPTY)) + Mockito.when(this.transactionChain.newReadWriteTransaction().exists(LogicalDatastoreType.CONFIGURATION, + YangInstanceIdentifier.EMPTY)) .thenReturn(Futures.immediateCheckedFuture(Boolean.FALSE)); // test and assert error try { - DeleteDataTransactionUtil.deleteData(new TransactionVarsWrapper(this.context, null, this.transaction)); + DeleteDataTransactionUtil.deleteData(new TransactionVarsWrapper(this.context, null, this.transactionChain)); fail("Delete operation should fail due to missing data"); } catch (final RestconfDocumentedException e) { assertEquals(ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType()); -- 2.36.6