2  *  ============LICENSE_START=======================================================
 
   3  *  Copyright (C) 2022-2023 Nordix Foundation
 
   4  *  ================================================================================
 
   5  *  Licensed under the Apache License, Version 2.0 (the "License");
 
   6  *  you may not use this file except in compliance with the License.
 
   7  *  You may obtain a copy of the License at
 
   9  *        http://www.apache.org/licenses/LICENSE-2.0
 
  11  *  Unless required by applicable law or agreed to in writing, software
 
  12  *  distributed under the License is distributed on an "AS IS" BASIS,
 
  13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
  14  *  See the License for the specific language governing permissions and
 
  15  *  limitations under the License.
 
  17  *  SPDX-License-Identifier: Apache-2.0
 
  18  *  ============LICENSE_END=========================================================
 
  21 package org.onap.cps.ncmp.rest.controller.handlers;
 
  23 import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.OPERATIONAL;
 
  24 import static org.onap.cps.ncmp.api.impl.operations.OperationType.READ;
 
  27 import java.util.UUID;
 
  28 import java.util.function.Supplier;
 
  29 import lombok.RequiredArgsConstructor;
 
  30 import lombok.extern.slf4j.Slf4j;
 
  31 import org.onap.cps.ncmp.api.impl.exception.InvalidDatastoreException;
 
  32 import org.onap.cps.ncmp.api.impl.operations.DatastoreType;
 
  33 import org.onap.cps.ncmp.api.impl.operations.OperationType;
 
  34 import org.onap.cps.ncmp.api.models.ResourceDataBatchRequest;
 
  35 import org.onap.cps.ncmp.rest.exceptions.OperationNotSupportedException;
 
  36 import org.onap.cps.ncmp.rest.executor.CpsNcmpTaskExecutor;
 
  37 import org.onap.cps.ncmp.rest.util.TopicValidator;
 
  38 import org.springframework.beans.factory.annotation.Value;
 
  39 import org.springframework.http.HttpStatus;
 
  40 import org.springframework.http.ResponseEntity;
 
  41 import org.springframework.stereotype.Service;
 
  45 @RequiredArgsConstructor
 
  46 public class NcmpDatastoreRequestHandler implements TaskManagementDefaultHandler {
 
  48     @Value("${notification.async.executor.time-out-value-in-ms:2000}")
 
  49     protected int timeOutInMilliSeconds;
 
  51     @Value("${notification.enabled:true}")
 
  52     protected boolean notificationFeatureEnabled;
 
  54     private final CpsNcmpTaskExecutor cpsNcmpTaskExecutor;
 
  57      * Executes synchronous/asynchronous request for given cm handle.
 
  59      * @param datastoreName       the name of the datastore
 
  60      * @param cmHandleId          the cm handle
 
  61      * @param resourceIdentifier  the resource identifier
 
  62      * @param optionsParamInQuery the options param in query
 
  63      * @param topicParamInQuery   the topic param in query
 
  64      * @param includeDescendants  whether include descendants
 
  65      * @return the response entity
 
  67     public ResponseEntity<Object> executeRequest(final String datastoreName,
 
  68                                                  final String cmHandleId,
 
  69                                                  final String resourceIdentifier,
 
  70                                                  final String optionsParamInQuery,
 
  71                                                  final String topicParamInQuery,
 
  72                                                  final boolean includeDescendants) {
 
  74         final boolean asyncResponseRequested = topicParamInQuery != null;
 
  75         if (asyncResponseRequested && notificationFeatureEnabled) {
 
  76             return executeAsyncTaskAndGetResponseEntity(datastoreName, cmHandleId, resourceIdentifier,
 
  77                 optionsParamInQuery, topicParamInQuery, includeDescendants);
 
  80         if (asyncResponseRequested) {
 
  81             log.warn("Asynchronous request is unavailable as notification feature is currently disabled, "
 
  82                     + "will use synchronous operation.");
 
  84         final Supplier<Object> taskSupplier = getTaskSupplierForGetRequest(datastoreName, cmHandleId,
 
  85                 resourceIdentifier, optionsParamInQuery, NO_TOPIC, NO_REQUEST_ID, includeDescendants);
 
  86         return executeTaskSync(taskSupplier);
 
  90      * Executes a synchronous request for given cm handle.
 
  91      * Note. Currently only ncmp-datastore:operational supports query operations.
 
  93      * @param cmHandleId         the cm handle
 
  94      * @param resourceIdentifier the resource identifier
 
  95      * @param includeDescendants whether include descendants
 
  96      * @return the response entity
 
  98     public ResponseEntity<Object> executeRequest(final String cmHandleId,
 
  99                                                  final String resourceIdentifier,
 
 100                                                  final boolean includeDescendants) {
 
 102         final Supplier<Object> taskSupplier = getTaskSupplierForQueryRequest(cmHandleId, resourceIdentifier,
 
 104         return executeTaskSync(taskSupplier);
 
 108      * Executes asynchronous request for batch of cm handles to resource data.
 
 110      * @param topicParamInQuery        the topic param in query
 
 111      * @param resourceDataBatchRequest batch request details for resource data
 
 112      * @return the response entity
 
 114     public ResponseEntity<Object> executeRequest(final String topicParamInQuery,
 
 115                                                  final ResourceDataBatchRequest
 
 116                                                          resourceDataBatchRequest) {
 
 117         validateBatchRequest(topicParamInQuery, resourceDataBatchRequest);
 
 118         if (!notificationFeatureEnabled) {
 
 119             return ResponseEntity.ok(Map.of("status",
 
 120                     "Asynchronous request is unavailable as notification feature is currently disabled."));
 
 122         return getRequestIdAndSendBatchRequestToDmiService(topicParamInQuery, resourceDataBatchRequest);
 
 125     protected ResponseEntity<Object> executeTaskAsync(final String topicParamInQuery,
 
 126                                                       final String requestId,
 
 127                                                       final Supplier<Object> taskSupplier) {
 
 129         TopicValidator.validateTopicName(topicParamInQuery);
 
 130         log.debug("Received Async request with id {}", requestId);
 
 131         cpsNcmpTaskExecutor.executeTask(taskSupplier, timeOutInMilliSeconds);
 
 132         return ResponseEntity.ok(Map.of("requestId", requestId));
 
 135     protected ResponseEntity<Object> executeTaskSync(final Supplier<Object> taskSupplier) {
 
 136         return ResponseEntity.ok(taskSupplier.get());
 
 139     private ResponseEntity<Object> executeAsyncTaskAndGetResponseEntity(final String datastoreName,
 
 140                                                                         final String cmHandleId,
 
 141                                                                         final String resourceIdentifier,
 
 142                                                                         final String optionsParamInQuery,
 
 143                                                                         final String topicParamInQuery,
 
 144                                                                         final boolean includeDescendants) {
 
 145         final String requestId = UUID.randomUUID().toString();
 
 146         final Supplier<Object> taskSupplier = getTaskSupplierForGetRequest(datastoreName, cmHandleId,
 
 147                 resourceIdentifier, optionsParamInQuery, topicParamInQuery, requestId, includeDescendants);
 
 148         if (taskSupplier == NO_OBJECT_SUPPLIER) {
 
 149             return new ResponseEntity<>(Map.of("status", "Unable to execute request as "
 
 150                     + "datastore is not implemented."), HttpStatus.NOT_IMPLEMENTED);
 
 152         return executeTaskAsync(topicParamInQuery, requestId, taskSupplier);
 
 155     private ResponseEntity<Object> getRequestIdAndSendBatchRequestToDmiService(final String topicParamInQuery,
 
 156                                                                                final ResourceDataBatchRequest
 
 157                                                                                        resourceDataBatchRequest) {
 
 158         final String requestId = UUID.randomUUID().toString();
 
 159         sendResourceDataBatchRequestAsynchronously(topicParamInQuery, resourceDataBatchRequest, requestId);
 
 160         return ResponseEntity.ok(Map.of("requestId", requestId));
 
 163     private void validateBatchRequest(final String topicParamInQuery,
 
 164                                       final ResourceDataBatchRequest
 
 165                                               resourceDataBatchRequest) {
 
 166         TopicValidator.validateTopicName(topicParamInQuery);
 
 167         resourceDataBatchRequest.getBatchOperationDefinitions().forEach(batchOperationDetail -> {
 
 168             if (OperationType.fromOperationName(batchOperationDetail.getOperation()) != READ) {
 
 169                 throw new OperationNotSupportedException(
 
 170                         batchOperationDetail.getOperation() + " operation not yet supported for target ids :"
 
 171                                 + batchOperationDetail.getCmHandleIds());
 
 172             } else if (DatastoreType.fromDatastoreName(batchOperationDetail.getDatastore()) == OPERATIONAL) {
 
 173                 throw new InvalidDatastoreException(batchOperationDetail.getDatastore()
 
 174                         + " datastore is not supported for target ids : "
 
 175                         + batchOperationDetail.getCmHandleIds());