Set CPS Project Status to 'Mature'
[cps.git] / cps-ncmp-rest / src / main / java / org / onap / cps / ncmp / rest / controller / handlers / NcmpPassthroughResourceRequestHandler.java
index 0e49c6d..1f87865 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
- *  Copyright (C) 2022-2023 Nordix Foundation
+ *  Copyright (C) 2022-2024 Nordix Foundation
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
 
 package org.onap.cps.ncmp.rest.controller.handlers;
 
+import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.OPERATIONAL;
+import static org.onap.cps.ncmp.api.impl.operations.OperationType.READ;
+
+import java.util.Map;
+import java.util.UUID;
+import java.util.function.BiConsumer;
 import java.util.function.Supplier;
 import org.onap.cps.ncmp.api.NetworkCmProxyDataService;
+import org.onap.cps.ncmp.api.impl.exception.InvalidDatastoreException;
+import org.onap.cps.ncmp.api.impl.operations.DatastoreType;
+import org.onap.cps.ncmp.api.impl.operations.OperationType;
+import org.onap.cps.ncmp.api.impl.utils.data.operation.ResourceDataOperationRequestUtils;
+import org.onap.cps.ncmp.api.models.CmResourceAddress;
 import org.onap.cps.ncmp.api.models.DataOperationRequest;
+import org.onap.cps.ncmp.rest.exceptions.OperationNotSupportedException;
+import org.onap.cps.ncmp.rest.exceptions.PayloadTooLargeException;
 import org.onap.cps.ncmp.rest.executor.CpsNcmpTaskExecutor;
-import org.springframework.scheduling.annotation.Async;
+import org.onap.cps.ncmp.rest.util.TopicValidator;
+import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Component;
 
 @Component
@@ -32,6 +46,12 @@ public class NcmpPassthroughResourceRequestHandler extends NcmpDatastoreRequestH
 
     private final NetworkCmProxyDataService networkCmProxyDataService;
 
+    private static final Object noReturn = null;
+
+    private static final int MAXIMUM_CM_HANDLES_PER_OPERATION = 50000;
+
+    private static final String PAYLOAD_TOO_LARGE_TEMPLATE = "Operation '%s' affects too many (%d) cm handles";
+
     /**
      * Constructor.
      *
@@ -44,27 +64,91 @@ public class NcmpPassthroughResourceRequestHandler extends NcmpDatastoreRequestH
         this.networkCmProxyDataService = networkCmProxyDataService;
     }
 
-    @Override
-    public Supplier<Object> getTaskSupplierForGetRequest(final String datastoreName,
-                                                         final String cmHandleId,
-                                                         final String resourceIdentifier,
-                                                         final String optionsParamInQuery,
-                                                         final String topicParamInQuery,
-                                                         final String requestId,
-                                                         final boolean includeDescendants) {
-
-        return () -> networkCmProxyDataService.getResourceDataForCmHandle(
-                datastoreName, cmHandleId, resourceIdentifier, optionsParamInQuery, topicParamInQuery, requestId);
+    /**
+     * Executes asynchronous request for group of cm handles to resource data.
+     *
+     * @param topicParamInQuery        the topic param in query
+     * @param dataOperationRequest     data operation request details for resource data
+     * @param authorization            contents of Authorization header, or null if not present
+     * @return the response entity
+     */
+    public ResponseEntity<Object> executeRequest(final String topicParamInQuery,
+                                                 final DataOperationRequest dataOperationRequest,
+                                                 final String authorization) {
+        validateDataOperationRequest(topicParamInQuery, dataOperationRequest);
+        if (!notificationFeatureEnabled) {
+            return ResponseEntity.ok(Map.of("status",
+                "Asynchronous request is unavailable as notification feature is currently disabled."));
+        }
+        return getRequestIdAndSendDataOperationRequestToDmiService(topicParamInQuery, dataOperationRequest,
+                authorization);
     }
 
-    @Async
     @Override
-    public void sendDataOperationRequestAsynchronously(final String topicParamInQuery,
-                                                       final DataOperationRequest
-                                                                   dataOperationRequest,
-                                                       final String requestId) {
-        networkCmProxyDataService.executeDataOperationForCmHandles(topicParamInQuery, dataOperationRequest,
-                requestId);
+    protected Supplier<Object> getTaskSupplierForGetRequest(final CmResourceAddress cmResourceAddress,
+                                                            final String optionsParamInQuery,
+                                                            final String topicParamInQuery,
+                                                            final String requestId,
+                                                            final boolean includeDescendants,
+                                                            final String authorization) {
 
+        return () -> networkCmProxyDataService.getResourceDataForCmHandle(cmResourceAddress, optionsParamInQuery,
+            topicParamInQuery, requestId, authorization);
     }
+
+    private ResponseEntity<Object> getRequestIdAndSendDataOperationRequestToDmiService(
+            final String topicParamInQuery,
+            final DataOperationRequest dataOperationRequest,
+            final String authorization) {
+        final String requestId = UUID.randomUUID().toString();
+        cpsNcmpTaskExecutor.executeTaskWithErrorHandling(
+            getTaskSupplierForDataOperationRequest(topicParamInQuery, dataOperationRequest, requestId, authorization),
+            getTaskCompletionHandlerForDataOperationRequest(topicParamInQuery, dataOperationRequest, requestId),
+            timeOutInMilliSeconds);
+        return ResponseEntity.ok(Map.of("requestId", requestId));
+    }
+
+    private void validateDataOperationRequest(final String topicParamInQuery,
+                                              final DataOperationRequest dataOperationRequest) {
+        TopicValidator.validateTopicName(topicParamInQuery);
+        dataOperationRequest.getDataOperationDefinitions().forEach(dataOperationDetail -> {
+            if (OperationType.fromOperationName(dataOperationDetail.getOperation()) != READ) {
+                throw new OperationNotSupportedException(
+                    dataOperationDetail.getOperation() + " operation not yet supported");
+            }
+            if (DatastoreType.fromDatastoreName(dataOperationDetail.getDatastore()) == OPERATIONAL) {
+                throw new InvalidDatastoreException(dataOperationDetail.getDatastore()
+                    + " datastore is not supported");
+            }
+            if (dataOperationDetail.getCmHandleIds().size() > MAXIMUM_CM_HANDLES_PER_OPERATION) {
+                final String errorMessage = String.format(PAYLOAD_TOO_LARGE_TEMPLATE,
+                    dataOperationDetail.getOperationId(),
+                    dataOperationDetail.getCmHandleIds().size());
+                throw new PayloadTooLargeException(errorMessage);
+            }
+        });
+    }
+
+    private Supplier<Object> getTaskSupplierForDataOperationRequest(final String topicParamInQuery,
+                                                                    final DataOperationRequest dataOperationRequest,
+                                                                    final String requestId,
+                                                                    final String authorization) {
+        return () -> {
+            networkCmProxyDataService.executeDataOperationForCmHandles(topicParamInQuery,
+                dataOperationRequest,
+                requestId,
+                authorization);
+            return noReturn;
+        };
+    }
+
+    private static BiConsumer<Object, Throwable> getTaskCompletionHandlerForDataOperationRequest(
+            final String topicParamInQuery,
+            final DataOperationRequest dataOperationRequest,
+            final String requestId) {
+        return (result, throwable) ->
+                ResourceDataOperationRequestUtils.handleAsyncTaskCompletionForDataOperationsRequest(topicParamInQuery,
+                        requestId, dataOperationRequest, throwable);
+    }
+
 }