import static org.opendaylight.restconf.nb.rfc8040.rests.utils.RestconfStreamsConstants.STREAM_PATH_PART;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.MoreExecutors;
import java.net.URI;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.Optional;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import javax.ws.rs.Path;
+import javax.ws.rs.container.AsyncResponse;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriInfo;
import org.opendaylight.restconf.common.patch.PatchContext;
import org.opendaylight.restconf.common.patch.PatchStatusContext;
import org.opendaylight.restconf.nb.rfc8040.ReadDataParams;
-import org.opendaylight.restconf.nb.rfc8040.Rfc8040;
import org.opendaylight.restconf.nb.rfc8040.WriteDataParams;
import org.opendaylight.restconf.nb.rfc8040.databind.DatabindProvider;
import org.opendaylight.restconf.nb.rfc8040.databind.jaxrs.QueryParams;
import org.opendaylight.restconf.nb.rfc8040.rests.services.api.RestconfStreamsSubscriptionService;
import org.opendaylight.restconf.nb.rfc8040.rests.transactions.MdsalRestconfStrategy;
import org.opendaylight.restconf.nb.rfc8040.rests.transactions.RestconfStrategy;
-import org.opendaylight.restconf.nb.rfc8040.rests.utils.DeleteDataTransactionUtil;
import org.opendaylight.restconf.nb.rfc8040.rests.utils.PatchDataTransactionUtil;
-import org.opendaylight.restconf.nb.rfc8040.rests.utils.PlainPatchDataTransactionUtil;
import org.opendaylight.restconf.nb.rfc8040.rests.utils.PostDataTransactionUtil;
import org.opendaylight.restconf.nb.rfc8040.rests.utils.PutDataTransactionUtil;
import org.opendaylight.restconf.nb.rfc8040.rests.utils.ReadDataTransactionUtil;
import org.opendaylight.restconf.nb.rfc8040.streams.listeners.ListenersBroker;
import org.opendaylight.restconf.nb.rfc8040.streams.listeners.NotificationListenerAdapter;
import org.opendaylight.restconf.nb.rfc8040.utils.parser.ParserIdentifier;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.restconf.rev170126.restconf.restconf.Data;
import org.opendaylight.yang.gen.v1.urn.sal.restconf.event.subscription.rev140708.NotificationOutputTypeGrouping.NotificationOutputType;
+import org.opendaylight.yangtools.yang.common.Empty;
import org.opendaylight.yangtools.yang.common.ErrorTag;
import org.opendaylight.yangtools.yang.common.ErrorType;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.ActionDefinition;
import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.model.api.SchemaNode;
import org.opendaylight.yangtools.yang.model.api.stmt.NotificationEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
public class RestconfDataServiceImpl implements RestconfDataService {
private static final Logger LOG = LoggerFactory.getLogger(RestconfDataServiceImpl.class);
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MMM-dd HH:mm:ss");
- private static final QName NETCONF_BASE_QNAME = SchemaContext.NAME;
private final RestconfStreamsSubscriptionService delegRestconfSubscrService;
private final DatabindProvider databindProvider;
final EffectiveModelContext schemaContextRef = databindProvider.currentContext().modelContext();
// FIXME: go through
final InstanceIdentifierContext instanceIdentifier = ParserIdentifier.toInstanceIdentifier(
- identifier, schemaContextRef, Optional.of(mountPointService));
+ identifier, schemaContextRef, mountPointService);
final DOMMountPoint mountPoint = instanceIdentifier.getMountPoint();
// FIXME: this looks quite crazy, why do we even have it?
private void writeNotificationStreamToDatastore(final EffectiveModelContext schemaContext,
final UriInfo uriInfo, final DOMDataTreeWriteOperations tx, final NotificationListenerAdapter listener) {
final URI uri = streamUtils.prepareUriByStreamName(uriInfo, listener.getStreamName());
- final MapEntryNode mapToStreams = RestconfStateStreams.notificationStreamEntry(
- listener.getSchemaPath().lastNodeIdentifier(), schemaContext.getNotifications(), null,
- listener.getOutputType(), uri);
+ final MapEntryNode mapToStreams = RestconfStateStreams.notificationStreamEntry(schemaContext,
+ listener.getSchemaPath().lastNodeIdentifier(), null, listener.getOutputType(), uri);
tx.merge(LogicalDatastoreType.OPERATIONAL,
- Rfc8040.restconfStateStreamPath(mapToStreams.name()), mapToStreams);
+ RestconfStateStreams.restconfStateStreamPath(mapToStreams.name()), mapToStreams);
}
@Override
final WriteDataParams params = QueryParams.newWriteDataParams(uriInfo);
final InstanceIdentifierContext iid = payload.getInstanceIdentifierContext();
+ final YangInstanceIdentifier path = iid.getInstanceIdentifier();
validInputData(iid.getSchemaNode() != null, payload);
- validTopLevelNodeName(iid.getInstanceIdentifier(), payload);
+ validTopLevelNodeName(path, payload);
validateListKeysEqualityInPayloadAndUri(payload);
final RestconfStrategy strategy = getRestconfStrategy(iid.getMountPoint());
- return PutDataTransactionUtil.putData(payload, iid.getSchemaContext(), strategy, params);
+ return PutDataTransactionUtil.putData(path, payload.getData(), iid.getSchemaContext(), strategy, params);
}
@Override
final WriteDataParams params = QueryParams.newWriteDataParams(uriInfo);
final RestconfStrategy strategy = getRestconfStrategy(iid.getMountPoint());
- return PostDataTransactionUtil.postData(uriInfo, payload, strategy, iid.getSchemaContext(), params);
+ return PostDataTransactionUtil.postData(uriInfo, iid.getInstanceIdentifier(), payload.getData(), strategy,
+ iid.getSchemaContext(), params);
}
@Override
- public Response deleteData(final String identifier) {
- final InstanceIdentifierContext instanceIdentifier = ParserIdentifier.toInstanceIdentifier(identifier,
- databindProvider.currentContext().modelContext(), Optional.of(mountPointService));
+ public void deleteData(final String identifier, final AsyncResponse ar) {
+ final var instanceIdentifier = ParserIdentifier.toInstanceIdentifier(identifier,
+ databindProvider.currentContext().modelContext(), mountPointService);
+ final var strategy = getRestconfStrategy(instanceIdentifier.getMountPoint());
+
+ Futures.addCallback(strategy.delete(instanceIdentifier.getInstanceIdentifier()), new FutureCallback<>() {
+ @Override
+ public void onSuccess(final Empty result) {
+ ar.resume(Response.noContent().build());
+ }
- final DOMMountPoint mountPoint = instanceIdentifier.getMountPoint();
- final RestconfStrategy strategy = getRestconfStrategy(mountPoint);
- return DeleteDataTransactionUtil.deleteData(strategy, instanceIdentifier.getInstanceIdentifier());
+ @Override
+ public void onFailure(final Throwable failure) {
+ ar.resume(failure);
+ }
+ }, MoreExecutors.directExecutor());
}
@Override
}
@Override
- public Response patchData(final String identifier, final NormalizedNodePayload payload, final UriInfo uriInfo) {
- requireNonNull(payload);
-
+ public void patchData(final String identifier, final NormalizedNodePayload payload, final UriInfo uriInfo,
+ final AsyncResponse ar) {
final InstanceIdentifierContext iid = payload.getInstanceIdentifierContext();
+ final YangInstanceIdentifier path = iid.getInstanceIdentifier();
validInputData(iid.getSchemaNode() != null, payload);
- validTopLevelNodeName(iid.getInstanceIdentifier(), payload);
+ validTopLevelNodeName(path, payload);
validateListKeysEqualityInPayloadAndUri(payload);
+ final var strategy = getRestconfStrategy(iid.getMountPoint());
- final RestconfStrategy strategy = getRestconfStrategy(iid.getMountPoint());
- return PlainPatchDataTransactionUtil.patchData(payload, strategy, iid.getSchemaContext());
+ Futures.addCallback(strategy.merge(path, payload.getData(), iid.getSchemaContext()), new FutureCallback<>() {
+ @Override
+ public void onSuccess(final Empty result) {
+ ar.resume(Response.ok().build());
+ }
+
+ @Override
+ public void onFailure(final Throwable failure) {
+ ar.resume(failure);
+ }
+ }, MoreExecutors.directExecutor());
}
@VisibleForTesting
final YangInstanceIdentifier yangIIdContext = context.getInstanceIdentifier();
final NormalizedNode data = payload.getData();
- if (yangIIdContext.isEmpty() && !NETCONF_BASE_QNAME.equals(data.name().getNodeType())) {
+ if (yangIIdContext.isEmpty() && !Data.QNAME.equals(data.name().getNodeType())) {
throw new RestconfDocumentedException("Instance identifier need to contain at least one path argument",
ErrorType.PROTOCOL, ErrorTag.MALFORMED_MESSAGE);
}
* @param payload input data
*/
@VisibleForTesting
- public static void validInputData(final boolean haveSchemaNode, final NormalizedNodePayload payload) {
+ static void validInputData(final boolean haveSchemaNode, final NormalizedNodePayload payload) {
final boolean haveData = payload.getData() != null;
if (haveSchemaNode) {
if (!haveData) {
* @param payload data
*/
@VisibleForTesting
- public static void validTopLevelNodeName(final YangInstanceIdentifier path, final NormalizedNodePayload payload) {
+ static void validTopLevelNodeName(final YangInstanceIdentifier path, final NormalizedNodePayload payload) {
final QName dataNodeType = payload.getData().name().getNodeType();
if (path.isEmpty()) {
- if (!NETCONF_BASE_QNAME.equals(dataNodeType)) {
+ if (!Data.QNAME.equals(dataNodeType)) {
throw new RestconfDocumentedException("Instance identifier has to contain at least one path argument",
ErrorType.PROTOCOL, ErrorTag.MALFORMED_MESSAGE);
}
}
}
-
/**
* Validates whether keys in {@code payload} are equal to values of keys in
* {@code iiWithData} for list schema node.
* @throws RestconfDocumentedException if key values or key count in payload and URI isn't equal
*/
@VisibleForTesting
- public static void validateListKeysEqualityInPayloadAndUri(final NormalizedNodePayload payload) {
+ static void validateListKeysEqualityInPayloadAndUri(final NormalizedNodePayload payload) {
final InstanceIdentifierContext iiWithData = payload.getInstanceIdentifierContext();
final PathArgument lastPathArgument = iiWithData.getInstanceIdentifier().getLastPathArgument();
final SchemaNode schemaNode = iiWithData.getSchemaNode();