X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=restconf%2Fsal-rest-connector%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Frestconf%2Frestful%2Fservices%2Fimpl%2FRestconfDataServiceImpl.java;h=bb42fbb9d55cf60e2c7a47cebe057a742c16f776;hb=d434f750405b4509121900b677a80402c077b422;hp=68f965206324ad604fba8a0df1d2dc1b1ce1b2b0;hpb=b2fd55e123e82a350337c3733e0809a6f8a02fb3;p=netconf.git 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 68f9652063..bb42fbb9d5 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,21 +9,34 @@ 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.Date; +import java.util.List; +import java.util.Map.Entry; +import java.util.TimeZone; +import javax.annotation.Nonnull; 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.netconf.sal.restconf.impl.RestconfError; +import org.opendaylight.netconf.sal.restconf.impl.WriterParameters; +import org.opendaylight.restconf.RestConnectorProvider; import org.opendaylight.restconf.common.references.SchemaContextRef; +import org.opendaylight.restconf.handlers.DOMMountPointServiceHandler; import org.opendaylight.restconf.handlers.SchemaContextHandler; import org.opendaylight.restconf.handlers.TransactionChainHandler; import org.opendaylight.restconf.restful.services.api.RestconfDataService; import org.opendaylight.restconf.restful.transaction.TransactionVarsWrapper; +import org.opendaylight.restconf.restful.utils.DeleteDataTransactionUtil; +import org.opendaylight.restconf.restful.utils.PatchDataTransactionUtil; +import org.opendaylight.restconf.restful.utils.PostDataTransactionUtil; import org.opendaylight.restconf.restful.utils.PutDataTransactionUtil; import org.opendaylight.restconf.restful.utils.ReadDataTransactionUtil; import org.opendaylight.restconf.restful.utils.RestconfDataServiceConstant; @@ -40,36 +53,105 @@ public class RestconfDataServiceImpl implements RestconfDataService { private final static Logger LOG = LoggerFactory.getLogger(RestconfDataServiceImpl.class); - private SchemaContextHandler schemaContextHandler; - private TransactionChainHandler transactionChainHandler; + private final SchemaContextHandler schemaContextHandler; + private final TransactionChainHandler transactionChainHandler; + private final DOMMountPointServiceHandler mountPointServiceHandler; + + public RestconfDataServiceImpl(final SchemaContextHandler schemaContextHandler, + final TransactionChainHandler transactionChainHandler, + final DOMMountPointServiceHandler mountPointServiceHandler) { + this.schemaContextHandler = schemaContextHandler; + this.transactionChainHandler = transactionChainHandler; + this.mountPointServiceHandler = mountPointServiceHandler; + } @Override - public NormalizedNodeContext readData(final String identifier, final UriInfo uriInfo) { - Preconditions.checkNotNull(identifier); + public Response readData(final UriInfo uriInfo) { + return readData(null, uriInfo); + } + + @Override + public Response readData(final String identifier, final UriInfo uriInfo) { final SchemaContextRef schemaContextRef = new SchemaContextRef(this.schemaContextHandler.get()); + final InstanceIdentifierContext instanceIdentifier = ParserIdentifier.toInstanceIdentifier( + identifier, schemaContextRef.get(), Optional.of(this.mountPointServiceHandler.get())); - final InstanceIdentifierContext instanceIdentifier = ParserIdentifier.toInstanceIdentifier(identifier, schemaContextRef.get()); - final DOMMountPoint mountPoint = instanceIdentifier.getMountPoint(); - final String value = uriInfo.getQueryParameters().getFirst(RestconfDataServiceConstant.CONTENT); + final WriterParameters parameters = ReadDataTransactionUtil.parseUriParameters( + instanceIdentifier, uriInfo); - DOMDataReadWriteTransaction transaction = null; + final DOMMountPoint mountPoint = instanceIdentifier.getMountPoint(); + final DOMTransactionChain transactionChain; if (mountPoint == null) { - transaction = this.transactionChainHandler.get().newReadWriteTransaction(); + transactionChain = this.transactionChainHandler.get(); } else { - transaction = transactionOfMountPoint(mountPoint); + transactionChain = transactionChainOfMountPoint(mountPoint); + } + + final TransactionVarsWrapper transactionNode = new TransactionVarsWrapper( + instanceIdentifier, mountPoint, transactionChain); + final NormalizedNode node = ReadDataTransactionUtil.readData(parameters.getContent(), transactionNode); + if (node == null) { + throw new RestconfDocumentedException( + "Request could not be completed because the relevant data model content does not exist", + RestconfError.ErrorType.PROTOCOL, + RestconfError.ErrorTag.DATA_MISSING); + } + 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() + '"'; + final Response resp; + + if ((parameters.getContent().equals(RestconfDataServiceConstant.ReadData.ALL)) + || parameters.getContent().equals(RestconfDataServiceConstant.ReadData.CONFIG)) { + resp = Response.status(200) + .entity(new NormalizedNodeContext(instanceIdentifier, node, parameters)) + .header("ETag", etag) + .header("Last-Modified", dateFormatGmt.format(new Date())) + .build(); + } else { + resp = Response.status(200) + .entity(new NormalizedNodeContext(instanceIdentifier, node, parameters)) + .build(); } - final TransactionVarsWrapper transactionNode = new TransactionVarsWrapper(instanceIdentifier, mountPoint, - transaction); - final NormalizedNode node = ReadDataTransactionUtil.readData(value, transactionNode); - return new NormalizedNodeContext(instanceIdentifier, node); + return resp; } @Override - public Response putData(final String identifier, final NormalizedNodeContext payload) { - Preconditions.checkNotNull(identifier); + public Response putData(final String identifier, final NormalizedNodeContext payload, final UriInfo uriInfo) { Preconditions.checkNotNull(payload); + boolean insert_used = false; + boolean point_used = false; + String insert = null; + String point = null; + + for (final Entry> entry : uriInfo.getQueryParameters().entrySet()) { + switch (entry.getKey()) { + case "insert": + if (!insert_used) { + insert_used = true; + insert = entry.getValue().iterator().next(); + } else { + throw new RestconfDocumentedException("Insert parameter can be used only once."); + } + break; + case "point": + if (!point_used) { + point_used = true; + point = entry.getValue().iterator().next(); + } else { + throw new RestconfDocumentedException("Point parameter can be used only once."); + } + break; + default: + throw new RestconfDocumentedException("Bad parameter for post: " + entry.getKey()); + } + } + + checkQueryParams(insert_used, point_used, insert); + final InstanceIdentifierContext iid = payload .getInstanceIdentifierContext(); @@ -78,59 +160,140 @@ public class RestconfDataServiceImpl implements RestconfDataService { PutDataTransactionUtil.validateListKeysEqualityInPayloadAndUri(payload); final DOMMountPoint mountPoint = payload.getInstanceIdentifierContext().getMountPoint(); - DOMDataReadWriteTransaction transaction = null; - SchemaContextRef ref = null; + final DOMTransactionChain transactionChain; + final SchemaContextRef ref; if (mountPoint == null) { - transaction = this.transactionChainHandler.get().newReadWriteTransaction(); + transactionChain = this.transactionChainHandler.get(); ref = new SchemaContextRef(this.schemaContextHandler.get()); } else { - transaction = transactionOfMountPoint(mountPoint); + transactionChain = transactionChainOfMountPoint(mountPoint); ref = new SchemaContextRef(mountPoint.getSchemaContext()); } final TransactionVarsWrapper transactionNode = new TransactionVarsWrapper( - payload.getInstanceIdentifierContext(), mountPoint, transaction); - return PutDataTransactionUtil.putData(payload, ref, transactionNode); + payload.getInstanceIdentifierContext(), mountPoint, transactionChain); + return PutDataTransactionUtil.putData(payload, ref, transactionNode, insert, point); + } + + private void checkQueryParams(final boolean insert_used, final boolean point_used, final String insert) { + if (point_used && !insert_used) { + throw new RestconfDocumentedException("Point parameter can't be used without Insert parameter."); + } + if (point_used && (insert.equals("first") || insert.equals("last"))) { + throw new RestconfDocumentedException( + "Point parameter can be used only with 'after' or 'before' values of Insert parameter."); + } } @Override public Response postData(final String identifier, final NormalizedNodeContext payload, final UriInfo uriInfo) { - throw new UnsupportedOperationException("Not yet implemented."); + return postData(payload, uriInfo); } @Override public Response postData(final NormalizedNodeContext payload, final UriInfo uriInfo) { - throw new UnsupportedOperationException("Not yet implemented."); + Preconditions.checkNotNull(payload); + + boolean insert_used = false; + boolean point_used = false; + String insert = null; + String point = null; + + for (final Entry> entry : uriInfo.getQueryParameters().entrySet()) { + switch (entry.getKey()) { + case "insert": + if (!insert_used) { + insert_used = true; + insert = entry.getValue().iterator().next(); + } else { + throw new RestconfDocumentedException("Insert parameter can be used only once."); + } + break; + case "point": + if (!point_used) { + point_used = true; + point = entry.getValue().iterator().next(); + } else { + throw new RestconfDocumentedException("Point parameter can be used only once."); + } + break; + default: + throw new RestconfDocumentedException("Bad parameter for post: " + entry.getKey()); + } + } + + checkQueryParams(insert_used, point_used, insert); + + final DOMMountPoint mountPoint = payload.getInstanceIdentifierContext().getMountPoint(); + final DOMTransactionChain transactionChain; + final SchemaContextRef ref; + if (mountPoint == null) { + transactionChain = this.transactionChainHandler.get(); + ref = new SchemaContextRef(this.schemaContextHandler.get()); + } else { + transactionChain = transactionChainOfMountPoint(mountPoint); + ref = new SchemaContextRef(mountPoint.getSchemaContext()); + } + final TransactionVarsWrapper transactionNode = new TransactionVarsWrapper( + payload.getInstanceIdentifierContext(), mountPoint, transactionChain); + return PostDataTransactionUtil.postData(uriInfo, payload, transactionNode, ref, insert, point); } @Override public Response deleteData(final String identifier) { - throw new UnsupportedOperationException("Not yet implemented."); + final SchemaContextRef schemaContextRef = new SchemaContextRef(this.schemaContextHandler.get()); + final InstanceIdentifierContext instanceIdentifier = ParserIdentifier.toInstanceIdentifier( + identifier, schemaContextRef.get(), Optional.of(this.mountPointServiceHandler.get())); + + final DOMMountPoint mountPoint = instanceIdentifier.getMountPoint(); + final DOMTransactionChain transactionChain; + if (mountPoint == null) { + transactionChain = this.transactionChainHandler.get(); + } else { + transactionChain = transactionChainOfMountPoint(mountPoint); + } + + final TransactionVarsWrapper transactionNode = new TransactionVarsWrapper(instanceIdentifier, mountPoint, + transactionChain); + return DeleteDataTransactionUtil.deleteData(transactionNode); } @Override public PATCHStatusContext patchData(final String identifier, final PATCHContext context, final UriInfo uriInfo) { - throw new UnsupportedOperationException("Not yet implemented."); + return patchData(context, uriInfo); } @Override public PATCHStatusContext patchData(final PATCHContext context, final UriInfo uriInfo) { - throw new UnsupportedOperationException("Not yet implemented."); + Preconditions.checkNotNull(context); + final DOMMountPoint mountPoint = context.getInstanceIdentifierContext().getMountPoint(); + + final DOMTransactionChain transactionChain; + final SchemaContextRef ref; + if (mountPoint == null) { + transactionChain = this.transactionChainHandler.get(); + ref = new SchemaContextRef(this.schemaContextHandler.get()); + } else { + transactionChain = transactionChainOfMountPoint(mountPoint); + ref = new SchemaContextRef(mountPoint.getSchemaContext()); + } + + final TransactionVarsWrapper transactionNode = new TransactionVarsWrapper( + context.getInstanceIdentifierContext(), mountPoint, transactionChain); + + return PatchDataTransactionUtil.patchData(context, transactionNode, ref); } /** - * Prepare transaction to read data of mount point, if these data are - * present. + * Prepare transaction chain to access data of mount point * @param mountPoint - * - * @param transactionNode - * - {@link TransactionVarsWrapper} - wrapper for variables - * @return {@link NormalizedNode} + * - mount point reference + * @return {@link DOMTransactionChain} */ - private static DOMDataReadWriteTransaction transactionOfMountPoint(final DOMMountPoint mountPoint) { + private static DOMTransactionChain transactionChainOfMountPoint(@Nonnull 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();