Add subscribeToStream to JSONRestConfService
[netconf.git] / restconf / restconf-nb-bierman02 / src / main / java / org / opendaylight / netconf / sal / restconf / impl / JSONRestconfServiceImpl.java
index 3b5ef86b374dfe12efc6a135ac62ca303e5c83f5..64c482bf0e980bee8fe9035f94d825c3cd69c060 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.netconf.sal.restconf.impl;
 
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
@@ -16,15 +17,25 @@ import java.io.InputStream;
 import java.lang.annotation.Annotation;
 import java.nio.charset.StandardCharsets;
 import java.util.List;
+import javax.annotation.Nonnull;
 import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.UriInfo;
+
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.netconf.sal.rest.api.RestconfService;
 import org.opendaylight.netconf.sal.rest.impl.JsonNormalizedNodeBodyReader;
+import org.opendaylight.netconf.sal.rest.impl.JsonToPatchBodyReader;
 import org.opendaylight.netconf.sal.rest.impl.NormalizedNodeJsonBodyWriter;
+import org.opendaylight.netconf.sal.rest.impl.PatchJsonBodyWriter;
 import org.opendaylight.netconf.sal.restconf.api.JSONRestconfService;
 import org.opendaylight.restconf.common.context.NormalizedNodeContext;
 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.patch.PatchContext;
+import org.opendaylight.restconf.common.patch.PatchStatusContext;
+import org.opendaylight.restconf.common.util.MultivaluedHashMap;
 import org.opendaylight.restconf.common.util.SimpleUriInfo;
 import org.opendaylight.yangtools.yang.common.OperationFailedException;
 import org.opendaylight.yangtools.yang.common.RpcError;
@@ -45,6 +56,14 @@ public class JSONRestconfServiceImpl implements JSONRestconfService, AutoCloseab
 
     private static final Annotation[] EMPTY_ANNOTATIONS = new Annotation[0];
 
+    private final ControllerContext controllerContext;
+    private final RestconfService restconfService;
+
+    public JSONRestconfServiceImpl(ControllerContext controllerContext, RestconfService restconfService) {
+        this.controllerContext = controllerContext;
+        this.restconfService = restconfService;
+    }
+
     @SuppressWarnings("checkstyle:IllegalCatch")
     @Override
     public void put(final String uriPath, final String payload) throws OperationFailedException {
@@ -53,13 +72,14 @@ public class JSONRestconfServiceImpl implements JSONRestconfService, AutoCloseab
         LOG.debug("put: uriPath: {}, payload: {}", uriPath, payload);
 
         final InputStream entityStream = new ByteArrayInputStream(payload.getBytes(StandardCharsets.UTF_8));
-        final NormalizedNodeContext context = JsonNormalizedNodeBodyReader.readFrom(uriPath, entityStream, false);
+        final NormalizedNodeContext context = JsonNormalizedNodeBodyReader.readFrom(uriPath, entityStream, false,
+                controllerContext);
 
         LOG.debug("Parsed YangInstanceIdentifier: {}", context.getInstanceIdentifierContext().getInstanceIdentifier());
         LOG.debug("Parsed NormalizedNode: {}", context.getData());
 
         try {
-            RestconfImpl.getInstance().updateConfigurationData(uriPath, context, new SimpleUriInfo(uriPath));
+            restconfService.updateConfigurationData(uriPath, context, new SimpleUriInfo(uriPath));
         } catch (final Exception e) {
             propagateExceptionAs(uriPath, e, "PUT");
         }
@@ -74,13 +94,14 @@ public class JSONRestconfServiceImpl implements JSONRestconfService, AutoCloseab
         LOG.debug("post: uriPath: {}, payload: {}", uriPath, payload);
 
         final InputStream entityStream = new ByteArrayInputStream(payload.getBytes(StandardCharsets.UTF_8));
-        final NormalizedNodeContext context = JsonNormalizedNodeBodyReader.readFrom(uriPath, entityStream, true);
+        final NormalizedNodeContext context = JsonNormalizedNodeBodyReader.readFrom(uriPath, entityStream, true,
+                controllerContext);
 
         LOG.debug("Parsed YangInstanceIdentifier: {}", context.getInstanceIdentifierContext().getInstanceIdentifier());
         LOG.debug("Parsed NormalizedNode: {}", context.getData());
 
         try {
-            RestconfImpl.getInstance().createConfigurationData(uriPath, context, new SimpleUriInfo(uriPath));
+            restconfService.createConfigurationData(uriPath, context, new SimpleUriInfo(uriPath));
         } catch (final Exception e) {
             propagateExceptionAs(uriPath, e, "POST");
         }
@@ -92,7 +113,7 @@ public class JSONRestconfServiceImpl implements JSONRestconfService, AutoCloseab
         LOG.debug("delete: uriPath: {}", uriPath);
 
         try {
-            RestconfImpl.getInstance().deleteConfigurationData(uriPath);
+            restconfService.deleteConfigurationData(uriPath);
         } catch (final Exception e) {
             propagateExceptionAs(uriPath, e, "DELETE");
         }
@@ -108,9 +129,9 @@ public class JSONRestconfServiceImpl implements JSONRestconfService, AutoCloseab
             NormalizedNodeContext readData;
             final SimpleUriInfo uriInfo = new SimpleUriInfo(uriPath);
             if (datastoreType == LogicalDatastoreType.CONFIGURATION) {
-                readData = RestconfImpl.getInstance().readConfigurationData(uriPath, uriInfo);
+                readData = restconfService.readConfigurationData(uriPath, uriInfo);
             } else {
-                readData = RestconfImpl.getInstance().readOperationalData(uriPath, uriInfo);
+                readData = restconfService.readOperationalData(uriPath, uriInfo);
             }
 
             final Optional<String> result = Optional.of(toJson(readData));
@@ -129,6 +150,7 @@ public class JSONRestconfServiceImpl implements JSONRestconfService, AutoCloseab
     }
 
     @SuppressWarnings("checkstyle:IllegalCatch")
+    @SuppressFBWarnings(value = "NP_NULL_PARAM_DEREF", justification = "Unrecognised NullableDecl")
     @Override
     public Optional<String> invokeRpc(final String uriPath, final Optional<String> input)
             throws OperationFailedException {
@@ -144,31 +166,87 @@ public class JSONRestconfServiceImpl implements JSONRestconfService, AutoCloseab
             if (actualInput != null) {
                 final InputStream entityStream = new ByteArrayInputStream(actualInput.getBytes(StandardCharsets.UTF_8));
                 final NormalizedNodeContext inputContext =
-                        JsonNormalizedNodeBodyReader.readFrom(uriPath, entityStream, true);
+                        JsonNormalizedNodeBodyReader.readFrom(uriPath, entityStream, true, controllerContext);
 
                 LOG.debug("Parsed YangInstanceIdentifier: {}", inputContext.getInstanceIdentifierContext()
                         .getInstanceIdentifier());
                 LOG.debug("Parsed NormalizedNode: {}", inputContext.getData());
 
-                outputContext = RestconfImpl.getInstance().invokeRpc(uriPath, inputContext, null);
+                outputContext = restconfService.invokeRpc(uriPath, inputContext, null);
             } else {
-                outputContext = RestconfImpl.getInstance().invokeRpc(uriPath, "", null);
+                outputContext = restconfService.invokeRpc(uriPath, "", null);
             }
 
             if (outputContext.getData() != null) {
                 output = toJson(outputContext);
             }
-        } catch (final Exception e) {
+        } catch (final RuntimeException | IOException e) {
             propagateExceptionAs(uriPath, e, "RPC");
         }
 
         return Optional.fromNullable(output);
     }
 
+    @SuppressWarnings("checkstyle:IllegalCatch")
+    @Override
+    public Optional<String> patch(final String uriPath, final String payload)
+            throws OperationFailedException {
+
+        String output = null;
+        Preconditions.checkNotNull(payload, "payload can't be null");
+
+        LOG.debug("patch: uriPath: {}, payload: {}", uriPath, payload);
+
+        final InputStream entityStream = new ByteArrayInputStream(payload.getBytes(StandardCharsets.UTF_8));
+
+        JsonToPatchBodyReader jsonToPatchBodyReader = new JsonToPatchBodyReader(controllerContext);
+        final PatchContext context = jsonToPatchBodyReader.readFrom(uriPath, entityStream);
+
+        LOG.debug("Parsed YangInstanceIdentifier: {}", context.getInstanceIdentifierContext().getInstanceIdentifier());
+        LOG.debug("Parsed NormalizedNode: {}", context.getData());
+
+        try {
+            PatchStatusContext patchStatusContext = restconfService
+                .patchConfigurationData(context, new SimpleUriInfo(uriPath));
+            output = toJson(patchStatusContext);
+        } catch (final Exception e) {
+            propagateExceptionAs(uriPath, e, "PATCH");
+        }
+        return Optional.fromNullable(output);
+    }
+
+    @SuppressWarnings("checkstyle:IllegalCatch")
+    @Override
+    public Optional<String> subscribeToStream(@Nonnull String identifier,
+                                      MultivaluedMap<String, String> params) throws OperationFailedException {
+        //Note: We use http://127.0.0.1 because the Uri parser requires something there though it does nothing
+        String uri = new StringBuilder("http://127.0.0.1:8081/restconf/streams/stream/").append(identifier).toString();
+        MultivaluedMap queryParams = (params != null) ? params : new MultivaluedHashMap<String, String>();
+        UriInfo uriInfo = new SimpleUriInfo(uri, queryParams);
+
+        String jsonRes = null;
+        try {
+            NormalizedNodeContext res = restconfService.subscribeToStream(identifier, uriInfo);
+            jsonRes = toJson(res);
+        } catch (final Exception e) {
+            propagateExceptionAs(identifier, e, "RPC");
+        }
+
+        return Optional.fromNullable(jsonRes);
+    }
+
     @Override
     public void close() {
     }
 
+    private  String toJson(final PatchStatusContext patchStatusContext) throws IOException {
+        final PatchJsonBodyWriter writer = new PatchJsonBodyWriter();
+        final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        writer.writeTo(patchStatusContext, PatchStatusContext.class, null, EMPTY_ANNOTATIONS,
+                MediaType.APPLICATION_JSON_TYPE, null, outputStream);
+        return outputStream.toString(StandardCharsets.UTF_8.name());
+    }
+
     private static String toJson(final NormalizedNodeContext readData) throws IOException {
         final NormalizedNodeJsonBodyWriter writer = new NormalizedNodeJsonBodyWriter();
         final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();