import javax.inject.Singleton;
import org.apache.aries.blueprint.annotation.service.Reference;
import org.opendaylight.mdsal.dom.api.DOMSchemaService;
+import org.opendaylight.restconf.nb.rfc8040.handlers.ActionServiceHandler;
import org.opendaylight.restconf.nb.rfc8040.handlers.DOMDataBrokerHandler;
import org.opendaylight.restconf.nb.rfc8040.handlers.DOMMountPointServiceHandler;
import org.opendaylight.restconf.nb.rfc8040.handlers.NotificationServiceHandler;
*/
@Singleton
public class Rfc8040RestConfWiring {
-
private final ServicesWrapper servicesWrapper;
@Inject
- public Rfc8040RestConfWiring(
- SchemaContextHandler schemaCtxHandler,
- DOMMountPointServiceHandler domMountPointServiceHandler, TransactionChainHandler transactionChainHandler,
- DOMDataBrokerHandler domDataBrokerHandler, RpcServiceHandler rpcServiceHandler,
- NotificationServiceHandler notificationServiceHandler, @Reference DOMSchemaService domSchemaService) {
+ public Rfc8040RestConfWiring(final SchemaContextHandler schemaCtxHandler,
+ final DOMMountPointServiceHandler domMountPointServiceHandler,
+ final TransactionChainHandler transactionChainHandler,
+ final DOMDataBrokerHandler domDataBrokerHandler, final RpcServiceHandler rpcServiceHandler,
+ final ActionServiceHandler actionServiceHandler,
+ final NotificationServiceHandler notificationServiceHandler,
+ @Reference final DOMSchemaService domSchemaService) {
servicesWrapper = ServicesWrapper.newInstance(schemaCtxHandler, domMountPointServiceHandler,
- transactionChainHandler, domDataBrokerHandler, rpcServiceHandler, notificationServiceHandler,
- domSchemaService);
+ transactionChainHandler, domDataBrokerHandler, rpcServiceHandler, actionServiceHandler,
+ notificationServiceHandler, domSchemaService);
}
public ServicesWrapper getServicesWrapper() {
--- /dev/null
+/*
+ * Copyright (C) 2019 Ericsson Software Technology AB. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.restconf.nb.rfc8040.handlers;
+
+import static java.util.Objects.requireNonNull;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import org.apache.aries.blueprint.annotation.service.Reference;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.dom.api.DOMActionService;
+
+/**
+ * Implementation of {@link ActionServiceHandler}.
+ */
+@Singleton
+public class ActionServiceHandler implements Handler<DOMActionService> {
+ private final @NonNull DOMActionService actionService;
+
+ /**
+ * Set DOMActionService.
+ *
+ * @param actionService
+ * DOMActionService
+ */
+ @Inject
+ public ActionServiceHandler(final @Reference DOMActionService actionService) {
+ this.actionService = requireNonNull(actionService);
+ }
+
+ @Override
+ public @NonNull DOMActionService get() {
+ return this.actionService;
+ }
+}
import org.opendaylight.yangtools.yang.data.codec.gson.JSONNormalizedNodeStreamWriter;
import org.opendaylight.yangtools.yang.data.codec.gson.JsonWriterFactory;
import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+import org.opendaylight.yangtools.yang.model.api.ActionDefinition;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
jsonWriter.beginObject();
writeChildren(nnWriter, (ContainerNode) data);
jsonWriter.endObject();
+ } else if (context.getSchemaNode() instanceof ActionDefinition) {
+ /*
+ * ActionDefinition is not supported as initial codec in JSONStreamWriter,
+ * so we need to emit initial output declaration..
+ */
+ nnWriter = createNormalizedNodeWriter(context,
+ ((ActionDefinition) context.getSchemaNode()).getOutput().getPath(), jsonWriter, depth, fields);
+ final Module module = context.getSchemaContext().findModule(data.getNodeType().getModule()).get();
+ jsonWriter.name(module.getName() + ":output");
+ jsonWriter.beginObject();
+ writeChildren(nnWriter, (ContainerNode) data);
+ jsonWriter.endObject();
} else {
if (SchemaPath.ROOT.equals(path)) {
nnWriter = createNormalizedNodeWriter(context, path, jsonWriter, depth, fields);
import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
import org.opendaylight.yangtools.yang.data.codec.xml.XMLStreamNormalizedNodeStreamWriter;
import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+import org.opendaylight.yangtools.yang.model.api.ActionDefinition;
import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
depth,
fields);
writeElements(xmlWriter, nnWriter, (ContainerNode) data);
+ } else if (pathContext.getSchemaNode() instanceof ActionDefinition) {
+ /*
+ * ActionDefinition is not supported as initial codec in XMLStreamWriter,
+ * so we need to emit initial output declaration..
+ */
+ nnWriter = createNormalizedNodeWriter(xmlWriter, schemaCtx,
+ ((ActionDefinition) pathContext.getSchemaNode()).getOutput().getPath(), depth, fields);
+ writeElements(xmlWriter, nnWriter, (ContainerNode) data);
} else {
if (SchemaPath.ROOT.equals(path)) {
nnWriter = createNormalizedNodeWriter(xmlWriter, schemaCtx, path, depth, fields);
*/
package org.opendaylight.restconf.nb.rfc8040.jersey.providers;
-import com.google.common.base.Preconditions;
+import static com.google.common.base.Preconditions.checkState;
+
import com.google.common.collect.Iterables;
import java.io.IOException;
import java.io.InputStream;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+import org.opendaylight.yangtools.yang.model.api.OperationDefinition;
import org.opendaylight.yangtools.yang.model.api.SchemaNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
throws XMLStreamException, IOException, ParserConfigurationException, SAXException, URISyntaxException {
final SchemaNode schemaNodeContext = pathContext.getSchemaNode();
DataSchemaNode schemaNode;
- boolean isRpc = false;
- if (schemaNodeContext instanceof RpcDefinition) {
- schemaNode = ((RpcDefinition) schemaNodeContext).getInput();
- isRpc = true;
+ final boolean isOperation;
+ if (schemaNodeContext instanceof OperationDefinition) {
+ schemaNode = ((OperationDefinition) schemaNodeContext).getInput();
+ isOperation = true;
} else if (schemaNodeContext instanceof DataSchemaNode) {
schemaNode = (DataSchemaNode) schemaNodeContext;
+ isOperation = false;
} else {
- throw new IllegalStateException("Unknown SchemaNode");
+ throw new IllegalStateException("Unknown SchemaNode " + schemaNodeContext);
}
final String docRootElm = doc.getDocumentElement().getLocalName();
final String docRootNamespace = doc.getDocumentElement().getNamespaceURI();
final List<YangInstanceIdentifier.PathArgument> iiToDataList = new ArrayList<>();
- if (isPost() && !isRpc) {
+ if (isPost() && !isOperation) {
final Deque<Object> foundSchemaNodes = findPathToSchemaNodeByName(schemaNode, docRootElm, docRootNamespace);
if (foundSchemaNodes.isEmpty()) {
throw new IllegalStateException(String.format("Child \"%s\" was not found in parent schema node \"%s\"",
}
}
// PUT
- } else if (!isRpc) {
+ } else if (!isOperation) {
final QName scQName = schemaNode.getQName();
- Preconditions.checkState(
- docRootElm.equals(scQName.getLocalName())
- && docRootNamespace.equals(scQName.getNamespace().toASCIIString()),
- String.format("Not correct message root element \"%s\", should be \"%s\"",
- docRootElm, scQName));
+ checkState(docRootElm.equals(scQName.getLocalName())
+ && docRootNamespace.equals(scQName.getNamespace().toASCIIString()),
+ "Not correct message root element \"%s\", should be \"%s\"", docRootElm, scQName);
}
NormalizedNode<?, ?> parsed;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map.Entry;
-import java.util.Objects;
import java.util.Optional;
import javax.ws.rs.Path;
+import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.dom.api.DOMActionResult;
import org.opendaylight.mdsal.dom.api.DOMDataBroker;
import org.opendaylight.mdsal.dom.api.DOMMountPoint;
import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
import org.opendaylight.restconf.common.context.WriterParameters;
import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
import org.opendaylight.restconf.common.errors.RestconfError;
+import org.opendaylight.restconf.common.errors.RestconfError.ErrorTag;
+import org.opendaylight.restconf.common.errors.RestconfError.ErrorType;
import org.opendaylight.restconf.common.patch.PatchContext;
import org.opendaylight.restconf.common.patch.PatchStatusContext;
+import org.opendaylight.restconf.nb.rfc8040.handlers.ActionServiceHandler;
import org.opendaylight.restconf.nb.rfc8040.handlers.DOMMountPointServiceHandler;
import org.opendaylight.restconf.nb.rfc8040.handlers.SchemaContextHandler;
import org.opendaylight.restconf.nb.rfc8040.handlers.TransactionChainHandler;
import org.opendaylight.restconf.nb.rfc8040.rests.utils.PutDataTransactionUtil;
import org.opendaylight.restconf.nb.rfc8040.rests.utils.ReadDataTransactionUtil;
import org.opendaylight.restconf.nb.rfc8040.rests.utils.RestconfDataServiceConstant;
+import org.opendaylight.restconf.nb.rfc8040.rests.utils.RestconfInvokeOperationsUtil;
import org.opendaylight.restconf.nb.rfc8040.utils.RestconfConstants;
import org.opendaylight.restconf.nb.rfc8040.utils.parser.ParserIdentifier;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.Revision;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.model.api.ActionDefinition;
import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger LOG = LoggerFactory.getLogger(RestconfDataServiceImpl.class);
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MMM-dd HH:mm:ss");
+ private final RestconfStreamsSubscriptionService delegRestconfSubscrService;
+
+ // FIXME: evaluate thread-safety of updates (synchronized) vs. access (mostly unsynchronized) here
private SchemaContextHandler schemaContextHandler;
private TransactionChainHandler transactionChainHandler;
private DOMMountPointServiceHandler mountPointServiceHandler;
-
- private final RestconfStreamsSubscriptionService delegRestconfSubscrService;
+ private volatile ActionServiceHandler actionServiceHandler;
public RestconfDataServiceImpl(final SchemaContextHandler schemaContextHandler,
- final TransactionChainHandler transactionChainHandler,
+ final TransactionChainHandler transactionChainHandler,
final DOMMountPointServiceHandler mountPointServiceHandler,
- final RestconfStreamsSubscriptionService delegRestconfSubscrService) {
- this.schemaContextHandler = Objects.requireNonNull(schemaContextHandler);
- this.transactionChainHandler = Objects.requireNonNull(transactionChainHandler);
- this.mountPointServiceHandler = Objects.requireNonNull(mountPointServiceHandler);
- this.delegRestconfSubscrService = Objects.requireNonNull(delegRestconfSubscrService);
+ final RestconfStreamsSubscriptionService delegRestconfSubscrService,
+ final ActionServiceHandler actionServiceHandler) {
+ this.actionServiceHandler = requireNonNull(actionServiceHandler);
+ this.schemaContextHandler = requireNonNull(schemaContextHandler);
+ this.transactionChainHandler = requireNonNull(transactionChainHandler);
+ this.mountPointServiceHandler = requireNonNull(mountPointServiceHandler);
+ this.delegRestconfSubscrService = requireNonNull(delegRestconfSubscrService);
}
@Override
for (final Object object : handlers) {
if (object instanceof SchemaContextHandler) {
schemaContextHandler = (SchemaContextHandler) object;
+ } else if (object instanceof ActionServiceHandler) {
+ actionServiceHandler = (ActionServiceHandler) object;
} else if (object instanceof DOMMountPointServiceHandler) {
mountPointServiceHandler = (DOMMountPointServiceHandler) object;
} else if (object instanceof TransactionChainHandler) {
@Override
public Response postData(final NormalizedNodeContext payload, final UriInfo uriInfo) {
requireNonNull(payload);
-
+ if (payload.getInstanceIdentifierContext().getSchemaNode() instanceof ActionDefinition) {
+ return invokeAction(payload, uriInfo);
+ }
boolean insertUsed = false;
boolean pointUsed = false;
String insert = null;
LOG.warn(errMsg);
throw new RestconfDocumentedException(errMsg);
}
+
+ /**
+ * Invoke Action operation.
+ *
+ * @param payload
+ * {@link NormalizedNodeContext} - the body of the operation
+ * @param uriInfo
+ * URI info
+ * @return {@link NormalizedNodeContext} wrapped in {@link Response}
+ */
+ public Response invokeAction(final NormalizedNodeContext payload, final UriInfo uriInfo) {
+ final InstanceIdentifierContext<?> context = payload.getInstanceIdentifierContext();
+ final DOMMountPoint mountPoint = context.getMountPoint();
+ final SchemaPath schemaPath = context.getSchemaNode().getPath();
+ final YangInstanceIdentifier yangIIdContext = context.getInstanceIdentifier();
+ final NormalizedNode<?, ?> data = payload.getData();
+
+ if (yangIIdContext.isEmpty() && !RestconfDataServiceConstant.NETCONF_BASE_QNAME.equals(data.getNodeType())) {
+ throw new RestconfDocumentedException("Instance identifier need to contain at least one path argument",
+ ErrorType.PROTOCOL, ErrorTag.MALFORMED_MESSAGE);
+ }
+
+ final DOMActionResult response;
+ final SchemaContextRef schemaContextRef;
+ if (mountPoint != null) {
+ response = RestconfInvokeOperationsUtil.invokeActionViaMountPoint(mountPoint, (ContainerNode) data,
+ schemaPath, yangIIdContext);
+ schemaContextRef = new SchemaContextRef(mountPoint.getSchemaContext());
+ } else {
+ response = RestconfInvokeOperationsUtil.invokeAction((ContainerNode) data, schemaPath,
+ this.actionServiceHandler, yangIIdContext);
+ schemaContextRef = new SchemaContextRef(this.schemaContextHandler.get());
+ }
+ final DOMActionResult result = RestconfInvokeOperationsUtil.checkActionResponse(response);
+
+ ActionDefinition resultNodeSchema = null;
+ ContainerNode resultData = null;
+ if (result != null) {
+ final Optional<ContainerNode> optOutput = result.getOutput();
+ if (optOutput.isPresent()) {
+ resultData = optOutput.get();
+ resultNodeSchema = (ActionDefinition) context.getSchemaNode();
+ }
+ }
+
+ if (resultData != null && resultData.getValue().isEmpty()) {
+ throw new WebApplicationException(Response.Status.NO_CONTENT);
+ }
+
+ return Response.status(200).entity(new NormalizedNodeContext(new InstanceIdentifierContext<>(yangIIdContext,
+ resultNodeSchema, mountPoint, schemaContextRef.get()), resultData)).build();
+ }
}
--- /dev/null
+/*
+ * Copyright (C) 2019 Ericsson Software Technology AB. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.restconf.nb.rfc8040.rests.utils;
+
+import org.opendaylight.mdsal.dom.api.DOMActionResult;
+import org.opendaylight.yangtools.concepts.Builder;
+
+/**
+ * Implementation of {@link ActionResultFactory}.
+ */
+public class ActionResultFactory extends FutureDataFactory<DOMActionResult> implements Builder<DOMActionResult> {
+
+ @Override
+ public DOMActionResult build() throws IllegalArgumentException {
+ return this.result;
+ }
+}
import java.util.List;
import java.util.concurrent.ExecutionException;
import org.opendaylight.mdsal.common.api.TransactionCommitFailedException;
+import org.opendaylight.mdsal.dom.api.DOMActionException;
import org.opendaylight.mdsal.dom.api.DOMRpcException;
import org.opendaylight.mdsal.dom.spi.DefaultDOMRpcResult;
+import org.opendaylight.mdsal.dom.spi.SimpleDOMActionResult;
import org.opendaylight.netconf.api.NetconfDocumentedException;
import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
import org.opendaylight.restconf.common.errors.RestconfError;
if (cause instanceof DOMRpcException) {
dataFactory.setResult((T) new DefaultDOMRpcResult(ImmutableList.of(
RpcResultBuilder.newError(RpcError.ErrorType.RPC, "operation-failed", cause.getMessage()))));
+ } else if (cause instanceof DOMActionException) {
+ dataFactory.setResult((T) new SimpleDOMActionResult(ImmutableList.of(
+ RpcResultBuilder.newError(RpcError.ErrorType.RPC, "operation-failed", cause.getMessage()))));
} else if (cause instanceof TransactionCommitFailedException) {
/* If device send some error message we want this message to get to client
and not just to throw it away or override it with new generic message.
package org.opendaylight.restconf.nb.rfc8040.rests.utils;
import com.google.common.util.concurrent.ListenableFuture;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Optional;
import java.util.concurrent.CancellationException;
import javax.ws.rs.core.Response.Status;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.mdsal.dom.api.DOMActionResult;
+import org.opendaylight.mdsal.dom.api.DOMActionService;
+import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier;
import org.opendaylight.mdsal.dom.api.DOMMountPoint;
import org.opendaylight.mdsal.dom.api.DOMRpcResult;
import org.opendaylight.mdsal.dom.api.DOMRpcService;
import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
import org.opendaylight.restconf.common.errors.RestconfError.ErrorTag;
import org.opendaylight.restconf.common.errors.RestconfError.ErrorType;
+import org.opendaylight.restconf.nb.rfc8040.handlers.ActionServiceHandler;
import org.opendaylight.restconf.nb.rfc8040.handlers.RpcServiceHandler;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
import org.slf4j.Logger;
FutureCallbackTx.addCallback(rpc, RestconfDataServiceConstant.PostData.POST_TX_TYPE, dataFactory);
return dataFactory.build();
}
+
+ /**
+ * Invoking Action via mount point.
+ *
+ * @param mountPoint
+ * mount point
+ * @param data
+ * input data
+ * @param schemaPath
+ * schema path of data
+ * @return {@link DOMActionResult}
+ */
+ public static DOMActionResult invokeActionViaMountPoint(final DOMMountPoint mountPoint, final ContainerNode data,
+ final SchemaPath schemaPath, final YangInstanceIdentifier yangIId) {
+ final Optional<DOMActionService> mountPointService = mountPoint.getService(DOMActionService.class);
+ if (!mountPointService.isPresent()) {
+ throw new RestconfDocumentedException("DomAction service is missing.");
+ }
+
+ return prepareActionResult(mountPointService.get().invokeAction(schemaPath,
+ prepareDataTreeId(yangIId, schemaPath), data));
+ }
+
+ /**
+ * Invoke Action via ActionServiceHandler.
+ *
+ * @param data
+ * input data
+ * @param schemaPath
+ * schema path of data
+ * @param actionServiceHandler
+ * action service handler to invoke action
+ * @return {@link DOMActionResult}
+ */
+ public static DOMActionResult invokeAction(final ContainerNode data, final SchemaPath schemaPath,
+ final ActionServiceHandler actionServiceHandler, final YangInstanceIdentifier yangIId) {
+ return prepareActionResult(actionServiceHandler.get().invokeAction(schemaPath,
+ prepareDataTreeId(yangIId, schemaPath), data));
+ }
+
+ /**
+ * Check the validity of the result.
+ *
+ * @param response
+ * response of Action
+ * @return {@link DOMActionResult} result
+ */
+ public static DOMActionResult checkActionResponse(final DOMActionResult response) {
+ if (response != null) {
+ try {
+ if (response.getErrors().isEmpty()) {
+ return response;
+ }
+ LOG.debug("InvokeAction Error Message {}", response.getErrors());
+ throw new RestconfDocumentedException("InvokeAction Error Message ", null, response.getErrors());
+ } catch (final CancellationException e) {
+ final String errMsg = "The Action Operation was cancelled while executing.";
+ LOG.debug("Cancel Execution: {}", errMsg, e);
+ throw new RestconfDocumentedException(errMsg, ErrorType.RPC, ErrorTag.PARTIAL_OPERATION, e);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Prepare Action Result.
+ *
+ * @param actionResult
+ * {@link DOMActionResult} - action result
+ * @return {@link DOMActionResult} result
+ */
+ private static DOMActionResult prepareActionResult(final ListenableFuture<? extends DOMActionResult> actionResult) {
+ final ActionResultFactory dataFactory = new ActionResultFactory();
+ FutureCallbackTx.addCallback(actionResult, RestconfDataServiceConstant.PostData.POST_TX_TYPE, dataFactory);
+ return dataFactory.build();
+ }
+
+ /**
+ * Prepare DOMDataTree Identifier.
+ *
+ * @param yangIId
+ * {@link YangInstanceIdentifier}
+ * @param schemaPath
+ * {@link SchemaPath}
+ * @return {@link DOMDataTreeIdentifier} domDataTreeIdentifier
+ */
+ private static DOMDataTreeIdentifier prepareDataTreeId(final YangInstanceIdentifier yangIId,
+ final SchemaPath schemaPath) {
+ final List<PathArgument> pathArg = new ArrayList<>();
+ for (PathArgument path : yangIId.getPathArguments()) {
+ if (path.getNodeType().getLocalName().equals(schemaPath.getLastComponent().getLocalName())) {
+ break;
+ }
+ pathArg.add(path);
+ }
+ YangInstanceIdentifier yangInstanceIdentifier = YangInstanceIdentifier.builder().append(pathArg).build();
+ DOMDataTreeIdentifier domDataTreeIdentifier = new DOMDataTreeIdentifier(LogicalDatastoreType.OPERATIONAL,
+ yangInstanceIdentifier);
+ return domDataTreeIdentifier;
+ }
}
import org.opendaylight.restconf.common.patch.PatchContext;
import org.opendaylight.restconf.common.patch.PatchStatusContext;
import org.opendaylight.restconf.common.schema.SchemaExportContext;
+import org.opendaylight.restconf.nb.rfc8040.handlers.ActionServiceHandler;
import org.opendaylight.restconf.nb.rfc8040.handlers.DOMDataBrokerHandler;
import org.opendaylight.restconf.nb.rfc8040.handlers.DOMMountPointServiceHandler;
import org.opendaylight.restconf.nb.rfc8040.handlers.NotificationServiceHandler;
private final RestconfSchemaService delegRestSchService;
private final RestconfService delegRestService;
- private ServicesWrapper(RestconfDataService delegRestconfDataService,
- RestconfInvokeOperationsService delegRestconfInvokeOpsService,
- RestconfStreamsSubscriptionService delegRestconfSubscrService,
- RestconfOperationsService delegRestOpsService, RestconfSchemaService delegRestSchService,
- RestconfService delegRestService) {
+ private ServicesWrapper(final RestconfDataService delegRestconfDataService,
+ final RestconfInvokeOperationsService delegRestconfInvokeOpsService,
+ final RestconfStreamsSubscriptionService delegRestconfSubscrService,
+ final RestconfOperationsService delegRestOpsService, final RestconfSchemaService delegRestSchService,
+ final RestconfService delegRestService) {
this.delegRestconfDataService = delegRestconfDataService;
this.delegRestconfInvokeOpsService = delegRestconfInvokeOpsService;
this.delegRestconfSubscrService = delegRestconfSubscrService;
public static ServicesWrapper newInstance(final SchemaContextHandler schemaCtxHandler,
final DOMMountPointServiceHandler domMountPointServiceHandler,
final TransactionChainHandler transactionChainHandler, final DOMDataBrokerHandler domDataBrokerHandler,
- final RpcServiceHandler rpcServiceHandler, final NotificationServiceHandler notificationServiceHandler,
- final DOMSchemaService domSchemaService) {
- RestconfOperationsService restconfOpsService =
- new RestconfOperationsServiceImpl(schemaCtxHandler, domMountPointServiceHandler);
+ final RpcServiceHandler rpcServiceHandler, final ActionServiceHandler actionServiceHandler,
+ final NotificationServiceHandler notificationServiceHandler, final DOMSchemaService domSchemaService) {
+ RestconfOperationsService restconfOpsService = new RestconfOperationsServiceImpl(schemaCtxHandler,
+ domMountPointServiceHandler);
final DOMYangTextSourceProvider yangTextSourceProvider = domSchemaService.getExtensions()
- .getInstance(DOMYangTextSourceProvider.class);
- RestconfSchemaService restconfSchemaService =
- new RestconfSchemaServiceImpl(schemaCtxHandler, domMountPointServiceHandler,
- yangTextSourceProvider);
- RestconfStreamsSubscriptionService restconfSubscrService =
- new RestconfStreamsSubscriptionServiceImpl(domDataBrokerHandler,
- notificationServiceHandler, schemaCtxHandler, transactionChainHandler);
- RestconfDataService restconfDataService =
- new RestconfDataServiceImpl(schemaCtxHandler, transactionChainHandler, domMountPointServiceHandler,
- restconfSubscrService);
- RestconfInvokeOperationsService restconfInvokeOpsService =
- new RestconfInvokeOperationsServiceImpl(rpcServiceHandler, schemaCtxHandler);
+ .getInstance(DOMYangTextSourceProvider.class);
+ RestconfSchemaService restconfSchemaService = new RestconfSchemaServiceImpl(schemaCtxHandler,
+ domMountPointServiceHandler, yangTextSourceProvider);
+ RestconfStreamsSubscriptionService restconfSubscrService = new RestconfStreamsSubscriptionServiceImpl(
+ domDataBrokerHandler, notificationServiceHandler, schemaCtxHandler, transactionChainHandler);
+ RestconfDataService restconfDataService = new RestconfDataServiceImpl(schemaCtxHandler, transactionChainHandler,
+ domMountPointServiceHandler, restconfSubscrService, actionServiceHandler);
+ RestconfInvokeOperationsService restconfInvokeOpsService = new RestconfInvokeOperationsServiceImpl(
+ rpcServiceHandler, schemaCtxHandler);
RestconfService restconfService = new RestconfImpl(schemaCtxHandler);
- return new ServicesWrapper(restconfDataService, restconfInvokeOpsService,
- restconfSubscrService, restconfOpsService, restconfSchemaService, restconfService);
+ return new ServicesWrapper(restconfDataService, restconfInvokeOpsService, restconfSubscrService,
+ restconfOpsService, restconfSchemaService, restconfService);
}
@Override
checkExpectValueNormalizeNodeContext(dataSchemaNode, returnValue);
}
+ @Test
+ public void moduleSubContainerDataPostActionTest() throws Exception {
+ final Optional<DataSchemaNode> dataSchemaNode = schemaContext
+ .findDataChildByName(QName.create(INSTANCE_IDENTIFIER_MODULE_QNAME, "cont"));
+ final String uri = "instance-identifier-module:cont/yang-ext:mount/instance-identifier-module:cont/cont1/reset";
+ mockBodyReader(uri, this.xmlBodyReader, true);
+ final InputStream inputStream = XmlBodyReaderMountPointTest.class
+ .getResourceAsStream("/instanceidentifier/xml/xml_cont_action.xml");
+ final NormalizedNodeContext returnValue = this.xmlBodyReader.readFrom(null,
+ null, null, this.mediaType, null, inputStream);
+ checkMountPointNormalizedNodeContext(returnValue);
+ checkExpectValueNormalizeNodeContext(dataSchemaNode.get(), returnValue);
+ }
+
@Test
public void rpcModuleInputTest() throws Exception {
final String uri = "instance-identifier-module:cont/yang-ext:mount/invoke-rpc-module:rpc-test";
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
import com.google.common.collect.Sets;
import java.io.File;
import java.io.InputStream;
import java.net.URI;
import java.util.Collection;
+import java.util.Optional;
import javax.ws.rs.core.MediaType;
import org.junit.BeforeClass;
import org.junit.Test;
import org.opendaylight.yangtools.yang.common.Revision;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes;
+import org.opendaylight.yangtools.yang.model.api.ActionDefinition;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.Module;
checkExpectValueNormalizeNodeContext(dataSchemaNode, returnValue, dataII);
}
+ @Test
+ public void moduleSubContainerDataPostActionTest() throws Exception {
+ final Optional<DataSchemaNode> dataSchemaNode = schemaContext
+ .findDataChildByName(QName.create(INSTANCE_IDENTIFIER_MODULE_QNAME, "cont"));
+ final QName cont1QName = QName.create(dataSchemaNode.get().getQName(), "cont1");
+ final QName actionQName = QName.create(dataSchemaNode.get().getQName(), "reset");
+ final YangInstanceIdentifier dataII = YangInstanceIdentifier.of(dataSchemaNode.get().getQName())
+ .node(cont1QName).node(actionQName);
+ final String uri = "instance-identifier-module:cont/cont1/reset";
+ mockBodyReader(uri, this.jsonBodyReader, true);
+ final InputStream inputStream = JsonBodyReaderTest.class
+ .getResourceAsStream("/instanceidentifier/json/json_cont_action.json");
+ final NormalizedNodeContext returnValue = this.jsonBodyReader
+ .readFrom(null, null, null, this.mediaType, null, inputStream);
+ checkNormalizedNodeContext(returnValue);
+ assertTrue(returnValue.getInstanceIdentifierContext().getSchemaNode() instanceof ActionDefinition);
+ }
+
@Test
public void moduleSubContainerAugmentDataPostTest() throws Exception {
final DataSchemaNode dataSchemaNode = schemaContext
import java.io.InputStream;
import java.net.URI;
import java.util.Collection;
+import java.util.Optional;
import javax.ws.rs.core.MediaType;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes;
+import org.opendaylight.yangtools.yang.model.api.ActionDefinition;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.Module;
checkExpectValueNormalizeNodeContext(dataSchemaNode, returnValue, dataII);
}
+ @Test
+ public void moduleSubContainerDataPostActionTest() throws Exception {
+ final Optional<DataSchemaNode> dataSchemaNode = schemaContext
+ .findDataChildByName(QName.create(INSTANCE_IDENTIFIER_MODULE_QNAME, "cont"));
+ final QName cont1QName = QName.create(dataSchemaNode.get().getQName(), "cont1");
+ final QName actionQName = QName.create(dataSchemaNode.get().getQName(), "reset");
+ final YangInstanceIdentifier dataII = YangInstanceIdentifier.of(dataSchemaNode.get().getQName())
+ .node(cont1QName).node(actionQName);
+ final String uri = "instance-identifier-module:cont/cont1/reset";
+ mockBodyReader(uri, this.xmlBodyReader, true);
+ final InputStream inputStream = XmlBodyReaderTest.class
+ .getResourceAsStream("/instanceidentifier/xml/xml_cont_action.xml");
+ final NormalizedNodeContext returnValue = this.xmlBodyReader.readFrom(null, null, null, this.mediaType, null,
+ inputStream);
+ checkNormalizedNodeContext(returnValue);
+ assertTrue(returnValue.getInstanceIdentifierContext().getSchemaNode() instanceof ActionDefinition);
+ }
+
@Test
public void moduleSubContainerAugmentDataPostTest() throws Exception {
final DataSchemaNode dataSchemaNode = schemaContext
import org.opendaylight.mdsal.common.api.CommitInfo;
import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
import org.opendaylight.mdsal.common.api.TransactionCommitFailedException;
+import org.opendaylight.mdsal.dom.api.DOMActionService;
import org.opendaylight.mdsal.dom.api.DOMDataBroker;
import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction;
import org.opendaylight.mdsal.dom.api.DOMDataTreeReadWriteTransaction;
import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
import org.opendaylight.mdsal.dom.spi.DefaultDOMRpcResult;
import org.opendaylight.restconf.nb.rfc8040.TestUtils;
+import org.opendaylight.restconf.nb.rfc8040.handlers.ActionServiceHandler;
import org.opendaylight.restconf.nb.rfc8040.handlers.DOMDataBrokerHandler;
import org.opendaylight.restconf.nb.rfc8040.handlers.DOMMountPointServiceHandler;
import org.opendaylight.restconf.nb.rfc8040.handlers.NotificationServiceHandler;
@Mock
private DOMRpcService mockRpcService;
+ @Mock
+ private DOMActionService mockActionService;
+
@Mock
private DOMSchemaService domSchemaService;
final DOMNotificationService mockNotificationService = mock(DOMNotificationService.class);
final ServicesWrapper servicesWrapper = ServicesWrapper.newInstance(schemaContextHandler,
mountPointServiceHandler, txChainHandler, new DOMDataBrokerHandler(mockDOMDataBroker),
- new RpcServiceHandler(mockRpcService), new NotificationServiceHandler(mockNotificationService),
- domSchemaService);
+ new RpcServiceHandler(mockRpcService), new ActionServiceHandler(mockActionService),
+ new NotificationServiceHandler(mockNotificationService), domSchemaService);
service = new JSONRestconfServiceRfc8040Impl(servicesWrapper, mountPointServiceHandler,
schemaContextHandler);
import org.opendaylight.restconf.common.patch.PatchEntity;
import org.opendaylight.restconf.common.patch.PatchStatusContext;
import org.opendaylight.restconf.nb.rfc8040.TestRestconfUtils;
+import org.opendaylight.restconf.nb.rfc8040.handlers.ActionServiceHandler;
import org.opendaylight.restconf.nb.rfc8040.handlers.DOMMountPointServiceHandler;
import org.opendaylight.restconf.nb.rfc8040.handlers.SchemaContextHandler;
import org.opendaylight.restconf.nb.rfc8040.handlers.TransactionChainHandler;
@Mock
private DOMDataBroker mountDataBroker;
@Mock
+ private ActionServiceHandler actionServiceHandler;
+ @Mock
private DOMTransactionChain mountTransactionChain;
@Mock
private RestconfStreamsSubscriptionService delegRestconfSubscrService;
schemaContextHandler.onGlobalContextUpdated(this.contextRef.get());
this.dataService = new RestconfDataServiceImpl(schemaContextHandler, this.transactionChainHandler,
- DOMMountPointServiceHandler.newInstance(mountPointService), this.delegRestconfSubscrService);
+ DOMMountPointServiceHandler.newInstance(mountPointService), this.delegRestconfSubscrService,
+ this.actionServiceHandler);
doReturn(Optional.of(this.mountPoint)).when(this.mountPointService)
.getMountPoint(any(YangInstanceIdentifier.class));
doReturn(this.contextRef.get()).when(this.mountPoint).getSchemaContext();
import org.opendaylight.mdsal.binding.api.DataBroker;
import org.opendaylight.mdsal.binding.dom.adapter.test.AbstractBaseDataBrokerTest;
import org.opendaylight.mdsal.binding.dom.adapter.test.AbstractConcurrentDataBrokerTest;
+import org.opendaylight.mdsal.dom.api.DOMActionService;
import org.opendaylight.mdsal.dom.api.DOMDataBroker;
import org.opendaylight.mdsal.dom.api.DOMMountPointService;
import org.opendaylight.mdsal.dom.api.DOMNotificationPublishService;
return DOMRpcRouter.newInstance(schemaService).getRpcService();
}
+ @Provides
+ @Singleton
+ DOMActionService getDOMActionService(DOMSchemaService schemaService) {
+ return DOMRpcRouter.newInstance(schemaService).getActionService();
+ }
+
@PreDestroy
public void close() {
}
--- /dev/null
+{
+ "instance-identifier-module:input": {
+ "delay": 600
+ }
+}
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<input xmlns="instance:identifier:module">
+ <delay>600</delay>
+</input>
\ No newline at end of file
module instance-identifier-module {
+ yang-version 1.1;
namespace "instance:identifier:module";
prefix "iimodule";
- revision 2014-01-17 {
- }
+ revision 2014-01-17;
- container cont {
- container cont1 {
+ container cont {
+ container cont1 {
+ action reset {
+ input {
+ leaf delay {
+ type uint32;
+ default 0;
+ }
}
+ }
}
-}
\ No newline at end of file
+ }
+}