From 98d9ac273754a8637bb5e08b1ec7c0b98c645e9e Mon Sep 17 00:00:00 2001 From: ToineSiebelink Date: Thu, 27 Jun 2024 12:49:27 +0100 Subject: repackage 'data' feature - moved relevant classes into these (new) packages: api.data.exceptions api.data.models impl.data impl.data.async impl.data.exceptions impl.data.models impl.data.utils utils.events - removed old unused event class - moves some missed inventory related class to the right place Issue-ID: CPS-2256 Change-Id: I75563e063acc0054769d8f2b13146e6c1d1c6054 Signed-off-by: ToineSiebelink --- .../cps/ncmp/api/NetworkCmProxyQueryService.java | 50 ---- .../data/exceptions/InvalidDatastoreException.java | 32 +++ .../exceptions/OperationNotSupportedException.java | 32 +++ .../ncmp/api/data/models/CmResourceAddress.java | 25 ++ .../api/data/models/DataOperationDefinition.java | 49 ++++ .../ncmp/api/data/models/DataOperationRequest.java | 43 +++ .../cps/ncmp/api/data/models/DatastoreType.java | 67 +++++ .../cps/ncmp/api/data/models/OperationType.java | 62 +++++ .../api/impl/NcmpCachedResourceRequestHandler.java | 76 ------ .../ncmp/api/impl/NcmpDatastoreRequestHandler.java | 96 ------- .../NcmpPassthroughResourceRequestHandler.java | 103 ------- .../cps/ncmp/api/impl/NetworkCmProxyFacade.java | 129 --------- .../api/impl/NetworkCmProxyQueryServiceImpl.java | 48 ---- .../AsyncRestRequestResponseEventConsumer.java | 62 ----- .../api/impl/async/DataOperationEventConsumer.java | 63 ----- .../async/NcmpAsyncRequestResponseEventMapper.java | 72 ----- .../api/impl/async/RecordFilterStrategies.java | 77 ------ .../cps/ncmp/api/impl/client/DmiRestClient.java | 4 +- .../CmNotificationSubscriptionDelta.java | 2 +- .../DmiCmNotificationSubscriptionCacheHandler.java | 2 +- .../DmiCmNotificationSubscriptionPredicate.java | 2 +- ...NotificationSubscriptionPersistenceService.java | 2 +- ...ficationSubscriptionPersistenceServiceImpl.java | 2 +- .../impl/exception/InvalidDatastoreException.java | 32 --- .../impl/exception/InvalidOperationException.java | 32 --- .../ncmp/api/impl/operations/DatastoreType.java | 67 ----- .../ncmp/api/impl/operations/DmiDataOperation.java | 62 ----- .../impl/operations/DmiDataOperationRequest.java | 35 --- .../api/impl/operations/DmiDataOperations.java | 297 -------------------- .../api/impl/operations/DmiModelOperations.java | 185 ------------- .../api/impl/operations/DmiOperationCmHandle.java | 49 ---- .../ncmp/api/impl/operations/DmiRequestBody.java | 61 ----- .../ncmp/api/impl/operations/OperationType.java | 62 ----- .../api/impl/operations/RequiredDmiService.java | 28 -- .../ncmp/api/impl/utils/AlternateIdChecker.java | 152 ----------- .../api/impl/utils/DmiServiceNameOrganizer.java | 2 +- .../data/operation/DataOperationEventCreator.java | 99 ------- .../ResourceDataOperationRequestUtils.java | 201 -------------- .../YangModelCmDataSubscriptionEvent.java | 76 ------ .../cps/ncmp/api/models/CmResourceAddress.java | 25 -- .../ncmp/api/models/DataOperationDefinition.java | 49 ---- .../cps/ncmp/api/models/DataOperationRequest.java | 43 --- .../exceptions/OperationNotSupportedException.java | 32 --- .../onap/cps/ncmp/impl/data/DmiDataOperations.java | 303 +++++++++++++++++++++ .../data/NcmpCachedResourceRequestHandler.java | 75 +++++ .../impl/data/NcmpDatastoreRequestHandler.java | 96 +++++++ .../NcmpPassthroughResourceRequestHandler.java | 102 +++++++ .../cps/ncmp/impl/data/NetworkCmProxyFacade.java | 128 +++++++++ .../ncmp/impl/data/NetworkCmProxyQueryService.java | 50 ++++ .../impl/data/NetworkCmProxyQueryServiceImpl.java | 47 ++++ .../AsyncRestRequestResponseEventConsumer.java | 62 +++++ .../data/async/DataOperationEventConsumer.java | 63 +++++ .../async/NcmpAsyncRequestResponseEventMapper.java | 72 +++++ .../impl/data/async/RecordFilterStrategies.java | 77 ++++++ .../data/exceptions/InvalidOperationException.java | 32 +++ .../ncmp/impl/data/models/DmiDataOperation.java | 64 +++++ .../impl/data/models/DmiDataOperationRequest.java | 35 +++ .../impl/data/models/DmiOperationCmHandle.java | 49 ++++ .../impl/data/utils/DataOperationEventCreator.java | 99 +++++++ .../impl/data/utils/DmiDataOperationsHelper.java | 201 ++++++++++++++ .../impl/datajobs/DmiSubJobRequestHandler.java | 4 +- .../ncmp/impl/inventory/AlternateIdChecker.java | 151 ++++++++++ .../inventory/CmHandleRegistrationService.java | 1 - ...CmHandleRegistrationServicePropertyHandler.java | 1 - .../impl/inventory/models/YangModelCmHandle.java | 2 +- .../impl/inventory/sync/DmiModelOperations.java | 186 +++++++++++++ .../impl/inventory/sync/ModuleOperationsUtils.java | 2 +- .../impl/inventory/sync/ModuleSyncService.java | 1 - .../inventory/trustlevel/TrustLevelManager.java | 2 +- .../onap/cps/ncmp/impl/models/DmiRequestBody.java | 62 +++++ .../cps/ncmp/impl/models/RequiredDmiService.java | 28 ++ .../ncmp/init/CmDataSubscriptionModelLoader.java | 2 +- .../cps/ncmp/utils/events/CmAvcEventPublisher.java | 1 + 73 files changed, 2307 insertions(+), 2380 deletions(-) delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyQueryService.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/data/exceptions/InvalidDatastoreException.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/data/exceptions/OperationNotSupportedException.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/data/models/CmResourceAddress.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/data/models/DataOperationDefinition.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/data/models/DataOperationRequest.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/data/models/DatastoreType.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/data/models/OperationType.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NcmpCachedResourceRequestHandler.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NcmpDatastoreRequestHandler.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NcmpPassthroughResourceRequestHandler.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyFacade.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyQueryServiceImpl.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/async/AsyncRestRequestResponseEventConsumer.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/async/DataOperationEventConsumer.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/async/NcmpAsyncRequestResponseEventMapper.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/async/RecordFilterStrategies.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/InvalidDatastoreException.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/InvalidOperationException.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DatastoreType.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperation.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperationRequest.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiModelOperations.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiOperationCmHandle.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiRequestBody.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/OperationType.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/RequiredDmiService.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/AlternateIdChecker.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/DataOperationEventCreator.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/ResourceDataOperationRequestUtils.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmDataSubscriptionEvent.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmResourceAddress.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DataOperationDefinition.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DataOperationRequest.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/exceptions/OperationNotSupportedException.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/DmiDataOperations.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NcmpCachedResourceRequestHandler.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NcmpDatastoreRequestHandler.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NcmpPassthroughResourceRequestHandler.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NetworkCmProxyFacade.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NetworkCmProxyQueryService.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NetworkCmProxyQueryServiceImpl.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/async/AsyncRestRequestResponseEventConsumer.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/async/DataOperationEventConsumer.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/async/NcmpAsyncRequestResponseEventMapper.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/async/RecordFilterStrategies.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/exceptions/InvalidOperationException.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/models/DmiDataOperation.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/models/DmiDataOperationRequest.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/models/DmiOperationCmHandle.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/utils/DataOperationEventCreator.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/utils/DmiDataOperationsHelper.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/AlternateIdChecker.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperations.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/models/DmiRequestBody.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/models/RequiredDmiService.java (limited to 'cps-ncmp-service/src/main/java') diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyQueryService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyQueryService.java deleted file mode 100644 index 39d497217f..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyQueryService.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.cps.ncmp.api; - -import java.util.Collection; -import org.onap.cps.spi.FetchDescendantsOption; -import org.onap.cps.spi.model.DataNode; - -/* - * Datastore interface for handling cached CPS data query requests. - */ -public interface NetworkCmProxyQueryService { - - /** - * Fetches operational resource data based on the provided CM handle identifier and CPS path. - * This method retrieves data nodes from the specified path within the context of a given CM handle. - * It supports options for fetching descendant nodes. - * - * @param cmHandleId The CM handle identifier, which uniquely identifies the CM handle. - * This parameter must not be null. - * @param cpsPath The CPS (Control Plane Service) path specifying the location of the - * resource data within the CM handle. This parameter must not be null. - * @param fetchDescendantsOption The option specifying whether to fetch descendant nodes along with the specified - * resource data. - * @return {@code Collection} A collection of DataNode objects representing the resource data - * retrieved from the specified path. The collection may include descendant nodes based on the - * fetchDescendantsOption. - */ - Collection queryResourceDataOperational(String cmHandleId, - String cpsPath, - FetchDescendantsOption fetchDescendantsOption); -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/data/exceptions/InvalidDatastoreException.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/data/exceptions/InvalidDatastoreException.java new file mode 100644 index 0000000000..740785e3be --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/data/exceptions/InvalidDatastoreException.java @@ -0,0 +1,32 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2023 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.api.data.exceptions; + +public class InvalidDatastoreException extends RuntimeException { + /** + * Instantiates a new Invalid datastore exception. + * + * @param message the message + */ + public InvalidDatastoreException(final String message) { + super(message); + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/data/exceptions/OperationNotSupportedException.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/data/exceptions/OperationNotSupportedException.java new file mode 100644 index 0000000000..eea846a0f6 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/data/exceptions/OperationNotSupportedException.java @@ -0,0 +1,32 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2023 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.api.data.exceptions; + +public class OperationNotSupportedException extends RuntimeException { + /** + * Instantiates a new not implemented operation exception. + * + * @param message the message + */ + public OperationNotSupportedException(final String message) { + super(message); + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/data/models/CmResourceAddress.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/data/models/CmResourceAddress.java new file mode 100644 index 0000000000..e93aa4c603 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/data/models/CmResourceAddress.java @@ -0,0 +1,25 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.api.data.models; + +public record CmResourceAddress(String datastoreName, String cmHandleId, String resourceIdentifier) { + +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/data/models/DataOperationDefinition.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/data/models/DataOperationDefinition.java new file mode 100644 index 0000000000..d1ff1a5815 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/data/models/DataOperationDefinition.java @@ -0,0 +1,49 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2023 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.api.data.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.Valid; +import java.util.ArrayList; +import java.util.List; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@EqualsAndHashCode +@JsonInclude(JsonInclude.Include.NON_EMPTY) +@JsonIgnoreProperties(ignoreUnknown = true) +public class DataOperationDefinition { + + private String operation; + private String operationId; + private String datastore; + private String options; + private String resourceIdentifier; + + @JsonProperty("targetIds") + @Valid + private List cmHandleIds = new ArrayList<>(); +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/data/models/DataOperationRequest.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/data/models/DataOperationRequest.java new file mode 100644 index 0000000000..b104f587fb --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/data/models/DataOperationRequest.java @@ -0,0 +1,43 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2023 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.api.data.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.Valid; +import java.util.Collections; +import java.util.List; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@EqualsAndHashCode +@JsonInclude(JsonInclude.Include.NON_EMPTY) +@JsonIgnoreProperties(ignoreUnknown = true) +public class DataOperationRequest { + + @JsonProperty("operations") + @Valid + private List dataOperationDefinitions = Collections.emptyList(); +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/data/models/DatastoreType.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/data/models/DatastoreType.java new file mode 100644 index 0000000000..a483341b65 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/data/models/DatastoreType.java @@ -0,0 +1,67 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2023 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.api.data.models; + + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import lombok.Getter; +import org.onap.cps.ncmp.api.data.exceptions.InvalidDatastoreException; + +@Getter +public enum DatastoreType { + + OPERATIONAL("ncmp-datastore:operational"), + PASSTHROUGH_RUNNING("ncmp-datastore:passthrough-running"), + PASSTHROUGH_OPERATIONAL("ncmp-datastore:passthrough-operational"); + + DatastoreType(final String datastoreName) { + this.datastoreName = datastoreName; + } + + private final String datastoreName; + private static final Map datastoreNameToDatastoreType = new HashMap<>(); + + static { + Arrays.stream(DatastoreType.values()).forEach( + type -> datastoreNameToDatastoreType.put(type.getDatastoreName(), type)); + } + + /** + * From datastore name get datastore type. + * + * @param datastoreName the datastore name + * @return the datastore type + */ + public static DatastoreType fromDatastoreName(final String datastoreName) { + + final DatastoreType datastoreType = datastoreNameToDatastoreType.get(datastoreName); + + if (null == datastoreType) { + throw new InvalidDatastoreException(datastoreName + " is an invalid datastore name"); + } + + return datastoreType; + } + +} + diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/data/models/OperationType.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/data/models/OperationType.java new file mode 100644 index 0000000000..da95fca714 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/data/models/OperationType.java @@ -0,0 +1,62 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2023 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.api.data.models; + +import com.fasterxml.jackson.annotation.JsonValue; +import java.util.Locale; +import lombok.Getter; +import org.onap.cps.ncmp.impl.data.exceptions.InvalidOperationException; + +@Getter +public enum OperationType { + + READ("read"), + CREATE("create"), + UPDATE("update"), + PATCH("patch"), + DELETE("delete"); + + private final String operationName; + + OperationType(final String operationName) { + this.operationName = operationName; + } + + @Override + @JsonValue + public String toString() { + return String.valueOf(operationName); + } + + /** + * From operation name get operation enum type. + * + * @param operationName the operation name + * @return the operation enum type + */ + public static OperationType fromOperationName(final String operationName) { + try { + return OperationType.valueOf(operationName.toUpperCase(Locale.ENGLISH)); + } catch (final IllegalArgumentException e) { + throw new InvalidOperationException(operationName + " is an invalid operation name"); + } + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NcmpCachedResourceRequestHandler.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NcmpCachedResourceRequestHandler.java deleted file mode 100644 index da230cf732..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NcmpCachedResourceRequestHandler.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.cps.ncmp.api.impl; - -import java.util.Collection; -import lombok.RequiredArgsConstructor; -import org.onap.cps.api.CpsDataService; -import org.onap.cps.ncmp.api.NetworkCmProxyQueryService; -import org.onap.cps.ncmp.api.models.CmResourceAddress; -import org.onap.cps.spi.FetchDescendantsOption; -import org.onap.cps.spi.model.DataNode; -import org.springframework.stereotype.Service; -import reactor.core.publisher.Mono; - -@Service -@RequiredArgsConstructor -public class NcmpCachedResourceRequestHandler extends NcmpDatastoreRequestHandler { - - private final CpsDataService cpsDataService; - private final NetworkCmProxyQueryService networkCmProxyQueryService; - - /** - * Executes a synchronous query request for given cm handle. - * Note. Currently only ncmp-datastore:operational supports query operations. - * - * @param cmHandleId the cm handle - * @param resourceIdentifier the resource identifier - * @param includeDescendants whether include descendants - * @return a collection of data nodes - */ - public Collection executeRequest(final String cmHandleId, final String resourceIdentifier, - final boolean includeDescendants) { - final FetchDescendantsOption fetchDescendantsOption = getFetchDescendantsOption(includeDescendants); - return networkCmProxyQueryService.queryResourceDataOperational(cmHandleId, resourceIdentifier, - fetchDescendantsOption); - } - - @Override - protected Mono getResourceDataForCmHandle(final CmResourceAddress cmResourceAddress, - final String optionsParamInQuery, - final String topicParamInQuery, - final String requestId, - final boolean includeDescendants, - final String authorization) { - final FetchDescendantsOption fetchDescendantsOption = getFetchDescendantsOption(includeDescendants); - - final DataNode dataNode = cpsDataService.getDataNodes(cmResourceAddress.datastoreName(), - cmResourceAddress.cmHandleId(), - cmResourceAddress.resourceIdentifier(), - fetchDescendantsOption).iterator().next(); - return Mono.justOrEmpty(dataNode); - } - - private static FetchDescendantsOption getFetchDescendantsOption(final boolean includeDescendants) { - return includeDescendants ? FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS - : FetchDescendantsOption.OMIT_DESCENDANTS; - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NcmpDatastoreRequestHandler.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NcmpDatastoreRequestHandler.java deleted file mode 100644 index 95453a71da..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NcmpDatastoreRequestHandler.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.cps.ncmp.api.impl; - -import java.util.Map; -import java.util.UUID; -import lombok.extern.slf4j.Slf4j; -import org.onap.cps.ncmp.api.models.CmResourceAddress; -import org.onap.cps.ncmp.utils.events.TopicValidator; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Service; -import reactor.core.publisher.Mono; - -@Slf4j -@Service -public abstract class NcmpDatastoreRequestHandler { - - private static final String NO_REQUEST_ID = null; - private static final String NO_TOPIC = null; - - @Value("${notification.async.executor.time-out-value-in-ms:60000}") - protected int timeOutInMilliSeconds; - @Value("${notification.enabled:true}") - protected boolean notificationFeatureEnabled; - - /** - * Executes synchronous/asynchronous get request for given cm handle. - * - * @param cmResourceAddress the name of the datastore, cm handle and resource identifier - * @param options options to pass through to dmi client - * @param topic topic (optional) for asynchronous responses - * @param includeDescendants whether include descendants - * @param authorization contents of Authorization header, or null if not present - * @return the result object, depends on use op topic. With topic a map object with request id is returned - * otherwise the result of the request. - */ - public Object executeRequest(final CmResourceAddress cmResourceAddress, - final String options, - final String topic, - final boolean includeDescendants, - final String authorization) { - - final boolean asyncResponseRequested = topic != null; - if (asyncResponseRequested && notificationFeatureEnabled) { - return getResourceDataAsynchronously(cmResourceAddress, options, topic, includeDescendants, authorization); - } - - if (asyncResponseRequested) { - log.warn("Asynchronous request is unavailable as notification feature is currently disabled, " - + "will use synchronous operation."); - } - final Mono resourceDataMono = getResourceDataForCmHandle(cmResourceAddress, options, - NO_TOPIC, NO_REQUEST_ID, includeDescendants, authorization); - return resourceDataMono.block(); - } - - private Map getResourceDataAsynchronously(final CmResourceAddress cmResourceAddress, - final String options, - final String topic, - final boolean includeDescendants, - final String authorization) { - TopicValidator.validateTopicName(topic); - final String requestId = UUID.randomUUID().toString(); - getResourceDataForCmHandle(cmResourceAddress, options, topic, requestId, includeDescendants, authorization) - .doOnSuccess(result -> - log.debug("Async operation succeeded for request id {}: {}", requestId, result)) - .subscribe(); - log.debug("Received Async request with id {}", requestId); - return Map.of("requestId", requestId); - } - - protected abstract Mono getResourceDataForCmHandle(final CmResourceAddress cmResourceAddress, - final String optionsParamInQuery, - final String topicParamInQuery, - final String requestId, - final boolean includeDescendant, - final String authorization); -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NcmpPassthroughResourceRequestHandler.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NcmpPassthroughResourceRequestHandler.java deleted file mode 100644 index 0867ab44a5..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NcmpPassthroughResourceRequestHandler.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.cps.ncmp.api.impl; - -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 lombok.RequiredArgsConstructor; -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.DmiDataOperations; -import org.onap.cps.ncmp.api.impl.operations.OperationType; -import org.onap.cps.ncmp.api.models.CmResourceAddress; -import org.onap.cps.ncmp.api.models.DataOperationRequest; -import org.onap.cps.ncmp.exceptions.OperationNotSupportedException; -import org.onap.cps.ncmp.exceptions.PayloadTooLargeException; -import org.onap.cps.ncmp.utils.events.TopicValidator; -import org.springframework.stereotype.Service; -import reactor.core.publisher.Mono; - -@Service -@RequiredArgsConstructor -public class NcmpPassthroughResourceRequestHandler extends NcmpDatastoreRequestHandler { - - private final DmiDataOperations dmiDataOperations; - - private static final int MAXIMUM_CM_HANDLES_PER_OPERATION = 200; - private static final String PAYLOAD_TOO_LARGE_TEMPLATE = "Operation '%s' affects too many (%d) cm handles"; - - /** - * Executes asynchronous request for group of cm handles to resource data. - * - * @param topic 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 a map with one entry of request Id for success or status and error when async feature is disabled - */ - public Map executeAsynchronousRequest(final String topic, - final DataOperationRequest dataOperationRequest, - final String authorization) { - validateDataOperationRequest(topic, dataOperationRequest); - if (!notificationFeatureEnabled) { - return Map.of("status", - "Asynchronous request is unavailable as notification feature is currently disabled."); - } - final String requestId = UUID.randomUUID().toString(); - dmiDataOperations.requestResourceDataFromDmi(topic, dataOperationRequest, requestId, authorization); - return Map.of("requestId", requestId); - } - - @Override - protected Mono getResourceDataForCmHandle(final CmResourceAddress cmResourceAddress, - final String options, - final String topic, - final String requestId, - final boolean includeDescendants, - final String authorization) { - - return dmiDataOperations.getResourceDataFromDmi(cmResourceAddress, options, topic, requestId, authorization) - .flatMap(responseEntity -> Mono.justOrEmpty(responseEntity.getBody())); - } - - private void validateDataOperationRequest(final String topicParamInQuery, - final DataOperationRequest dataOperationRequest) { - TopicValidator.validateTopicName(topicParamInQuery); - dataOperationRequest.getDataOperationDefinitions().forEach(dataOperationDefinition -> { - if (OperationType.fromOperationName(dataOperationDefinition.getOperation()) != READ) { - throw new OperationNotSupportedException( - dataOperationDefinition.getOperation() + " operation not yet supported"); - } - if (DatastoreType.fromDatastoreName(dataOperationDefinition.getDatastore()) == OPERATIONAL) { - throw new InvalidDatastoreException(dataOperationDefinition.getDatastore() - + " datastore is not supported"); - } - if (dataOperationDefinition.getCmHandleIds().size() > MAXIMUM_CM_HANDLES_PER_OPERATION) { - final String errorMessage = String.format(PAYLOAD_TOO_LARGE_TEMPLATE, - dataOperationDefinition.getOperationId(), - dataOperationDefinition.getCmHandleIds().size()); - throw new PayloadTooLargeException(errorMessage); - } - }); - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyFacade.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyFacade.java deleted file mode 100644 index a24b18446e..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyFacade.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2021 highstreet technologies GmbH - * Modifications Copyright (C) 2021-2024 Nordix Foundation - * Modifications Copyright (C) 2021 Pantheon.tech - * Modifications Copyright (C) 2021-2022 Bell Canada - * Modifications Copyright (C) 2023 TechMahindra Ltd. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.cps.ncmp.api.impl; - -import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.OPERATIONAL; - -import java.util.Collection; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.onap.cps.ncmp.api.impl.operations.DatastoreType; -import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations; -import org.onap.cps.ncmp.api.impl.operations.OperationType; -import org.onap.cps.ncmp.api.models.CmResourceAddress; -import org.onap.cps.ncmp.api.models.DataOperationRequest; -import org.onap.cps.spi.model.DataNode; -import org.springframework.stereotype.Service; - -@Slf4j -@Service -@RequiredArgsConstructor -public class NetworkCmProxyFacade { - - private final NcmpCachedResourceRequestHandler ncmpCachedResourceRequestHandler; - private final NcmpPassthroughResourceRequestHandler ncmpPassthroughResourceRequestHandler; - private final DmiDataOperations dmiDataOperations; - - /** - * Fetches resource data for a given data store using DMI (Data Management Interface). - * This method retrieves data based on the provided CmResourceAddress and additional query parameters. - * It supports asynchronous processing and handles authorization if required. - * - * @param cmResourceAddress The target data store, including the CM handle and resource identifier. - * This parameter must not be null. - * @param options Additional query parameters that may influence the data retrieval process, - * such as filters or limits. This parameter can be null. - * @param topic The topic name for triggering asynchronous responses. If specified, - * the response will be sent to this topic. This parameter can be null. - * @param includeDescendants include (all) descendants or not - * @param authorization The contents of the Authorization header. This parameter can be null - * if authorization is not required. - * @return the result object, depends on use op topic. With topic a map object with request id is returned - * otherwise the result of the request. - */ - public Object getResourceDataForCmHandle(final CmResourceAddress cmResourceAddress, - final String options, - final String topic, - final Boolean includeDescendants, - final String authorization) { - final NcmpDatastoreRequestHandler ncmpDatastoreRequestHandler - = getNcmpDatastoreRequestHandler(cmResourceAddress.datastoreName()); - - return ncmpDatastoreRequestHandler.executeRequest(cmResourceAddress, options, topic, includeDescendants, - authorization); - } - - /** - * Executes asynchronous request for group of cm handles to resource data. - * - * @param topic 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 a map with one entry of request Id for success or status and error when async feature is disabled - */ - public Object executeDataOperationForCmHandles(final String topic, - final DataOperationRequest dataOperationRequest, - final String authorization) { - return ncmpPassthroughResourceRequestHandler.executeAsynchronousRequest(topic, - dataOperationRequest, - authorization); - } - - public Collection queryResourceDataForCmHandle(final String cmHandle, - final String cpsPath, - final Boolean includeDescendants) { - return ncmpCachedResourceRequestHandler.executeRequest(cmHandle, cpsPath, includeDescendants); - } - - /** - * Write resource data for data store pass-through running using dmi for given cm-handle. - * - * @param cmHandleId cm handle identifier - * @param resourceIdentifier resource identifier - * @param operationType required operation type - * @param requestData request body to create resource - * @param dataType content type in body - * @param authorization contents of Authorization header, or null if not present - * @return {@code Object} return data - */ - public Object writeResourceDataPassThroughRunningForCmHandle(final String cmHandleId, - final String resourceIdentifier, - final OperationType operationType, - final String requestData, - final String dataType, - final String authorization) { - return dmiDataOperations.writeResourceDataPassThroughRunningFromDmi(cmHandleId, resourceIdentifier, - operationType, requestData, dataType, authorization); - } - - - private NcmpDatastoreRequestHandler getNcmpDatastoreRequestHandler(final String datastoreName) { - if (OPERATIONAL.equals(DatastoreType.fromDatastoreName(datastoreName))) { - return ncmpCachedResourceRequestHandler; - } - return ncmpPassthroughResourceRequestHandler; - } - -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyQueryServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyQueryServiceImpl.java deleted file mode 100644 index 8507fb773f..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyQueryServiceImpl.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022-2023 Nordix Foundation - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.cps.ncmp.api.impl; - -import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME; - -import java.util.Collection; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.onap.cps.api.CpsQueryService; -import org.onap.cps.ncmp.api.NetworkCmProxyQueryService; -import org.onap.cps.spi.FetchDescendantsOption; -import org.onap.cps.spi.model.DataNode; -import org.springframework.stereotype.Service; - -@Slf4j -@Service -@RequiredArgsConstructor -public class NetworkCmProxyQueryServiceImpl implements NetworkCmProxyQueryService { - - private final CpsQueryService cpsQueryService; - - @Override - public Collection queryResourceDataOperational(final String cmHandleId, - final String cpsPath, - final FetchDescendantsOption fetchDescendantsOption) { - return cpsQueryService.queryDataNodes(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId, cpsPath, - fetchDescendantsOption); - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/async/AsyncRestRequestResponseEventConsumer.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/async/AsyncRestRequestResponseEventConsumer.java deleted file mode 100644 index 993e3d63db..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/async/AsyncRestRequestResponseEventConsumer.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (c) 2023-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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.cps.ncmp.api.impl.async; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.onap.cps.events.EventsPublisher; -import org.onap.cps.ncmp.event.model.DmiAsyncRequestResponseEvent; -import org.onap.cps.ncmp.event.model.NcmpAsyncRequestResponseEvent; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.kafka.annotation.KafkaListener; -import org.springframework.stereotype.Component; - -/** - * Listener for cps-ncmp async request response events. - */ -@Component -@Slf4j -@RequiredArgsConstructor -@ConditionalOnProperty(name = "notification.enabled", havingValue = "true", matchIfMissing = true) -public class AsyncRestRequestResponseEventConsumer { - - private final EventsPublisher eventsPublisher; - private final NcmpAsyncRequestResponseEventMapper ncmpAsyncRequestResponseEventMapper; - - /** - * Consume the specified event. - * - * @param dmiAsyncRequestResponseEvent the event to be consumed and produced. - */ - @KafkaListener( - topics = "${app.ncmp.async-m2m.topic}", - filter = "includeNonCloudEventsOnly", - groupId = "ncmp-async-rest-request-event-group", - properties = {"spring.json.value.default.type=org.onap.cps.ncmp.event.model.DmiAsyncRequestResponseEvent"}) - public void consumeAndForward(final DmiAsyncRequestResponseEvent dmiAsyncRequestResponseEvent) { - log.debug("Consuming event {} ...", dmiAsyncRequestResponseEvent); - final NcmpAsyncRequestResponseEvent ncmpAsyncRequestResponseEvent = - ncmpAsyncRequestResponseEventMapper.toNcmpAsyncEvent(dmiAsyncRequestResponseEvent); - eventsPublisher.publishEvent(ncmpAsyncRequestResponseEvent.getEventTarget(), - ncmpAsyncRequestResponseEvent.getEventId(), - ncmpAsyncRequestResponseEvent); - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/async/DataOperationEventConsumer.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/async/DataOperationEventConsumer.java deleted file mode 100644 index 9bb7fae4d9..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/async/DataOperationEventConsumer.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2023-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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.cps.ncmp.api.impl.async; - -import io.cloudevents.CloudEvent; -import io.cloudevents.kafka.impl.KafkaHeaders; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.apache.kafka.clients.consumer.ConsumerRecord; -import org.onap.cps.events.EventsPublisher; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.kafka.annotation.KafkaListener; -import org.springframework.stereotype.Component; - -/** - * Listener for cps-ncmp async data operation events. - */ -@Component -@Slf4j -@RequiredArgsConstructor -@ConditionalOnProperty(name = "notification.enabled", havingValue = "true", matchIfMissing = true) -public class DataOperationEventConsumer { - - private final EventsPublisher eventsPublisher; - - /** - * Consume the DataOperation cloud event published by producer to topic 'async-m2m.topic' - * and publish the same to client specified topic. - * - * @param dataOperationEventConsumerRecord consuming event as a ConsumerRecord. - */ - @KafkaListener( - topics = "${app.ncmp.async-m2m.topic}", - filter = "includeDataOperationEventsOnly", - groupId = "ncmp-data-operation-event-group", - containerFactory = "cloudEventConcurrentKafkaListenerContainerFactory") - public void consumeAndPublish(final ConsumerRecord dataOperationEventConsumerRecord) { - log.debug("Consuming event payload {} ...", dataOperationEventConsumerRecord.value()); - final String eventTarget = KafkaHeaders.getParsedKafkaHeader( - dataOperationEventConsumerRecord.headers(), "ce_destination"); - final String correlationId = KafkaHeaders.getParsedKafkaHeader( - dataOperationEventConsumerRecord.headers(), "ce_correlationid"); - eventsPublisher.publishCloudEvent(eventTarget, correlationId, dataOperationEventConsumerRecord.value()); - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/async/NcmpAsyncRequestResponseEventMapper.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/async/NcmpAsyncRequestResponseEventMapper.java deleted file mode 100644 index 46a11b82a0..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/async/NcmpAsyncRequestResponseEventMapper.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022 Nordix Foundation - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.cps.ncmp.api.impl.async; - -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.util.UUID; -import org.mapstruct.AfterMapping; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.MappingTarget; -import org.mapstruct.Named; -import org.onap.cps.ncmp.event.model.DmiAsyncRequestResponseEvent; -import org.onap.cps.ncmp.event.model.NcmpAsyncRequestResponseEvent; - -/** - * Mapper for converting DmiAsyncRequestResponseEvent to NcmpAsyncRequestResponseEvent. - */ -@Mapper(componentModel = "spring") -public interface NcmpAsyncRequestResponseEventMapper { - - @Mapping(source = "eventId", target = "eventId", qualifiedByName = "ncmpAsyncEventId") - @Mapping(source = "eventTime", target = "eventTime", qualifiedByName = "currentTime") - @Mapping(source = "eventId", target = "forwardedEvent.eventId") - @Mapping(source = "eventCorrelationId", target = "forwardedEvent.eventCorrelationId") - @Mapping(source = "eventSchema", target = "forwardedEvent.eventSchema") - @Mapping(source = "eventSchemaVersion", target = "forwardedEvent.eventSchemaVersion") - @Mapping(source = "eventSource", target = "forwardedEvent.eventSource") - @Mapping(source = "eventTarget", target = "forwardedEvent.eventTarget") - @Mapping(source = "eventTime", target = "forwardedEvent.eventTime") - @Mapping(source = "eventType", target = "forwardedEvent.eventType") - @Mapping(source = "eventContent.responseStatus", target = "forwardedEvent.responseStatus") - @Mapping(source = "eventContent.responseCode", target = "forwardedEvent.responseCode") - @Mapping(source = "eventContent.responseDataSchema", target = "forwardedEvent.responseDataSchema") - NcmpAsyncRequestResponseEvent toNcmpAsyncEvent(DmiAsyncRequestResponseEvent dmiAsyncRequestResponseEvent); - - @Named("ncmpAsyncEventId") - static String getNcmpAsyncEventId(String eventId) { - return UUID.randomUUID().toString(); - } - - @Named("currentTime") - static String getFormattedCurrentTime(String eventTime) { - return ZonedDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ")); - } - - @AfterMapping - default void mapAdditionalProperties(DmiAsyncRequestResponseEvent dmiAsyncRequestResponseEvent, - @MappingTarget NcmpAsyncRequestResponseEvent ncmpAsyncRequestResponseEvent) { - ncmpAsyncRequestResponseEvent.getForwardedEvent().setAdditionalProperty("response-data", - dmiAsyncRequestResponseEvent.getEventContent().getResponseData().getAdditionalProperties()); - } - -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/async/RecordFilterStrategies.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/async/RecordFilterStrategies.java deleted file mode 100644 index 0404790408..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/async/RecordFilterStrategies.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2023 Nordix Foundation - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.cps.ncmp.api.impl.async; - -import io.cloudevents.CloudEvent; -import io.cloudevents.kafka.impl.KafkaHeaders; -import java.io.Serializable; -import lombok.extern.slf4j.Slf4j; -import org.apache.kafka.common.header.Headers; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.kafka.listener.adapter.RecordFilterStrategy; - -/** - * Record filter strategies, which helps to filter the consumer records based on some conditions. - * - */ -@Configuration -@Slf4j -public class RecordFilterStrategies { - - private static final boolean EXCLUDE_EVENT = true; - - /** - * Include only DataOperation events based on the cloud event type header, It - * returns boolean, true means exclude the consumer record and false - * means include the consumer record. - * @return boolean value. - */ - @Bean - public RecordFilterStrategy includeDataOperationEventsOnly() { - return consumerRecord -> - isNotCloudEventOfType(consumerRecord.headers(), "DataOperationEvent"); - } - - /** - * Includes the consumer records based on the cloud event type header, It returns boolean, - * true means exclude the consumer record and false means include the consumer record. - * It includes only the legacy events i.e. non-cloud events - * @return boolean value. - */ - @Bean - public RecordFilterStrategy includeNonCloudEventsOnly() { - return consumerRecord -> isCloudEvent(consumerRecord.headers()); - } - - private boolean isCloudEvent(final Headers headers) { - return headers.lastHeader("ce_type") != null; - } - - private boolean isNotCloudEventOfType(final Headers headers, final String requiredEventType) { - final String eventTypeHeaderValue = KafkaHeaders.getParsedKafkaHeader(headers, "ce_type"); - if (eventTypeHeaderValue == null) { - log.trace("No ce_type header found, possibly a legacy event (ignored)"); - return EXCLUDE_EVENT; - } - return !(eventTypeHeaderValue.contains(requiredEventType)); - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/client/DmiRestClient.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/client/DmiRestClient.java index d4c5d16a4c..39219bd371 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/client/DmiRestClient.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/client/DmiRestClient.java @@ -34,11 +34,11 @@ import java.net.URISyntaxException; import java.util.Locale; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.onap.cps.ncmp.api.data.models.OperationType; import org.onap.cps.ncmp.api.impl.config.DmiProperties; import org.onap.cps.ncmp.api.impl.exception.DmiClientRequestException; import org.onap.cps.ncmp.api.impl.exception.InvalidDmiResourceUrlException; -import org.onap.cps.ncmp.api.impl.operations.OperationType; -import org.onap.cps.ncmp.api.impl.operations.RequiredDmiService; +import org.onap.cps.ncmp.impl.models.RequiredDmiService; import org.onap.cps.utils.JsonObjectMapper; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.http.HttpHeaders; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmNotificationSubscriptionDelta.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmNotificationSubscriptionDelta.java index 4e2062fed6..ff322ee3cc 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmNotificationSubscriptionDelta.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmNotificationSubscriptionDelta.java @@ -25,9 +25,9 @@ import java.util.HashSet; import java.util.List; import java.util.Set; import lombok.RequiredArgsConstructor; +import org.onap.cps.ncmp.api.data.models.DatastoreType; import org.onap.cps.ncmp.api.impl.events.cmsubscription.model.DmiCmNotificationSubscriptionPredicate; import org.onap.cps.ncmp.api.impl.events.cmsubscription.service.CmNotificationSubscriptionPersistenceService; -import org.onap.cps.ncmp.api.impl.operations.DatastoreType; import org.springframework.stereotype.Component; @Component diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/DmiCmNotificationSubscriptionCacheHandler.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/DmiCmNotificationSubscriptionCacheHandler.java index 21c26228bc..840ab0fb92 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/DmiCmNotificationSubscriptionCacheHandler.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/DmiCmNotificationSubscriptionCacheHandler.java @@ -31,11 +31,11 @@ import java.util.Map; import java.util.Set; import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; +import org.onap.cps.ncmp.api.data.models.DatastoreType; import org.onap.cps.ncmp.api.impl.events.cmsubscription.model.CmNotificationSubscriptionStatus; import org.onap.cps.ncmp.api.impl.events.cmsubscription.model.DmiCmNotificationSubscriptionDetails; import org.onap.cps.ncmp.api.impl.events.cmsubscription.model.DmiCmNotificationSubscriptionPredicate; import org.onap.cps.ncmp.api.impl.events.cmsubscription.service.CmNotificationSubscriptionPersistenceService; -import org.onap.cps.ncmp.api.impl.operations.DatastoreType; import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.client_to_ncmp.Predicate; import org.onap.cps.ncmp.impl.inventory.InventoryPersistence; import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/model/DmiCmNotificationSubscriptionPredicate.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/model/DmiCmNotificationSubscriptionPredicate.java index 9c4c3f64e3..40c0188fa0 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/model/DmiCmNotificationSubscriptionPredicate.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/model/DmiCmNotificationSubscriptionPredicate.java @@ -24,7 +24,7 @@ import java.util.Set; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.Setter; -import org.onap.cps.ncmp.api.impl.operations.DatastoreType; +import org.onap.cps.ncmp.api.data.models.DatastoreType; @Getter @Setter diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/service/CmNotificationSubscriptionPersistenceService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/service/CmNotificationSubscriptionPersistenceService.java index 3bb40c3b7e..d87624c23c 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/service/CmNotificationSubscriptionPersistenceService.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/service/CmNotificationSubscriptionPersistenceService.java @@ -21,7 +21,7 @@ package org.onap.cps.ncmp.api.impl.events.cmsubscription.service; import java.util.Collection; -import org.onap.cps.ncmp.api.impl.operations.DatastoreType; +import org.onap.cps.ncmp.api.data.models.DatastoreType; public interface CmNotificationSubscriptionPersistenceService { diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/service/CmNotificationSubscriptionPersistenceServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/service/CmNotificationSubscriptionPersistenceServiceImpl.java index a9b1e26f54..e2480c5e56 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/service/CmNotificationSubscriptionPersistenceServiceImpl.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/service/CmNotificationSubscriptionPersistenceServiceImpl.java @@ -34,7 +34,7 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.onap.cps.api.CpsDataService; import org.onap.cps.api.CpsQueryService; -import org.onap.cps.ncmp.api.impl.operations.DatastoreType; +import org.onap.cps.ncmp.api.data.models.DatastoreType; import org.onap.cps.spi.model.DataNode; import org.onap.cps.utils.ContentType; import org.onap.cps.utils.JsonObjectMapper; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/InvalidDatastoreException.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/InvalidDatastoreException.java deleted file mode 100644 index 6cfa159b20..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/InvalidDatastoreException.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2023 Nordix Foundation - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.cps.ncmp.api.impl.exception; - -public class InvalidDatastoreException extends RuntimeException { - /** - * Instantiates a new Invalid datastore exception. - * - * @param message the message - */ - public InvalidDatastoreException(final String message) { - super(message); - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/InvalidOperationException.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/InvalidOperationException.java deleted file mode 100644 index 17069098cb..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/InvalidOperationException.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2023 Nordix Foundation - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.cps.ncmp.api.impl.exception; - -public class InvalidOperationException extends RuntimeException { - /** - * Instantiates a new invalid operation exception. - * - * @param message the message - */ - public InvalidOperationException(final String message) { - super(message); - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DatastoreType.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DatastoreType.java deleted file mode 100644 index 6520c05c08..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DatastoreType.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2023 Nordix Foundation - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.cps.ncmp.api.impl.operations; - - -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import lombok.Getter; -import org.onap.cps.ncmp.api.impl.exception.InvalidDatastoreException; - -@Getter -public enum DatastoreType { - - OPERATIONAL("ncmp-datastore:operational"), - PASSTHROUGH_RUNNING("ncmp-datastore:passthrough-running"), - PASSTHROUGH_OPERATIONAL("ncmp-datastore:passthrough-operational"); - - DatastoreType(final String datastoreName) { - this.datastoreName = datastoreName; - } - - private final String datastoreName; - private static final Map datastoreNameToDatastoreType = new HashMap<>(); - - static { - Arrays.stream(DatastoreType.values()).forEach( - type -> datastoreNameToDatastoreType.put(type.getDatastoreName(), type)); - } - - /** - * From datastore name get datastore type. - * - * @param datastoreName the datastore name - * @return the datastore type - */ - public static DatastoreType fromDatastoreName(final String datastoreName) { - - final DatastoreType datastoreType = datastoreNameToDatastoreType.get(datastoreName); - - if (null == datastoreType) { - throw new InvalidDatastoreException(datastoreName + " is an invalid datastore name"); - } - - return datastoreType; - } - -} - diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperation.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperation.java deleted file mode 100644 index 7baac34b1f..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperation.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2023 Nordix Foundation - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.cps.ncmp.api.impl.operations; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonPropertyOrder; -import java.util.ArrayList; -import java.util.List; -import lombok.Builder; -import lombok.Getter; -import org.onap.cps.ncmp.api.models.DataOperationDefinition; - -@JsonInclude(JsonInclude.Include.NON_NULL) -@Getter -@Builder -@JsonPropertyOrder({"operation", "operationId", "datastore", "options", "resourceIdentifier", "cmHandles"}) -public class DmiDataOperation { - - private OperationType operation; - private String operationId; - private String datastore; - private String options; - private String resourceIdentifier; - - private final List cmHandles = new ArrayList<>(); - - /** - * Create and initialise a (outgoing) DMI data operation. - * - * @param dataOperationDefinition definition of incoming of dataOperation request - * @return mapped dmi operation details - */ - public static DmiDataOperation buildDmiDataOperationRequestBodyWithoutCmHandles( - final DataOperationDefinition dataOperationDefinition) { - - return DmiDataOperation.builder() - .operation(OperationType.fromOperationName(dataOperationDefinition.getOperation())) - .operationId(dataOperationDefinition.getOperationId()) - .datastore(DatastoreType.fromDatastoreName(dataOperationDefinition.getDatastore()).getDatastoreName()) - .options(dataOperationDefinition.getOptions()) - .resourceIdentifier(dataOperationDefinition.getResourceIdentifier()) - .build(); - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperationRequest.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperationRequest.java deleted file mode 100644 index 8ee1d905bf..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperationRequest.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2023 Nordix Foundation - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.cps.ncmp.api.impl.operations; - -import com.fasterxml.jackson.annotation.JsonInclude; -import java.util.List; -import lombok.Builder; -import lombok.Getter; - -@JsonInclude(JsonInclude.Include.NON_NULL) -@Getter -@Builder -public class DmiDataOperationRequest { - - private List operations; - -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java deleted file mode 100644 index 32fc8a5dbb..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java +++ /dev/null @@ -1,297 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2021-2024 Nordix Foundation - * Modifications Copyright (C) 2022 Bell Canada - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.cps.ncmp.api.impl.operations; - -import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_OPERATIONAL; -import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_RUNNING; -import static org.onap.cps.ncmp.api.impl.operations.OperationType.READ; -import static org.onap.cps.ncmp.api.impl.operations.RequiredDmiService.DATA; - -import io.micrometer.core.annotation.Timed; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; -import lombok.RequiredArgsConstructor; -import org.onap.cps.ncmp.api.NcmpResponseStatus; -import org.onap.cps.ncmp.api.impl.client.DmiRestClient; -import org.onap.cps.ncmp.api.impl.config.DmiProperties; -import org.onap.cps.ncmp.api.impl.exception.DmiClientRequestException; -import org.onap.cps.ncmp.api.impl.utils.DmiServiceUrlBuilder; -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.impl.inventory.InventoryPersistence; -import org.onap.cps.ncmp.impl.inventory.models.CmHandleState; -import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; -import org.onap.cps.spi.exceptions.CpsException; -import org.onap.cps.utils.JsonObjectMapper; -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Service; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; -import org.springframework.web.util.UriComponentsBuilder; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -/** - * Operations class for DMI data. - */ -@RequiredArgsConstructor -@Service -public class DmiDataOperations { - - private final InventoryPersistence inventoryPersistence; - private final JsonObjectMapper jsonObjectMapper; - private final DmiProperties dmiProperties; - private final DmiRestClient dmiRestClient; - - /** - * This method fetches the resource data from the operational data store for a given CM handle - * identifier on the specified resource using the DMI client. - * - * @param cmResourceAddress Target datastore, CM handle, and resource identifier. - * @param options Options query string. - * @param topic Topic name for triggering asynchronous responses. - * @param requestId Request ID for asynchronous responses. - * @param authorization Contents of the Authorization header, or null if not present. - * @return {@code Mono>} A reactive type representing the response entity. - */ - @Timed(value = "cps.ncmp.dmi.get", - description = "Time taken to fetch the resource data from operational data store for given cm handle " - + "identifier on given resource using dmi client") - public Mono> getResourceDataFromDmi(final CmResourceAddress cmResourceAddress, - final String options, - final String topic, - final String requestId, - final String authorization) { - final YangModelCmHandle yangModelCmHandle = getYangModelCmHandle(cmResourceAddress.cmHandleId()); - final CmHandleState cmHandleState = yangModelCmHandle.getCompositeState().getCmHandleState(); - validateIfCmHandleStateReady(yangModelCmHandle, cmHandleState); - final String jsonRequestBody = getDmiRequestBody(READ, requestId, null, null, yangModelCmHandle); - final String dmiUrl = getDmiResourceDataUrl(cmResourceAddress.datastoreName(), yangModelCmHandle, - cmResourceAddress.resourceIdentifier(), options, topic); - return dmiRestClient.asynchronousPostOperationWithJsonData(DATA, dmiUrl, jsonRequestBody, READ, authorization); - } - - /** - * This method fetches all the resource data from operational data store for given cm handle - * identifier using dmi client. - * Note: this method is only used for DataSync - * - * @param cmHandleId network resource identifier - * @param requestId requestId for async responses - * @return {@code ResponseEntity} response entity - */ - public ResponseEntity getAllResourceDataFromDmi(final String cmHandleId, final String requestId) { - final YangModelCmHandle yangModelCmHandle = getYangModelCmHandle(cmHandleId); - final CmHandleState cmHandleState = yangModelCmHandle.getCompositeState().getCmHandleState(); - validateIfCmHandleStateReady(yangModelCmHandle, cmHandleState); - - final String jsonRequestBody = getDmiRequestBody(READ, requestId, null, null, yangModelCmHandle); - final String dmiUrl = - getDmiResourceDataUrl(PASSTHROUGH_OPERATIONAL.getDatastoreName(), yangModelCmHandle, "/", null, null); - return dmiRestClient.synchronousPostOperationWithJsonData(DATA, dmiUrl, jsonRequestBody, READ, null); - } - - /** - * This method requests the resource data by data store for given list of cm handles using dmi client. - * The data wil be returned as message on the topic specified. - * - * @param topicParamInQuery topic name for (triggering) async responses - * @param dataOperationRequest data operation request to execute operations - * @param requestId requestId for as a response - * @param authorization contents of Authorization header, or null if not present - */ - public void requestResourceDataFromDmi(final String topicParamInQuery, - final DataOperationRequest dataOperationRequest, - final String requestId, - final String authorization) { - - final Set cmHandlesIds - = getDistinctCmHandleIdsFromDataOperationRequest(dataOperationRequest); - - final Collection yangModelCmHandles - = inventoryPersistence.getYangModelCmHandles(cmHandlesIds); - - final Map> operationsOutPerDmiServiceName - = ResourceDataOperationRequestUtils.processPerDefinitionInDataOperationsRequest(topicParamInQuery, - requestId, dataOperationRequest, yangModelCmHandles); - - buildDataOperationRequestUrlAndSendToDmiService(requestId, topicParamInQuery, operationsOutPerDmiServiceName, - authorization); - } - - /** - * This method creates the resource data from pass-through running data store for given cm handle - * identifier on given resource using dmi client. - * - * @param cmHandleId network resource identifier - * @param resourceId resource identifier - * @param operationType operation enum - * @param requestData the request data - * @param dataType data type - * @param authorization contents of Authorization header, or null if not present - * @return {@code ResponseEntity} response entity - */ - public ResponseEntity writeResourceDataPassThroughRunningFromDmi(final String cmHandleId, - final String resourceId, - final OperationType operationType, - final String requestData, - final String dataType, - final String authorization) { - final YangModelCmHandle yangModelCmHandle = getYangModelCmHandle(cmHandleId); - final CmHandleState cmHandleState = yangModelCmHandle.getCompositeState().getCmHandleState(); - validateIfCmHandleStateReady(yangModelCmHandle, cmHandleState); - - final String jsonRequestBody = getDmiRequestBody(operationType, null, requestData, dataType, - yangModelCmHandle); - final String dmiUrl = getDmiResourceDataUrl(PASSTHROUGH_RUNNING.getDatastoreName(), - yangModelCmHandle, resourceId, null, null); - return dmiRestClient.synchronousPostOperationWithJsonData(DATA, dmiUrl, jsonRequestBody, - operationType, authorization); - } - - private YangModelCmHandle getYangModelCmHandle(final String cmHandleId) { - return inventoryPersistence.getYangModelCmHandle(cmHandleId); - } - - private String getDmiRequestBody(final OperationType operationType, - final String requestId, - final String requestData, - final String dataType, - final YangModelCmHandle yangModelCmHandle) { - final DmiRequestBody dmiRequestBody = DmiRequestBody.builder() - .operationType(operationType) - .requestId(requestId) - .data(requestData) - .dataType(dataType) - .moduleSetTag(yangModelCmHandle.getModuleSetTag()) - .build(); - dmiRequestBody.asDmiProperties(yangModelCmHandle.getDmiProperties()); - return jsonObjectMapper.asJsonString(dmiRequestBody); - } - - private String getDmiResourceDataUrl(final String datastoreName, - final YangModelCmHandle yangModelCmHandle, - final String resourceIdentifier, - final String optionsParamInQuery, - final String topicParamInQuery) { - final String dmiServiceName = yangModelCmHandle.resolveDmiServiceName(RequiredDmiService.DATA); - return DmiServiceUrlBuilder.newInstance() - .pathSegment("ch") - .variablePathSegment("cmHandleId", yangModelCmHandle.getId()) - .pathSegment("data") - .pathSegment("ds") - .variablePathSegment("datastore", datastoreName) - .queryParameter("resourceIdentifier", resourceIdentifier) - .queryParameter("options", optionsParamInQuery) - .queryParameter("topic", topicParamInQuery) - .build(dmiServiceName, dmiProperties.getDmiBasePath()); - } - - private void validateIfCmHandleStateReady(final YangModelCmHandle yangModelCmHandle, - final CmHandleState cmHandleState) { - if (cmHandleState != CmHandleState.READY) { - throw new CpsException("State mismatch exception.", "Cm-Handle not in READY state. " - + "cm handle state is " - + yangModelCmHandle.getCompositeState().getCmHandleState()); - } - } - - private static Set getDistinctCmHandleIdsFromDataOperationRequest(final DataOperationRequest - dataOperationRequest) { - return dataOperationRequest.getDataOperationDefinitions().stream() - .flatMap(dataOperationDefinition -> - dataOperationDefinition.getCmHandleIds().stream()).collect(Collectors.toSet()); - } - - private void buildDataOperationRequestUrlAndSendToDmiService(final String requestId, - final String topicParamInQuery, - final Map> - groupsOutPerDmiServiceName, - final String authorization) { - - Flux.fromIterable(groupsOutPerDmiServiceName.entrySet()) - .flatMap(dmiDataOperationsByDmiServiceName -> { - final String dmiServiceName = dmiDataOperationsByDmiServiceName.getKey(); - final String dmiUrl = buildDmiServiceUrl(dmiServiceName, requestId, topicParamInQuery); - final List dmiDataOperationRequestBodies - = dmiDataOperationsByDmiServiceName.getValue(); - return sendDataOperationRequestToDmiService(dmiUrl, dmiDataOperationRequestBodies, authorization); - }) - .subscribe(); - } - - private String buildDmiServiceUrl(final String dmiServiceName, final String requestId, - final String topicParamInQuery) { - return DmiServiceUrlBuilder.newInstance() - .pathSegment("data") - .queryParameter("requestId", requestId) - .queryParameter("topic", topicParamInQuery) - .build(dmiServiceName, dmiProperties.getDmiBasePath()); - } - - private Mono sendDataOperationRequestToDmiService(final String dmiUrl, - final List dmiDataOperationRequestBodies, - final String authorization) { - final String dmiDataOperationRequestAsJsonString - = createDmiDataOperationRequestAsJsonString(dmiDataOperationRequestBodies); - return dmiRestClient.asynchronousPostOperationWithJsonData(DATA, dmiUrl, dmiDataOperationRequestAsJsonString, - READ, authorization) - .then() - .onErrorResume(DmiClientRequestException.class, dmiClientRequestException -> { - handleTaskCompletionException(dmiClientRequestException, dmiUrl, dmiDataOperationRequestBodies); - return Mono.empty(); - }); - } - - private String createDmiDataOperationRequestAsJsonString( - final List dmiDataOperationRequestBodies) { - final DmiDataOperationRequest dmiDataOperationRequest = DmiDataOperationRequest.builder() - .operations(dmiDataOperationRequestBodies) - .build(); - return jsonObjectMapper.asJsonString(dmiDataOperationRequest); - } - - private void handleTaskCompletionException(final DmiClientRequestException dmiClientRequestException, - final String dataOperationResourceUrl, - final List dmiDataOperationRequestBodies) { - final MultiValueMap dataOperationResourceUrlParameters = - UriComponentsBuilder.fromUriString(dataOperationResourceUrl).build().getQueryParams(); - final String topicName = dataOperationResourceUrlParameters.get("topic").get(0); - final String requestId = dataOperationResourceUrlParameters.get("requestId").get(0); - - final MultiValueMap>> - cmHandleIdsPerResponseCodesPerOperation = new LinkedMultiValueMap<>(); - - dmiDataOperationRequestBodies.forEach(dmiDataOperationRequestBody -> { - final List cmHandleIds = dmiDataOperationRequestBody.getCmHandles().stream() - .map(DmiOperationCmHandle::getId).toList(); - cmHandleIdsPerResponseCodesPerOperation.add(dmiDataOperationRequestBody, - Map.of(dmiClientRequestException.getNcmpResponseStatus(), cmHandleIds)); - }); - ResourceDataOperationRequestUtils.publishErrorMessageToClientTopic(topicName, requestId, - cmHandleIdsPerResponseCodesPerOperation); - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiModelOperations.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiModelOperations.java deleted file mode 100644 index f1fdbea7f6..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiModelOperations.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2021-2024 Nordix Foundation - * Modifications Copyright (C) 2022 Bell Canada - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.cps.ncmp.api.impl.operations; - -import static org.onap.cps.ncmp.api.impl.operations.OperationType.READ; -import static org.onap.cps.ncmp.api.impl.operations.RequiredDmiService.MODEL; - -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import lombok.RequiredArgsConstructor; -import org.onap.cps.ncmp.api.impl.client.DmiRestClient; -import org.onap.cps.ncmp.api.impl.config.DmiProperties; -import org.onap.cps.ncmp.api.impl.utils.DmiServiceUrlBuilder; -import org.onap.cps.ncmp.api.inventory.models.YangResource; -import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; -import org.onap.cps.spi.model.ModuleReference; -import org.onap.cps.utils.JsonObjectMapper; -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Service; - -/** - * Operations class for DMI Model. - */ -@RequiredArgsConstructor -@Service -public class DmiModelOperations { - - private final JsonObjectMapper jsonObjectMapper; - private final DmiProperties dmiProperties; - private final DmiRestClient dmiRestClient; - - /** - * Retrieves module references. - * - * @param yangModelCmHandle the yang model cm handle - * @return module references - */ - public List getModuleReferences(final YangModelCmHandle yangModelCmHandle) { - final DmiRequestBody dmiRequestBody = DmiRequestBody.builder() - .moduleSetTag(yangModelCmHandle.getModuleSetTag()).build(); - dmiRequestBody.asDmiProperties(yangModelCmHandle.getDmiProperties()); - final ResponseEntity dmiFetchModulesResponseEntity = getResourceFromDmiWithJsonData( - yangModelCmHandle.resolveDmiServiceName(MODEL), - jsonObjectMapper.asJsonString(dmiRequestBody), yangModelCmHandle.getId(), "modules"); - return toModuleReferences((Map) dmiFetchModulesResponseEntity.getBody()); - } - - /** - * Retrieve yang resources from dmi for any modules that CPS-NCMP hasn't cached before. - * - * @param yangModelCmHandle the yangModelCmHandle - * @param newModuleReferences the unknown module references - * @return yang resources as map of module name to yang(re)source - */ - public Map getNewYangResourcesFromDmi(final YangModelCmHandle yangModelCmHandle, - final Collection newModuleReferences) { - if (newModuleReferences.isEmpty()) { - return Collections.emptyMap(); - } - final String jsonWithDataAndDmiProperties = getRequestBodyToFetchYangResources(newModuleReferences, - yangModelCmHandle.getDmiProperties(), yangModelCmHandle.getModuleSetTag()); - final ResponseEntity responseEntity = getResourceFromDmiWithJsonData( - yangModelCmHandle.resolveDmiServiceName(MODEL), - jsonWithDataAndDmiProperties, - yangModelCmHandle.getId(), - "moduleResources"); - return asModuleNameToYangResourceMap(responseEntity); - } - - /** - * Get resources from DMI for modules. - * - * @param dmiServiceName dmi service name - * @param jsonRequestBody module names and revisions as JSON - * @param cmHandle cmHandle - * @param resourceName name of the resource(s) - * @return {@code ResponseEntity} response entity - */ - private ResponseEntity getResourceFromDmiWithJsonData(final String dmiServiceName, - final String jsonRequestBody, - final String cmHandle, - final String resourceName) { - final String dmiUrl = DmiServiceUrlBuilder.newInstance() - .pathSegment("ch") - .variablePathSegment("cmHandleId", cmHandle) - .variablePathSegment("resourceName", resourceName) - .build(dmiServiceName, dmiProperties.getDmiBasePath()); - return dmiRestClient.synchronousPostOperationWithJsonData(MODEL, dmiUrl, jsonRequestBody, READ, null); - } - - private static String getRequestBodyToFetchYangResources(final Collection newModuleReferences, - final List dmiProperties, - final String moduleSetTag) { - final JsonArray moduleReferencesAsJson = getModuleReferencesAsJson(newModuleReferences); - final JsonObject data = new JsonObject(); - data.add("modules", moduleReferencesAsJson); - final JsonObject jsonRequestObject = new JsonObject(); - if (!moduleSetTag.isEmpty()) { - final JsonElement moduleSetTagAsJson = JsonParser.parseString(moduleSetTag); - jsonRequestObject.add("moduleSetTag", moduleSetTagAsJson); - } - jsonRequestObject.add("data", data); - jsonRequestObject.add("cmHandleProperties", toJsonObject(dmiProperties)); - return jsonRequestObject.toString(); - } - - private static JsonArray getModuleReferencesAsJson(final Collection unknownModuleReferences) { - final JsonArray moduleReferences = new JsonArray(); - - for (final ModuleReference moduleReference : unknownModuleReferences) { - final JsonObject moduleReferenceAsJson = new JsonObject(); - moduleReferenceAsJson.addProperty("name", moduleReference.getModuleName()); - moduleReferenceAsJson.addProperty("revision", moduleReference.getRevision()); - moduleReferences.add(moduleReferenceAsJson); - } - return moduleReferences; - } - - private static JsonObject toJsonObject(final List - dmiProperties) { - final JsonObject asJsonObject = new JsonObject(); - for (final YangModelCmHandle.Property additionalProperty : dmiProperties) { - asJsonObject.addProperty(additionalProperty.getName(), additionalProperty.getValue()); - } - return asJsonObject; - } - - private List toModuleReferences(final Map dmiFetchModulesResponseAsMap) { - final List moduleReferences = new ArrayList<>(); - - if (dmiFetchModulesResponseAsMap != null) { - final List moduleReferencesAsList = (List) dmiFetchModulesResponseAsMap.get("schemas"); - if (moduleReferencesAsList != null) { - moduleReferencesAsList.forEach(moduleReferenceAsMap -> { - final ModuleReference moduleReference = - jsonObjectMapper.convertToValueType(moduleReferenceAsMap, ModuleReference.class); - moduleReferences.add(moduleReference); - }); - } - } - return moduleReferences; - } - - private Map asModuleNameToYangResourceMap(final ResponseEntity responseEntity) { - final Map yangResourcesModuleNameToContentMap = new HashMap<>(); - final List> yangResourcesAsList = (List) responseEntity.getBody(); - - if (yangResourcesAsList != null) { - yangResourcesAsList.forEach(yangResourceAsMap -> { - final YangResource yangResource = - jsonObjectMapper.convertToValueType(yangResourceAsMap, YangResource.class); - yangResourcesModuleNameToContentMap.put(yangResource.getModuleName(), - yangResource.getYangSource()); - }); - } - return yangResourcesModuleNameToContentMap; - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiOperationCmHandle.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiOperationCmHandle.java deleted file mode 100644 index 1bf2b77dcc..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiOperationCmHandle.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2023 Nordix Foundation - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.cps.ncmp.api.impl.operations; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.Map; -import lombok.Builder; -import lombok.Getter; - -@JsonInclude(JsonInclude.Include.NON_NULL) -@Getter -@Builder -public class DmiOperationCmHandle { - private String id; - - @JsonProperty("cmHandleProperties") - private Map dmiProperties; - private String moduleSetTag; - - /** - * Builds Dmi Operation Cm Handle object with all its associated properties. - */ - public static DmiOperationCmHandle buildDmiOperationCmHandle(final String cmHandleId, - final Map dmiProperties, - final String moduleSetTag) { - return DmiOperationCmHandle.builder().id(cmHandleId) - .dmiProperties(dmiProperties).moduleSetTag(moduleSetTag) - .build(); - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiRequestBody.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiRequestBody.java deleted file mode 100644 index f10b4f920f..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiRequestBody.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2021-2023 Nordix Foundation - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.cps.ncmp.api.impl.operations; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonPropertyOrder; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import lombok.Builder; -import lombok.Getter; -import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; - -@JsonInclude(JsonInclude.Include.NON_NULL) -@Getter -@Builder -@JsonPropertyOrder({"operation", "dataType", "data", "cmHandleProperties", "requestId", "moduleSetTag"}) -public class DmiRequestBody { - - @JsonProperty("operation") - private OperationType operationType; - private String dataType; - private String data; - @JsonProperty("cmHandleProperties") - private Map dmiProperties; - private String requestId; - private String moduleSetTag; - - /** - * Set DMI Properties by converting a list of YangModelCmHandle.Property objects. - * - * @param yangModelCmHandleProperties list of cm handle dmi properties - */ - public void asDmiProperties( - final List yangModelCmHandleProperties) { - dmiProperties = new LinkedHashMap<>(); - for (final YangModelCmHandle.Property dmiProperty : yangModelCmHandleProperties) { - dmiProperties.put(dmiProperty.getName(), dmiProperty.getValue()); - } - } - -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/OperationType.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/OperationType.java deleted file mode 100644 index e863228ed5..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/OperationType.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2023 Nordix Foundation - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.cps.ncmp.api.impl.operations; - -import com.fasterxml.jackson.annotation.JsonValue; -import java.util.Locale; -import lombok.Getter; -import org.onap.cps.ncmp.api.impl.exception.InvalidOperationException; - -@Getter -public enum OperationType { - - READ("read"), - CREATE("create"), - UPDATE("update"), - PATCH("patch"), - DELETE("delete"); - - private final String operationName; - - OperationType(final String operationName) { - this.operationName = operationName; - } - - @Override - @JsonValue - public String toString() { - return String.valueOf(operationName); - } - - /** - * From operation name get operation enum type. - * - * @param operationName the operation name - * @return the operation enum type - */ - public static OperationType fromOperationName(final String operationName) { - try { - return OperationType.valueOf(operationName.toUpperCase(Locale.ENGLISH)); - } catch (final IllegalArgumentException e) { - throw new InvalidOperationException(operationName + " is an invalid operation name"); - } - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/RequiredDmiService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/RequiredDmiService.java deleted file mode 100644 index 7e39766f3f..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/RequiredDmiService.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2021 Nordix Foundation - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.cps.ncmp.api.impl.operations; - -/** - * Enmm to determine if the required service is for a data or model operation. - */ -public enum RequiredDmiService { - DATA, MODEL -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/AlternateIdChecker.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/AlternateIdChecker.java deleted file mode 100644 index 7ddde643aa..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/AlternateIdChecker.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * ============LICENSE_START======================================================== - * Copyright (c) 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an 'AS IS' BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.cps.ncmp.api.impl.utils; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle; -import org.onap.cps.ncmp.impl.inventory.InventoryPersistence; -import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; -import org.onap.cps.spi.exceptions.DataNodeNotFoundException; -import org.springframework.stereotype.Service; - -@Service -@Slf4j -@RequiredArgsConstructor -public class AlternateIdChecker { - - public enum Operation { - CREATE, UPDATE - } - - private final InventoryPersistence inventoryPersistence; - - private static final String NO_CURRENT_ALTERNATE_ID = ""; - - /** - * Check if the alternate can be applied to the given cm handle (id). - * Conditions: - * - proposed alternate is blank (it wil be ignored) - * - proposed alternate is same as current (no change) - * - proposed alternate is not in use for a different cm handle (in the DB) - * - * @param cmHandleId cm handle id - * @param proposedAlternateId proposed alternate id - * @return true if the new alternate id not in use or equal to current alternate id, false otherwise - */ - public boolean canApplyAlternateId(final String cmHandleId, final String proposedAlternateId) { - String currentAlternateId = ""; - try { - final YangModelCmHandle yangModelCmHandle = inventoryPersistence.getYangModelCmHandle(cmHandleId); - currentAlternateId = yangModelCmHandle.getAlternateId(); - } catch (final DataNodeNotFoundException dataNodeNotFoundException) { - // work with blank current alternate id - } - return this.canApplyAlternateId(cmHandleId, currentAlternateId, proposedAlternateId); - } - - /** - * Check if the alternate can be applied to the given cm handle. - * Conditions: - * - proposed alternate is blank (it wil be ignored) - * - proposed alternate is same as current (no change) - * - proposed alternate is not in use for a different cm handle (in the DB) - * - * @param cmHandleId cm handle id - * @param currentAlternateId current alternate id - * @param proposedAlternateId new alternate id - * @return true if the new alternate id not in use or equal to current alternate id, false otherwise - */ - public boolean canApplyAlternateId(final String cmHandleId, - final String currentAlternateId, - final String proposedAlternateId) { - if (StringUtils.isBlank(currentAlternateId)) { - if (alternateIdAlreadyInDb(proposedAlternateId)) { - log.warn("Alternate id update ignored, cannot update cm handle {}, alternate id is already " - + "assigned to a different cm handle", cmHandleId); - return false; - } - return true; - } - if (currentAlternateId.equals(proposedAlternateId)) { - return true; - } - log.warn("Alternate id update ignored, cannot update cm handle {}, already has an alternate id of {}", - cmHandleId, currentAlternateId); - return false; - } - - /** - * Check all alternate ids of a batch of cm handles. - * Includes cross-checks in the batch itself for duplicates. Only the first entry encountered wil be accepted. - * - * @param newNcmpServiceCmHandles the proposed new cm handles - * @param operation type of operation being executed - * @return collection of cm handles ids which are acceptable - */ - public Collection getIdsOfCmHandlesWithRejectedAlternateId( - final Collection newNcmpServiceCmHandles, - final Operation operation) { - final Set acceptedAlternateIds = new HashSet<>(newNcmpServiceCmHandles.size()); - final Collection rejectedCmHandleIds = new ArrayList<>(); - for (final NcmpServiceCmHandle ncmpServiceCmHandle : newNcmpServiceCmHandles) { - final String cmHandleId = ncmpServiceCmHandle.getCmHandleId(); - final String proposedAlternateId = ncmpServiceCmHandle.getAlternateId(); - if (isProposedAlternateIdAcceptable(proposedAlternateId, operation, acceptedAlternateIds, cmHandleId)) { - acceptedAlternateIds.add(proposedAlternateId); - } else { - rejectedCmHandleIds.add(cmHandleId); - } - } - return rejectedCmHandleIds; - } - - private boolean isProposedAlternateIdAcceptable(final String proposedAlternateId, final Operation operation, - final Set acceptedAlternateIds, final String cmHandleId) { - if (StringUtils.isEmpty(proposedAlternateId)) { - return true; - } - if (acceptedAlternateIds.contains(proposedAlternateId)) { - log.warn("Alternate id update ignored, cannot update cm handle {}, alternate id is already " - + "assigned to a different cm handle (in this batch)", cmHandleId); - return false; - } - if (Operation.CREATE.equals(operation)) { - return canApplyAlternateId(cmHandleId, NO_CURRENT_ALTERNATE_ID, proposedAlternateId); - } - return canApplyAlternateId(cmHandleId, proposedAlternateId); - } - - private boolean alternateIdAlreadyInDb(final String alternateId) { - try { - inventoryPersistence.getCmHandleDataNodeByAlternateId(alternateId); - } catch (final DataNodeNotFoundException dataNodeNotFoundException) { - return false; - } - return true; - } - -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/DmiServiceNameOrganizer.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/DmiServiceNameOrganizer.java index 533e15b918..67880648bc 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/DmiServiceNameOrganizer.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/DmiServiceNameOrganizer.java @@ -27,8 +27,8 @@ import java.util.Map; import java.util.stream.Collectors; import lombok.AccessLevel; import lombok.NoArgsConstructor; -import org.onap.cps.ncmp.api.impl.operations.RequiredDmiService; import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; +import org.onap.cps.ncmp.impl.models.RequiredDmiService; @NoArgsConstructor(access = AccessLevel.PRIVATE) public class DmiServiceNameOrganizer { diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/DataOperationEventCreator.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/DataOperationEventCreator.java deleted file mode 100644 index 68b14349df..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/DataOperationEventCreator.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2023-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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.cps.ncmp.api.impl.utils.data.operation; - -import io.cloudevents.CloudEvent; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.onap.cps.ncmp.api.NcmpResponseStatus; -import org.onap.cps.ncmp.api.impl.operations.DmiDataOperation; -import org.onap.cps.ncmp.events.async1_0_0.Data; -import org.onap.cps.ncmp.events.async1_0_0.DataOperationEvent; -import org.onap.cps.ncmp.events.async1_0_0.Response; -import org.onap.cps.ncmp.utils.events.NcmpEvent; -import org.springframework.util.MultiValueMap; - -@Slf4j -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public class DataOperationEventCreator { - - /** - * Creates data operation event. - * - * @param clientTopic topic the client wants to use for responses - * @param requestId unique identifier per request - * @param cmHandleIdsPerResponseCodesPerOperation map of cm handles per operation response per response code - * @return Cloud Event - */ - public static CloudEvent createDataOperationEvent(final String clientTopic, - final String requestId, - final MultiValueMap>> - cmHandleIdsPerResponseCodesPerOperation) { - final DataOperationEvent dataOperationEvent = new DataOperationEvent(); - final Data data = createPayloadFromDataOperationResponses(cmHandleIdsPerResponseCodesPerOperation); - dataOperationEvent.setData(data); - final Map extensions = createDataOperationExtensions(requestId, clientTopic); - return NcmpEvent.builder().type(DataOperationEvent.class.getName()) - .data(dataOperationEvent).extensions(extensions).build().asCloudEvent(); - } - - private static Data createPayloadFromDataOperationResponses(final MultiValueMap>> cmHandleIdsPerResponseCodesPerOperation) { - final Data data = new Data(); - final List responses = new ArrayList<>(); - cmHandleIdsPerResponseCodesPerOperation.forEach((dmiDataOperation, cmHandleIdsPerResponseCodes) -> - cmHandleIdsPerResponseCodes.forEach(cmHandleIdsPerResponseCodeEntries -> - responses.addAll(createResponseFromDataOperationResponses( - dmiDataOperation, cmHandleIdsPerResponseCodeEntries)))); - data.setResponses(responses); - return data; - } - - private static List createResponseFromDataOperationResponses( - final DmiDataOperation dmiDataOperation, - final Map> cmHandleIdsPerResponseCodeEntries) { - final List responses = new ArrayList<>(); - cmHandleIdsPerResponseCodeEntries.forEach((ncmpEventResponseCode, cmHandleIds) -> { - final Response response = new Response(); - response.setOperationId(dmiDataOperation.getOperationId()); - response.setStatusCode(ncmpEventResponseCode.getCode()); - response.setStatusMessage(ncmpEventResponseCode.getMessage()); - response.setIds(cmHandleIds); - response.setResourceIdentifier(dmiDataOperation.getResourceIdentifier()); - response.setOptions(dmiDataOperation.getOptions()); - responses.add(response); - }); - return responses; - } - - private static Map createDataOperationExtensions(final String requestId, final String clientTopic) { - final Map extensions = new HashMap<>(); - extensions.put("correlationid", requestId); - extensions.put("destination", clientTopic); - return extensions; - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/ResourceDataOperationRequestUtils.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/ResourceDataOperationRequestUtils.java deleted file mode 100644 index bb0c9a3150..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/ResourceDataOperationRequestUtils.java +++ /dev/null @@ -1,201 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2023-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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.cps.ncmp.api.impl.utils.data.operation; - -import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLES_NOT_FOUND; -import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLES_NOT_READY; - -import io.cloudevents.CloudEvent; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.onap.cps.events.EventsPublisher; -import org.onap.cps.ncmp.api.NcmpResponseStatus; -import org.onap.cps.ncmp.api.impl.operations.DmiDataOperation; -import org.onap.cps.ncmp.api.impl.operations.DmiOperationCmHandle; -import org.onap.cps.ncmp.api.impl.utils.DmiServiceNameOrganizer; -import org.onap.cps.ncmp.api.impl.utils.context.CpsApplicationContext; -import org.onap.cps.ncmp.api.models.DataOperationDefinition; -import org.onap.cps.ncmp.api.models.DataOperationRequest; -import org.onap.cps.ncmp.impl.inventory.models.CmHandleState; -import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; - -@NoArgsConstructor(access = AccessLevel.PRIVATE) -@Slf4j -public class ResourceDataOperationRequestUtils { - - private static final String UNKNOWN_SERVICE_NAME = null; - - /** - * Create a list of DMI data operation per DMI service (name). - * - * @param topicParamInQuery client given topic - * @param requestId unique identifier per request - * @param dataOperationRequestIn incoming data operation request details - * @param yangModelCmHandles involved cm handles represented as YangModelCmHandle (incl. metadata) - * @return {@code Map>} Create a list of DMI batch operation per DMI service (name). - */ - public static Map> processPerDefinitionInDataOperationsRequest( - final String topicParamInQuery, - final String requestId, - final DataOperationRequest dataOperationRequestIn, - final Collection yangModelCmHandles) { - - final Map> dmiDataOperationsOutPerDmiServiceName = new HashMap<>(); - final MultiValueMap>> cmHandleIdsPerResponseCodesPerOperation = new LinkedMultiValueMap<>(); - final Set nonReadyCmHandleIdsLookup = filterAndGetNonReadyCmHandleIds(yangModelCmHandles); - - final Map>> dmiPropertiesPerCmHandleIdPerServiceName = - DmiServiceNameOrganizer.getDmiPropertiesPerCmHandleIdPerServiceName(yangModelCmHandles); - - final Map dmiServiceNamesPerCmHandleId = - getDmiServiceNamesPerCmHandleId(dmiPropertiesPerCmHandleIdPerServiceName); - - final Map moduleSetTagPerCmHandle = getModuleSetTagPerCmHandleId(yangModelCmHandles); - - for (final DataOperationDefinition dataOperationDefinitionIn : - dataOperationRequestIn.getDataOperationDefinitions()) { - final List nonExistingCmHandleIds = new ArrayList<>(); - final List nonReadyCmHandleIds = new ArrayList<>(); - for (final String cmHandleId : dataOperationDefinitionIn.getCmHandleIds()) { - if (nonReadyCmHandleIdsLookup.contains(cmHandleId)) { - nonReadyCmHandleIds.add(cmHandleId); - } else { - final String dmiServiceName = dmiServiceNamesPerCmHandleId.get(cmHandleId); - final Map cmHandleIdProperties - = dmiPropertiesPerCmHandleIdPerServiceName.get(dmiServiceName).get(cmHandleId); - if (cmHandleIdProperties == null) { - nonExistingCmHandleIds.add(cmHandleId); - } else { - final DmiDataOperation dmiBatchOperationOut = getOrAddDmiBatchOperation(dmiServiceName, - dataOperationDefinitionIn, dmiDataOperationsOutPerDmiServiceName); - final DmiOperationCmHandle dmiOperationCmHandle = DmiOperationCmHandle - .buildDmiOperationCmHandle(cmHandleId, cmHandleIdProperties, - moduleSetTagPerCmHandle.get(cmHandleId)); - dmiBatchOperationOut.getCmHandles().add(dmiOperationCmHandle); - } - } - } - populateCmHandleIdsPerOperationIdPerResponseCode(cmHandleIdsPerResponseCodesPerOperation, - DmiDataOperation.buildDmiDataOperationRequestBodyWithoutCmHandles(dataOperationDefinitionIn), - CM_HANDLES_NOT_FOUND, nonExistingCmHandleIds); - populateCmHandleIdsPerOperationIdPerResponseCode(cmHandleIdsPerResponseCodesPerOperation, - DmiDataOperation.buildDmiDataOperationRequestBodyWithoutCmHandles(dataOperationDefinitionIn), - CM_HANDLES_NOT_READY, nonReadyCmHandleIds); - } - publishErrorMessageToClientTopic(topicParamInQuery, requestId, cmHandleIdsPerResponseCodesPerOperation); - return dmiDataOperationsOutPerDmiServiceName; - } - - private static Map getModuleSetTagPerCmHandleId( - final Collection yangModelCmHandles) { - final Map moduleSetTagPerCmHandle = new HashMap<>(yangModelCmHandles.size()); - yangModelCmHandles.forEach(yangModelCmHandle -> - moduleSetTagPerCmHandle.put(yangModelCmHandle.getId(), yangModelCmHandle.getModuleSetTag())); - return moduleSetTagPerCmHandle; - } - - /** - * Creates data operation cloud event and publish it to client topic. - * - * @param clientTopic client given topic - * @param requestId unique identifier per request - * @param cmHandleIdsPerResponseCodesPerOperation list of cm handle ids per operation with response code - */ - public static void publishErrorMessageToClientTopic(final String clientTopic, - final String requestId, - final MultiValueMap>> - cmHandleIdsPerResponseCodesPerOperation) { - if (!cmHandleIdsPerResponseCodesPerOperation.isEmpty()) { - final CloudEvent dataOperationCloudEvent = DataOperationEventCreator.createDataOperationEvent(clientTopic, - requestId, cmHandleIdsPerResponseCodesPerOperation); - final EventsPublisher eventsPublisher = CpsApplicationContext.getCpsBean(EventsPublisher.class); - log.warn("publishing error message to client topic: {} ,requestId: {}, data operation cloud event id: {}", - clientTopic, requestId, dataOperationCloudEvent.getId()); - eventsPublisher.publishCloudEvent(clientTopic, requestId, dataOperationCloudEvent); - } - } - - private static Map getDmiServiceNamesPerCmHandleId( - final Map>> dmiDmiPropertiesPerCmHandleIdPerServiceName) { - final Map dmiServiceNamesPerCmHandleId = new HashMap<>(); - for (final Map.Entry>> dmiDmiPropertiesEntry - : dmiDmiPropertiesPerCmHandleIdPerServiceName.entrySet()) { - final String dmiServiceName = dmiDmiPropertiesEntry.getKey(); - final Set cmHandleIds = dmiDmiPropertiesPerCmHandleIdPerServiceName.get(dmiServiceName).keySet(); - for (final String cmHandleId : cmHandleIds) { - dmiServiceNamesPerCmHandleId.put(cmHandleId, dmiServiceName); - } - } - dmiDmiPropertiesPerCmHandleIdPerServiceName.put(UNKNOWN_SERVICE_NAME, Collections.emptyMap()); - return dmiServiceNamesPerCmHandleId; - } - - private static DmiDataOperation getOrAddDmiBatchOperation(final String dmiServiceName, - final DataOperationDefinition - dataOperationDefinitionIn, - final Map> - dmiBatchOperationsOutPerDmiServiceName) { - dmiBatchOperationsOutPerDmiServiceName - .computeIfAbsent(dmiServiceName, dmiServiceNameAsKey -> new ArrayList<>()); - final List dmiBatchOperationsOut - = dmiBatchOperationsOutPerDmiServiceName.get(dmiServiceName); - final boolean isNewOperation = dmiBatchOperationsOut.isEmpty() - || !dmiBatchOperationsOut.get(dmiBatchOperationsOut.size() - 1).getOperationId() - .equals(dataOperationDefinitionIn.getOperationId()); - if (isNewOperation) { - final DmiDataOperation newDmiBatchOperationOut = - DmiDataOperation.buildDmiDataOperationRequestBodyWithoutCmHandles(dataOperationDefinitionIn); - dmiBatchOperationsOut.add(newDmiBatchOperationOut); - return newDmiBatchOperationOut; - } - return dmiBatchOperationsOut.get(dmiBatchOperationsOut.size() - 1); - } - - private static Set filterAndGetNonReadyCmHandleIds(final Collection yangModelCmHandles) { - return yangModelCmHandles.stream() - .filter(yangModelCmHandle -> yangModelCmHandle.getCompositeState().getCmHandleState() - != CmHandleState.READY).map(YangModelCmHandle::getId).collect(Collectors.toSet()); - } - - private static void populateCmHandleIdsPerOperationIdPerResponseCode(final MultiValueMap>> cmHandleIdsPerResponseCodesPerOperation, - final DmiDataOperation dmiDataOperation, - final NcmpResponseStatus - ncmpResponseStatus, - final List cmHandleIds) { - if (!cmHandleIds.isEmpty()) { - cmHandleIdsPerResponseCodesPerOperation.add(dmiDataOperation, Map.of(ncmpResponseStatus, cmHandleIds)); - } - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmDataSubscriptionEvent.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmDataSubscriptionEvent.java deleted file mode 100644 index e527d99f2f..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmDataSubscriptionEvent.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2023 Nordix Foundation - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - - -package org.onap.cps.ncmp.api.impl.yangmodels; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonInclude.Include; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -/** - * Subscription event model to persist data into DB. - * Yang model subscription event - */ -@Getter -@Setter -@NoArgsConstructor -@JsonInclude(Include.NON_NULL) -@EqualsAndHashCode(onlyExplicitlyIncluded = true) -public class YangModelCmDataSubscriptionEvent { - - @EqualsAndHashCode.Include - @JsonProperty("name") - private String name; - - private List cmHandles; - - @AllArgsConstructor - @Data - @JsonInclude(JsonInclude.Include.NON_NULL) - public static class CmHandle { - - @JsonProperty() - private final String id; - - private final List filters; - } - - @AllArgsConstructor - @Data - @JsonInclude(JsonInclude.Include.NON_NULL) - public static class Filter { - - @JsonProperty() - private final String id; - - @JsonProperty() - private final List subscribers; - } -} - - diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmResourceAddress.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmResourceAddress.java deleted file mode 100644 index 21d82fcf56..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmResourceAddress.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.cps.ncmp.api.models; - -public record CmResourceAddress(String datastoreName, String cmHandleId, String resourceIdentifier) { - -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DataOperationDefinition.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DataOperationDefinition.java deleted file mode 100644 index 366d845832..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DataOperationDefinition.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2023 Nordix Foundation - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.cps.ncmp.api.models; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import jakarta.validation.Valid; -import java.util.ArrayList; -import java.util.List; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; - -@Getter -@Setter -@EqualsAndHashCode -@JsonInclude(JsonInclude.Include.NON_EMPTY) -@JsonIgnoreProperties(ignoreUnknown = true) -public class DataOperationDefinition { - - private String operation; - private String operationId; - private String datastore; - private String options; - private String resourceIdentifier; - - @JsonProperty("targetIds") - @Valid - private List cmHandleIds = new ArrayList<>(); -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DataOperationRequest.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DataOperationRequest.java deleted file mode 100644 index a4d070c38d..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DataOperationRequest.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2023 Nordix Foundation - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.cps.ncmp.api.models; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import jakarta.validation.Valid; -import java.util.Collections; -import java.util.List; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; - -@Getter -@Setter -@EqualsAndHashCode -@JsonInclude(JsonInclude.Include.NON_EMPTY) -@JsonIgnoreProperties(ignoreUnknown = true) -public class DataOperationRequest { - - @JsonProperty("operations") - @Valid - private List dataOperationDefinitions = Collections.emptyList(); -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/exceptions/OperationNotSupportedException.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/exceptions/OperationNotSupportedException.java deleted file mode 100644 index d75c0bd47a..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/exceptions/OperationNotSupportedException.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2023 Nordix Foundation - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.cps.ncmp.exceptions; - -public class OperationNotSupportedException extends RuntimeException { - /** - * Instantiates a new not implemented operation exception. - * - * @param message the message - */ - public OperationNotSupportedException(final String message) { - super(message); - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/DmiDataOperations.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/DmiDataOperations.java new file mode 100644 index 0000000000..e6bb712861 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/DmiDataOperations.java @@ -0,0 +1,303 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021-2024 Nordix Foundation + * Modifications Copyright (C) 2022 Bell Canada + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.impl.data; + +import static org.onap.cps.ncmp.api.data.models.DatastoreType.PASSTHROUGH_OPERATIONAL; +import static org.onap.cps.ncmp.api.data.models.DatastoreType.PASSTHROUGH_RUNNING; + +import io.micrometer.core.annotation.Timed; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import lombok.RequiredArgsConstructor; +import org.onap.cps.ncmp.api.NcmpResponseStatus; +import org.onap.cps.ncmp.api.data.models.CmResourceAddress; +import org.onap.cps.ncmp.api.data.models.DataOperationRequest; +import org.onap.cps.ncmp.api.data.models.OperationType; +import org.onap.cps.ncmp.api.impl.client.DmiRestClient; +import org.onap.cps.ncmp.api.impl.config.DmiProperties; +import org.onap.cps.ncmp.api.impl.exception.DmiClientRequestException; +import org.onap.cps.ncmp.api.impl.utils.DmiServiceUrlBuilder; +import org.onap.cps.ncmp.impl.data.models.DmiDataOperation; +import org.onap.cps.ncmp.impl.data.models.DmiDataOperationRequest; +import org.onap.cps.ncmp.impl.data.models.DmiOperationCmHandle; +import org.onap.cps.ncmp.impl.data.utils.DmiDataOperationsHelper; +import org.onap.cps.ncmp.impl.inventory.InventoryPersistence; +import org.onap.cps.ncmp.impl.inventory.models.CmHandleState; +import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; +import org.onap.cps.ncmp.impl.models.DmiRequestBody; +import org.onap.cps.ncmp.impl.models.RequiredDmiService; +import org.onap.cps.spi.exceptions.CpsException; +import org.onap.cps.utils.JsonObjectMapper; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.util.UriComponentsBuilder; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +/** + * Operations class for DMI data. + */ +@RequiredArgsConstructor +@Service +public class DmiDataOperations { + + private final InventoryPersistence inventoryPersistence; + private final JsonObjectMapper jsonObjectMapper; + private final DmiProperties dmiProperties; + private final DmiRestClient dmiRestClient; + + /** + * This method fetches the resource data from the operational data store for a given CM handle + * identifier on the specified resource using the DMI client. + * + * @param cmResourceAddress Target datastore, CM handle, and resource identifier. + * @param options Options query string. + * @param topic Topic name for triggering asynchronous responses. + * @param requestId Request ID for asynchronous responses. + * @param authorization Contents of the Authorization header, or null if not present. + * @return {@code Mono>} A reactive type representing the response entity. + */ + @Timed(value = "cps.ncmp.dmi.get", + description = "Time taken to fetch the resource data from operational data store for given cm handle " + + "identifier on given resource using dmi client") + public Mono> getResourceDataFromDmi(final CmResourceAddress cmResourceAddress, + final String options, + final String topic, + final String requestId, + final String authorization) { + final YangModelCmHandle yangModelCmHandle = getYangModelCmHandle(cmResourceAddress.cmHandleId()); + final CmHandleState cmHandleState = yangModelCmHandle.getCompositeState().getCmHandleState(); + validateIfCmHandleStateReady(yangModelCmHandle, cmHandleState); + final String jsonRequestBody = getDmiRequestBody(OperationType.READ, requestId, null, null, yangModelCmHandle); + final String dmiUrl = getDmiResourceDataUrl(cmResourceAddress.datastoreName(), yangModelCmHandle, + cmResourceAddress.resourceIdentifier(), options, topic); + return dmiRestClient.asynchronousPostOperationWithJsonData(RequiredDmiService.DATA, + dmiUrl, jsonRequestBody, OperationType.READ, authorization); + } + + /** + * This method fetches all the resource data from operational data store for given cm handle + * identifier using dmi client. + * Note: this method is only used for DataSync + * + * @param cmHandleId network resource identifier + * @param requestId requestId for async responses + * @return {@code ResponseEntity} response entity + */ + public ResponseEntity getAllResourceDataFromDmi(final String cmHandleId, final String requestId) { + final YangModelCmHandle yangModelCmHandle = getYangModelCmHandle(cmHandleId); + final CmHandleState cmHandleState = yangModelCmHandle.getCompositeState().getCmHandleState(); + validateIfCmHandleStateReady(yangModelCmHandle, cmHandleState); + + final String jsonRequestBody = getDmiRequestBody(OperationType.READ, requestId, null, null, yangModelCmHandle); + final String dmiUrl = + getDmiResourceDataUrl(PASSTHROUGH_OPERATIONAL.getDatastoreName(), yangModelCmHandle, "/", null, null); + return dmiRestClient.synchronousPostOperationWithJsonData(RequiredDmiService.DATA, dmiUrl, jsonRequestBody, + OperationType.READ, null); + } + + /** + * This method requests the resource data by data store for given list of cm handles using dmi client. + * The data wil be returned as message on the topic specified. + * + * @param topicParamInQuery topic name for (triggering) async responses + * @param dataOperationRequest data operation request to execute operations + * @param requestId requestId for as a response + * @param authorization contents of Authorization header, or null if not present + */ + public void requestResourceDataFromDmi(final String topicParamInQuery, + final DataOperationRequest dataOperationRequest, + final String requestId, + final String authorization) { + + final Set cmHandlesIds + = getDistinctCmHandleIdsFromDataOperationRequest(dataOperationRequest); + + final Collection yangModelCmHandles + = inventoryPersistence.getYangModelCmHandles(cmHandlesIds); + + final Map> operationsOutPerDmiServiceName + = DmiDataOperationsHelper.processPerDefinitionInDataOperationsRequest(topicParamInQuery, + requestId, dataOperationRequest, yangModelCmHandles); + + buildDataOperationRequestUrlAndSendToDmiService(requestId, topicParamInQuery, operationsOutPerDmiServiceName, + authorization); + } + + /** + * This method creates the resource data from pass-through running data store for given cm handle + * identifier on given resource using dmi client. + * + * @param cmHandleId network resource identifier + * @param resourceId resource identifier + * @param operationType operation enum + * @param requestData the request data + * @param dataType data type + * @param authorization contents of Authorization header, or null if not present + * @return {@code ResponseEntity} response entity + */ + public ResponseEntity writeResourceDataPassThroughRunningFromDmi(final String cmHandleId, + final String resourceId, + final OperationType operationType, + final String requestData, + final String dataType, + final String authorization) { + final YangModelCmHandle yangModelCmHandle = getYangModelCmHandle(cmHandleId); + final CmHandleState cmHandleState = yangModelCmHandle.getCompositeState().getCmHandleState(); + validateIfCmHandleStateReady(yangModelCmHandle, cmHandleState); + + final String jsonRequestBody = getDmiRequestBody(operationType, null, requestData, dataType, + yangModelCmHandle); + final String dmiUrl = getDmiResourceDataUrl(PASSTHROUGH_RUNNING.getDatastoreName(), + yangModelCmHandle, resourceId, null, null); + return dmiRestClient.synchronousPostOperationWithJsonData(RequiredDmiService.DATA, dmiUrl, jsonRequestBody, + operationType, authorization); + } + + private YangModelCmHandle getYangModelCmHandle(final String cmHandleId) { + return inventoryPersistence.getYangModelCmHandle(cmHandleId); + } + + private String getDmiRequestBody(final OperationType operationType, + final String requestId, + final String requestData, + final String dataType, + final YangModelCmHandle yangModelCmHandle) { + final DmiRequestBody dmiRequestBody = DmiRequestBody.builder() + .operationType(operationType) + .requestId(requestId) + .data(requestData) + .dataType(dataType) + .moduleSetTag(yangModelCmHandle.getModuleSetTag()) + .build(); + dmiRequestBody.asDmiProperties(yangModelCmHandle.getDmiProperties()); + return jsonObjectMapper.asJsonString(dmiRequestBody); + } + + private String getDmiResourceDataUrl(final String datastoreName, + final YangModelCmHandle yangModelCmHandle, + final String resourceIdentifier, + final String optionsParamInQuery, + final String topicParamInQuery) { + final String dmiServiceName = yangModelCmHandle.resolveDmiServiceName(RequiredDmiService.DATA); + return DmiServiceUrlBuilder.newInstance() + .pathSegment("ch") + .variablePathSegment("cmHandleId", yangModelCmHandle.getId()) + .pathSegment("data") + .pathSegment("ds") + .variablePathSegment("datastore", datastoreName) + .queryParameter("resourceIdentifier", resourceIdentifier) + .queryParameter("options", optionsParamInQuery) + .queryParameter("topic", topicParamInQuery) + .build(dmiServiceName, dmiProperties.getDmiBasePath()); + } + + private void validateIfCmHandleStateReady(final YangModelCmHandle yangModelCmHandle, + final CmHandleState cmHandleState) { + if (cmHandleState != CmHandleState.READY) { + throw new CpsException("State mismatch exception.", "Cm-Handle not in READY state. " + + "cm handle state is " + + yangModelCmHandle.getCompositeState().getCmHandleState()); + } + } + + private static Set getDistinctCmHandleIdsFromDataOperationRequest(final DataOperationRequest + dataOperationRequest) { + return dataOperationRequest.getDataOperationDefinitions().stream() + .flatMap(dataOperationDefinition -> + dataOperationDefinition.getCmHandleIds().stream()).collect(Collectors.toSet()); + } + + private void buildDataOperationRequestUrlAndSendToDmiService(final String requestId, + final String topicParamInQuery, + final Map> + groupsOutPerDmiServiceName, + final String authorization) { + + Flux.fromIterable(groupsOutPerDmiServiceName.entrySet()) + .flatMap(dmiDataOperationsByDmiServiceName -> { + final String dmiServiceName = dmiDataOperationsByDmiServiceName.getKey(); + final String dmiUrl = buildDmiServiceUrl(dmiServiceName, requestId, topicParamInQuery); + final List dmiDataOperationRequestBodies + = dmiDataOperationsByDmiServiceName.getValue(); + return sendDataOperationRequestToDmiService(dmiUrl, dmiDataOperationRequestBodies, authorization); + }) + .subscribe(); + } + + private String buildDmiServiceUrl(final String dmiServiceName, final String requestId, + final String topicParamInQuery) { + return DmiServiceUrlBuilder.newInstance() + .pathSegment("data") + .queryParameter("requestId", requestId) + .queryParameter("topic", topicParamInQuery) + .build(dmiServiceName, dmiProperties.getDmiBasePath()); + } + + private Mono sendDataOperationRequestToDmiService(final String dmiUrl, + final List dmiDataOperationRequestBodies, + final String authorization) { + final String dmiDataOperationRequestAsJsonString + = createDmiDataOperationRequestAsJsonString(dmiDataOperationRequestBodies); + return dmiRestClient.asynchronousPostOperationWithJsonData(RequiredDmiService.DATA, dmiUrl, + dmiDataOperationRequestAsJsonString, OperationType.READ, authorization) + .then() + .onErrorResume(DmiClientRequestException.class, dmiClientRequestException -> { + handleTaskCompletionException(dmiClientRequestException, dmiUrl, dmiDataOperationRequestBodies); + return Mono.empty(); + }); + } + + private String createDmiDataOperationRequestAsJsonString( + final List dmiDataOperationRequestBodies) { + final DmiDataOperationRequest dmiDataOperationRequest = DmiDataOperationRequest.builder() + .operations(dmiDataOperationRequestBodies) + .build(); + return jsonObjectMapper.asJsonString(dmiDataOperationRequest); + } + + private void handleTaskCompletionException(final DmiClientRequestException dmiClientRequestException, + final String dataOperationResourceUrl, + final List dmiDataOperationRequestBodies) { + final MultiValueMap dataOperationResourceUrlParameters = + UriComponentsBuilder.fromUriString(dataOperationResourceUrl).build().getQueryParams(); + final String topicName = dataOperationResourceUrlParameters.get("topic").get(0); + final String requestId = dataOperationResourceUrlParameters.get("requestId").get(0); + + final MultiValueMap>> + cmHandleIdsPerResponseCodesPerOperation = new LinkedMultiValueMap<>(); + + dmiDataOperationRequestBodies.forEach(dmiDataOperationRequestBody -> { + final List cmHandleIds = dmiDataOperationRequestBody.getCmHandles().stream() + .map(DmiOperationCmHandle::getId).toList(); + cmHandleIdsPerResponseCodesPerOperation.add(dmiDataOperationRequestBody, + Map.of(dmiClientRequestException.getNcmpResponseStatus(), cmHandleIds)); + }); + DmiDataOperationsHelper.publishErrorMessageToClientTopic(topicName, requestId, + cmHandleIdsPerResponseCodesPerOperation); + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NcmpCachedResourceRequestHandler.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NcmpCachedResourceRequestHandler.java new file mode 100644 index 0000000000..bff2f6390c --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NcmpCachedResourceRequestHandler.java @@ -0,0 +1,75 @@ +/* + * ============LICENSE_START======================================================= + * 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.impl.data; + +import java.util.Collection; +import lombok.RequiredArgsConstructor; +import org.onap.cps.api.CpsDataService; +import org.onap.cps.ncmp.api.data.models.CmResourceAddress; +import org.onap.cps.spi.FetchDescendantsOption; +import org.onap.cps.spi.model.DataNode; +import org.springframework.stereotype.Service; +import reactor.core.publisher.Mono; + +@Service +@RequiredArgsConstructor +public class NcmpCachedResourceRequestHandler extends NcmpDatastoreRequestHandler { + + private final CpsDataService cpsDataService; + private final NetworkCmProxyQueryService networkCmProxyQueryService; + + /** + * Executes a synchronous query request for given cm handle. + * Note. Currently only ncmp-datastore:operational supports query operations. + * + * @param cmHandleId the cm handle + * @param resourceIdentifier the resource identifier + * @param includeDescendants whether include descendants + * @return a collection of data nodes + */ + public Collection executeRequest(final String cmHandleId, final String resourceIdentifier, + final boolean includeDescendants) { + final FetchDescendantsOption fetchDescendantsOption = getFetchDescendantsOption(includeDescendants); + return networkCmProxyQueryService.queryResourceDataOperational(cmHandleId, resourceIdentifier, + fetchDescendantsOption); + } + + @Override + protected Mono getResourceDataForCmHandle(final CmResourceAddress cmResourceAddress, + final String optionsParamInQuery, + final String topicParamInQuery, + final String requestId, + final boolean includeDescendants, + final String authorization) { + final FetchDescendantsOption fetchDescendantsOption = getFetchDescendantsOption(includeDescendants); + + final DataNode dataNode = cpsDataService.getDataNodes(cmResourceAddress.datastoreName(), + cmResourceAddress.cmHandleId(), + cmResourceAddress.resourceIdentifier(), + fetchDescendantsOption).iterator().next(); + return Mono.justOrEmpty(dataNode); + } + + private static FetchDescendantsOption getFetchDescendantsOption(final boolean includeDescendants) { + return includeDescendants ? FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS + : FetchDescendantsOption.OMIT_DESCENDANTS; + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NcmpDatastoreRequestHandler.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NcmpDatastoreRequestHandler.java new file mode 100644 index 0000000000..f0a8c6c5d2 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NcmpDatastoreRequestHandler.java @@ -0,0 +1,96 @@ +/* + * ============LICENSE_START======================================================= + * 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.impl.data; + +import java.util.Map; +import java.util.UUID; +import lombok.extern.slf4j.Slf4j; +import org.onap.cps.ncmp.api.data.models.CmResourceAddress; +import org.onap.cps.ncmp.utils.events.TopicValidator; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import reactor.core.publisher.Mono; + +@Slf4j +@Service +public abstract class NcmpDatastoreRequestHandler { + + private static final String NO_REQUEST_ID = null; + private static final String NO_TOPIC = null; + + @Value("${notification.async.executor.time-out-value-in-ms:60000}") + protected int timeOutInMilliSeconds; + @Value("${notification.enabled:true}") + protected boolean notificationFeatureEnabled; + + /** + * Executes synchronous/asynchronous get request for given cm handle. + * + * @param cmResourceAddress the name of the datastore, cm handle and resource identifier + * @param options options to pass through to dmi client + * @param topic topic (optional) for asynchronous responses + * @param includeDescendants whether include descendants + * @param authorization contents of Authorization header, or null if not present + * @return the result object, depends on use op topic. With topic a map object with request id is returned + * otherwise the result of the request. + */ + public Object executeRequest(final CmResourceAddress cmResourceAddress, + final String options, + final String topic, + final boolean includeDescendants, + final String authorization) { + + final boolean asyncResponseRequested = topic != null; + if (asyncResponseRequested && notificationFeatureEnabled) { + return getResourceDataAsynchronously(cmResourceAddress, options, topic, includeDescendants, authorization); + } + + if (asyncResponseRequested) { + log.warn("Asynchronous request is unavailable as notification feature is currently disabled, " + + "will use synchronous operation."); + } + final Mono resourceDataMono = getResourceDataForCmHandle(cmResourceAddress, options, + NO_TOPIC, NO_REQUEST_ID, includeDescendants, authorization); + return resourceDataMono.block(); + } + + private Map getResourceDataAsynchronously(final CmResourceAddress cmResourceAddress, + final String options, + final String topic, + final boolean includeDescendants, + final String authorization) { + TopicValidator.validateTopicName(topic); + final String requestId = UUID.randomUUID().toString(); + getResourceDataForCmHandle(cmResourceAddress, options, topic, requestId, includeDescendants, authorization) + .doOnSuccess(result -> + log.debug("Async operation succeeded for request id {}: {}", requestId, result)) + .subscribe(); + log.debug("Received Async request with id {}", requestId); + return Map.of("requestId", requestId); + } + + protected abstract Mono getResourceDataForCmHandle(final CmResourceAddress cmResourceAddress, + final String optionsParamInQuery, + final String topicParamInQuery, + final String requestId, + final boolean includeDescendant, + final String authorization); +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NcmpPassthroughResourceRequestHandler.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NcmpPassthroughResourceRequestHandler.java new file mode 100644 index 0000000000..be2dde2308 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NcmpPassthroughResourceRequestHandler.java @@ -0,0 +1,102 @@ +/* + * ============LICENSE_START======================================================= + * 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.impl.data; + +import static org.onap.cps.ncmp.api.data.models.DatastoreType.OPERATIONAL; +import static org.onap.cps.ncmp.api.data.models.OperationType.READ; + +import java.util.Map; +import java.util.UUID; +import lombok.RequiredArgsConstructor; +import org.onap.cps.ncmp.api.data.exceptions.InvalidDatastoreException; +import org.onap.cps.ncmp.api.data.exceptions.OperationNotSupportedException; +import org.onap.cps.ncmp.api.data.models.CmResourceAddress; +import org.onap.cps.ncmp.api.data.models.DataOperationRequest; +import org.onap.cps.ncmp.api.data.models.DatastoreType; +import org.onap.cps.ncmp.api.data.models.OperationType; +import org.onap.cps.ncmp.exceptions.PayloadTooLargeException; +import org.onap.cps.ncmp.utils.events.TopicValidator; +import org.springframework.stereotype.Service; +import reactor.core.publisher.Mono; + +@Service +@RequiredArgsConstructor +public class NcmpPassthroughResourceRequestHandler extends NcmpDatastoreRequestHandler { + + private final DmiDataOperations dmiDataOperations; + + private static final int MAXIMUM_CM_HANDLES_PER_OPERATION = 200; + private static final String PAYLOAD_TOO_LARGE_TEMPLATE = "Operation '%s' affects too many (%d) cm handles"; + + /** + * Executes asynchronous request for group of cm handles to resource data. + * + * @param topic 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 a map with one entry of request Id for success or status and error when async feature is disabled + */ + public Map executeAsynchronousRequest(final String topic, + final DataOperationRequest dataOperationRequest, + final String authorization) { + validateDataOperationRequest(topic, dataOperationRequest); + if (!notificationFeatureEnabled) { + return Map.of("status", + "Asynchronous request is unavailable as notification feature is currently disabled."); + } + final String requestId = UUID.randomUUID().toString(); + dmiDataOperations.requestResourceDataFromDmi(topic, dataOperationRequest, requestId, authorization); + return Map.of("requestId", requestId); + } + + @Override + protected Mono getResourceDataForCmHandle(final CmResourceAddress cmResourceAddress, + final String options, + final String topic, + final String requestId, + final boolean includeDescendants, + final String authorization) { + + return dmiDataOperations.getResourceDataFromDmi(cmResourceAddress, options, topic, requestId, authorization) + .flatMap(responseEntity -> Mono.justOrEmpty(responseEntity.getBody())); + } + + private void validateDataOperationRequest(final String topicParamInQuery, + final DataOperationRequest dataOperationRequest) { + TopicValidator.validateTopicName(topicParamInQuery); + dataOperationRequest.getDataOperationDefinitions().forEach(dataOperationDefinition -> { + if (OperationType.fromOperationName(dataOperationDefinition.getOperation()) != READ) { + throw new OperationNotSupportedException( + dataOperationDefinition.getOperation() + " operation not yet supported"); + } + if (DatastoreType.fromDatastoreName(dataOperationDefinition.getDatastore()) == OPERATIONAL) { + throw new InvalidDatastoreException(dataOperationDefinition.getDatastore() + + " datastore is not supported"); + } + if (dataOperationDefinition.getCmHandleIds().size() > MAXIMUM_CM_HANDLES_PER_OPERATION) { + final String errorMessage = String.format(PAYLOAD_TOO_LARGE_TEMPLATE, + dataOperationDefinition.getOperationId(), + dataOperationDefinition.getCmHandleIds().size()); + throw new PayloadTooLargeException(errorMessage); + } + }); + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NetworkCmProxyFacade.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NetworkCmProxyFacade.java new file mode 100644 index 0000000000..503915716e --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NetworkCmProxyFacade.java @@ -0,0 +1,128 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 highstreet technologies GmbH + * Modifications Copyright (C) 2021-2024 Nordix Foundation + * Modifications Copyright (C) 2021 Pantheon.tech + * Modifications Copyright (C) 2021-2022 Bell Canada + * Modifications Copyright (C) 2023 TechMahindra Ltd. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.impl.data; + +import static org.onap.cps.ncmp.api.data.models.DatastoreType.OPERATIONAL; + +import java.util.Collection; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.onap.cps.ncmp.api.data.models.CmResourceAddress; +import org.onap.cps.ncmp.api.data.models.DataOperationRequest; +import org.onap.cps.ncmp.api.data.models.DatastoreType; +import org.onap.cps.ncmp.api.data.models.OperationType; +import org.onap.cps.spi.model.DataNode; +import org.springframework.stereotype.Service; + +@Slf4j +@Service +@RequiredArgsConstructor +public class NetworkCmProxyFacade { + + private final NcmpCachedResourceRequestHandler ncmpCachedResourceRequestHandler; + private final NcmpPassthroughResourceRequestHandler ncmpPassthroughResourceRequestHandler; + private final DmiDataOperations dmiDataOperations; + + /** + * Fetches resource data for a given data store using DMI (Data Management Interface). + * This method retrieves data based on the provided CmResourceAddress and additional query parameters. + * It supports asynchronous processing and handles authorization if required. + * + * @param cmResourceAddress The target data store, including the CM handle and resource identifier. + * This parameter must not be null. + * @param options Additional query parameters that may influence the data retrieval process, + * such as filters or limits. This parameter can be null. + * @param topic The topic name for triggering asynchronous responses. If specified, + * the response will be sent to this topic. This parameter can be null. + * @param includeDescendants include (all) descendants or not + * @param authorization The contents of the Authorization header. This parameter can be null + * if authorization is not required. + * @return the result object, depends on use op topic. With topic a map object with request id is returned + * otherwise the result of the request. + */ + public Object getResourceDataForCmHandle(final CmResourceAddress cmResourceAddress, + final String options, + final String topic, + final Boolean includeDescendants, + final String authorization) { + final NcmpDatastoreRequestHandler ncmpDatastoreRequestHandler + = getNcmpDatastoreRequestHandler(cmResourceAddress.datastoreName()); + + return ncmpDatastoreRequestHandler.executeRequest(cmResourceAddress, options, topic, includeDescendants, + authorization); + } + + /** + * Executes asynchronous request for group of cm handles to resource data. + * + * @param topic 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 a map with one entry of request Id for success or status and error when async feature is disabled + */ + public Object executeDataOperationForCmHandles(final String topic, + final DataOperationRequest dataOperationRequest, + final String authorization) { + return ncmpPassthroughResourceRequestHandler.executeAsynchronousRequest(topic, + dataOperationRequest, + authorization); + } + + public Collection queryResourceDataForCmHandle(final String cmHandle, + final String cpsPath, + final Boolean includeDescendants) { + return ncmpCachedResourceRequestHandler.executeRequest(cmHandle, cpsPath, includeDescendants); + } + + /** + * Write resource data for data store pass-through running using dmi for given cm-handle. + * + * @param cmHandleId cm handle identifier + * @param resourceIdentifier resource identifier + * @param operationType required operation type + * @param requestData request body to create resource + * @param dataType content type in body + * @param authorization contents of Authorization header, or null if not present + * @return {@code Object} return data + */ + public Object writeResourceDataPassThroughRunningForCmHandle(final String cmHandleId, + final String resourceIdentifier, + final OperationType operationType, + final String requestData, + final String dataType, + final String authorization) { + return dmiDataOperations.writeResourceDataPassThroughRunningFromDmi(cmHandleId, resourceIdentifier, + operationType, requestData, dataType, authorization); + } + + + private NcmpDatastoreRequestHandler getNcmpDatastoreRequestHandler(final String datastoreName) { + if (OPERATIONAL.equals(DatastoreType.fromDatastoreName(datastoreName))) { + return ncmpCachedResourceRequestHandler; + } + return ncmpPassthroughResourceRequestHandler; + } + +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NetworkCmProxyQueryService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NetworkCmProxyQueryService.java new file mode 100644 index 0000000000..39abdc56a0 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NetworkCmProxyQueryService.java @@ -0,0 +1,50 @@ +/* + * ============LICENSE_START======================================================= + * 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.impl.data; + +import java.util.Collection; +import org.onap.cps.spi.FetchDescendantsOption; +import org.onap.cps.spi.model.DataNode; + +/* + * Datastore interface for handling cached CPS data query requests. + */ +public interface NetworkCmProxyQueryService { + + /** + * Fetches operational resource data based on the provided CM handle identifier and CPS path. + * This method retrieves data nodes from the specified path within the context of a given CM handle. + * It supports options for fetching descendant nodes. + * + * @param cmHandleId The CM handle identifier, which uniquely identifies the CM handle. + * This parameter must not be null. + * @param cpsPath The CPS (Control Plane Service) path specifying the location of the + * resource data within the CM handle. This parameter must not be null. + * @param fetchDescendantsOption The option specifying whether to fetch descendant nodes along with the specified + * resource data. + * @return {@code Collection} A collection of DataNode objects representing the resource data + * retrieved from the specified path. The collection may include descendant nodes based on the + * fetchDescendantsOption. + */ + Collection queryResourceDataOperational(String cmHandleId, + String cpsPath, + FetchDescendantsOption fetchDescendantsOption); +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NetworkCmProxyQueryServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NetworkCmProxyQueryServiceImpl.java new file mode 100644 index 0000000000..021924a616 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NetworkCmProxyQueryServiceImpl.java @@ -0,0 +1,47 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022-2023 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.impl.data; + +import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME; + +import java.util.Collection; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.onap.cps.api.CpsQueryService; +import org.onap.cps.spi.FetchDescendantsOption; +import org.onap.cps.spi.model.DataNode; +import org.springframework.stereotype.Service; + +@Slf4j +@Service +@RequiredArgsConstructor +public class NetworkCmProxyQueryServiceImpl implements NetworkCmProxyQueryService { + + private final CpsQueryService cpsQueryService; + + @Override + public Collection queryResourceDataOperational(final String cmHandleId, + final String cpsPath, + final FetchDescendantsOption fetchDescendantsOption) { + return cpsQueryService.queryDataNodes(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId, cpsPath, + fetchDescendantsOption); + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/async/AsyncRestRequestResponseEventConsumer.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/async/AsyncRestRequestResponseEventConsumer.java new file mode 100644 index 0000000000..f14bb15842 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/async/AsyncRestRequestResponseEventConsumer.java @@ -0,0 +1,62 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (c) 2023-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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.impl.data.async; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.onap.cps.events.EventsPublisher; +import org.onap.cps.ncmp.event.model.DmiAsyncRequestResponseEvent; +import org.onap.cps.ncmp.event.model.NcmpAsyncRequestResponseEvent; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.kafka.annotation.KafkaListener; +import org.springframework.stereotype.Component; + +/** + * Listener for cps-ncmp async request response events. + */ +@Component +@Slf4j +@RequiredArgsConstructor +@ConditionalOnProperty(name = "notification.enabled", havingValue = "true", matchIfMissing = true) +public class AsyncRestRequestResponseEventConsumer { + + private final EventsPublisher eventsPublisher; + private final NcmpAsyncRequestResponseEventMapper ncmpAsyncRequestResponseEventMapper; + + /** + * Consume the specified event. + * + * @param dmiAsyncRequestResponseEvent the event to be consumed and produced. + */ + @KafkaListener( + topics = "${app.ncmp.async-m2m.topic}", + filter = "includeNonCloudEventsOnly", + groupId = "ncmp-async-rest-request-event-group", + properties = {"spring.json.value.default.type=org.onap.cps.ncmp.event.model.DmiAsyncRequestResponseEvent"}) + public void consumeAndForward(final DmiAsyncRequestResponseEvent dmiAsyncRequestResponseEvent) { + log.debug("Consuming event {} ...", dmiAsyncRequestResponseEvent); + final NcmpAsyncRequestResponseEvent ncmpAsyncRequestResponseEvent = + ncmpAsyncRequestResponseEventMapper.toNcmpAsyncEvent(dmiAsyncRequestResponseEvent); + eventsPublisher.publishEvent(ncmpAsyncRequestResponseEvent.getEventTarget(), + ncmpAsyncRequestResponseEvent.getEventId(), + ncmpAsyncRequestResponseEvent); + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/async/DataOperationEventConsumer.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/async/DataOperationEventConsumer.java new file mode 100644 index 0000000000..6f368da2d0 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/async/DataOperationEventConsumer.java @@ -0,0 +1,63 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2023-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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.impl.data.async; + +import io.cloudevents.CloudEvent; +import io.cloudevents.kafka.impl.KafkaHeaders; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.onap.cps.events.EventsPublisher; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.kafka.annotation.KafkaListener; +import org.springframework.stereotype.Component; + +/** + * Listener for cps-ncmp async data operation events. + */ +@Component +@Slf4j +@RequiredArgsConstructor +@ConditionalOnProperty(name = "notification.enabled", havingValue = "true", matchIfMissing = true) +public class DataOperationEventConsumer { + + private final EventsPublisher eventsPublisher; + + /** + * Consume the DataOperation cloud event published by producer to topic 'async-m2m.topic' + * and publish the same to client specified topic. + * + * @param dataOperationEventConsumerRecord consuming event as a ConsumerRecord. + */ + @KafkaListener( + topics = "${app.ncmp.async-m2m.topic}", + filter = "includeDataOperationEventsOnly", + groupId = "ncmp-data-operation-event-group", + containerFactory = "cloudEventConcurrentKafkaListenerContainerFactory") + public void consumeAndPublish(final ConsumerRecord dataOperationEventConsumerRecord) { + log.debug("Consuming event payload {} ...", dataOperationEventConsumerRecord.value()); + final String eventTarget = KafkaHeaders.getParsedKafkaHeader( + dataOperationEventConsumerRecord.headers(), "ce_destination"); + final String correlationId = KafkaHeaders.getParsedKafkaHeader( + dataOperationEventConsumerRecord.headers(), "ce_correlationid"); + eventsPublisher.publishCloudEvent(eventTarget, correlationId, dataOperationEventConsumerRecord.value()); + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/async/NcmpAsyncRequestResponseEventMapper.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/async/NcmpAsyncRequestResponseEventMapper.java new file mode 100644 index 0000000000..21d40339b2 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/async/NcmpAsyncRequestResponseEventMapper.java @@ -0,0 +1,72 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.impl.data.async; + +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.UUID; +import org.mapstruct.AfterMapping; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.MappingTarget; +import org.mapstruct.Named; +import org.onap.cps.ncmp.event.model.DmiAsyncRequestResponseEvent; +import org.onap.cps.ncmp.event.model.NcmpAsyncRequestResponseEvent; + +/** + * Mapper for converting DmiAsyncRequestResponseEvent to NcmpAsyncRequestResponseEvent. + */ +@Mapper(componentModel = "spring") +public interface NcmpAsyncRequestResponseEventMapper { + + @Mapping(source = "eventId", target = "eventId", qualifiedByName = "ncmpAsyncEventId") + @Mapping(source = "eventTime", target = "eventTime", qualifiedByName = "currentTime") + @Mapping(source = "eventId", target = "forwardedEvent.eventId") + @Mapping(source = "eventCorrelationId", target = "forwardedEvent.eventCorrelationId") + @Mapping(source = "eventSchema", target = "forwardedEvent.eventSchema") + @Mapping(source = "eventSchemaVersion", target = "forwardedEvent.eventSchemaVersion") + @Mapping(source = "eventSource", target = "forwardedEvent.eventSource") + @Mapping(source = "eventTarget", target = "forwardedEvent.eventTarget") + @Mapping(source = "eventTime", target = "forwardedEvent.eventTime") + @Mapping(source = "eventType", target = "forwardedEvent.eventType") + @Mapping(source = "eventContent.responseStatus", target = "forwardedEvent.responseStatus") + @Mapping(source = "eventContent.responseCode", target = "forwardedEvent.responseCode") + @Mapping(source = "eventContent.responseDataSchema", target = "forwardedEvent.responseDataSchema") + NcmpAsyncRequestResponseEvent toNcmpAsyncEvent(DmiAsyncRequestResponseEvent dmiAsyncRequestResponseEvent); + + @Named("ncmpAsyncEventId") + static String getNcmpAsyncEventId(String eventId) { + return UUID.randomUUID().toString(); + } + + @Named("currentTime") + static String getFormattedCurrentTime(String eventTime) { + return ZonedDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ")); + } + + @AfterMapping + default void mapAdditionalProperties(DmiAsyncRequestResponseEvent dmiAsyncRequestResponseEvent, + @MappingTarget NcmpAsyncRequestResponseEvent ncmpAsyncRequestResponseEvent) { + ncmpAsyncRequestResponseEvent.getForwardedEvent().setAdditionalProperty("response-data", + dmiAsyncRequestResponseEvent.getEventContent().getResponseData().getAdditionalProperties()); + } + +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/async/RecordFilterStrategies.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/async/RecordFilterStrategies.java new file mode 100644 index 0000000000..2615672374 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/async/RecordFilterStrategies.java @@ -0,0 +1,77 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2023 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.impl.data.async; + +import io.cloudevents.CloudEvent; +import io.cloudevents.kafka.impl.KafkaHeaders; +import java.io.Serializable; +import lombok.extern.slf4j.Slf4j; +import org.apache.kafka.common.header.Headers; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.kafka.listener.adapter.RecordFilterStrategy; + +/** + * Record filter strategies, which helps to filter the consumer records based on some conditions. + * + */ +@Configuration +@Slf4j +public class RecordFilterStrategies { + + private static final boolean EXCLUDE_EVENT = true; + + /** + * Include only DataOperation events based on the cloud event type header, It + * returns boolean, true means exclude the consumer record and false + * means include the consumer record. + * @return boolean value. + */ + @Bean + public RecordFilterStrategy includeDataOperationEventsOnly() { + return consumerRecord -> + isNotCloudEventOfType(consumerRecord.headers(), "DataOperationEvent"); + } + + /** + * Includes the consumer records based on the cloud event type header, It returns boolean, + * true means exclude the consumer record and false means include the consumer record. + * It includes only the legacy events i.e. non-cloud events + * @return boolean value. + */ + @Bean + public RecordFilterStrategy includeNonCloudEventsOnly() { + return consumerRecord -> isCloudEvent(consumerRecord.headers()); + } + + private boolean isCloudEvent(final Headers headers) { + return headers.lastHeader("ce_type") != null; + } + + private boolean isNotCloudEventOfType(final Headers headers, final String requiredEventType) { + final String eventTypeHeaderValue = KafkaHeaders.getParsedKafkaHeader(headers, "ce_type"); + if (eventTypeHeaderValue == null) { + log.trace("No ce_type header found, possibly a legacy event (ignored)"); + return EXCLUDE_EVENT; + } + return !(eventTypeHeaderValue.contains(requiredEventType)); + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/exceptions/InvalidOperationException.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/exceptions/InvalidOperationException.java new file mode 100644 index 0000000000..aea4e638f5 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/exceptions/InvalidOperationException.java @@ -0,0 +1,32 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2023 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.impl.data.exceptions; + +public class InvalidOperationException extends RuntimeException { + /** + * Instantiates a new invalid operation exception. + * + * @param message the message + */ + public InvalidOperationException(final String message) { + super(message); + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/models/DmiDataOperation.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/models/DmiDataOperation.java new file mode 100644 index 0000000000..649d3ad374 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/models/DmiDataOperation.java @@ -0,0 +1,64 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2023 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.impl.data.models; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import java.util.ArrayList; +import java.util.List; +import lombok.Builder; +import lombok.Getter; +import org.onap.cps.ncmp.api.data.models.DataOperationDefinition; +import org.onap.cps.ncmp.api.data.models.DatastoreType; +import org.onap.cps.ncmp.api.data.models.OperationType; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@Getter +@Builder +@JsonPropertyOrder({"operation", "operationId", "datastore", "options", "resourceIdentifier", "cmHandles"}) +public class DmiDataOperation { + + private OperationType operation; + private String operationId; + private String datastore; + private String options; + private String resourceIdentifier; + + private final List cmHandles = new ArrayList<>(); + + /** + * Create and initialise a (outgoing) DMI data operation. + * + * @param dataOperationDefinition definition of incoming of dataOperation request + * @return mapped dmi operation details + */ + public static DmiDataOperation buildDmiDataOperationRequestBodyWithoutCmHandles( + final DataOperationDefinition dataOperationDefinition) { + + return DmiDataOperation.builder() + .operation(OperationType.fromOperationName(dataOperationDefinition.getOperation())) + .operationId(dataOperationDefinition.getOperationId()) + .datastore(DatastoreType.fromDatastoreName(dataOperationDefinition.getDatastore()).getDatastoreName()) + .options(dataOperationDefinition.getOptions()) + .resourceIdentifier(dataOperationDefinition.getResourceIdentifier()) + .build(); + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/models/DmiDataOperationRequest.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/models/DmiDataOperationRequest.java new file mode 100644 index 0000000000..f342f04a1a --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/models/DmiDataOperationRequest.java @@ -0,0 +1,35 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2023 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.impl.data.models; + +import com.fasterxml.jackson.annotation.JsonInclude; +import java.util.List; +import lombok.Builder; +import lombok.Getter; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@Getter +@Builder +public class DmiDataOperationRequest { + + private List operations; + +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/models/DmiOperationCmHandle.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/models/DmiOperationCmHandle.java new file mode 100644 index 0000000000..6926b6890e --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/models/DmiOperationCmHandle.java @@ -0,0 +1,49 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2023 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.impl.data.models; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Map; +import lombok.Builder; +import lombok.Getter; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@Getter +@Builder +public class DmiOperationCmHandle { + private String id; + + @JsonProperty("cmHandleProperties") + private Map dmiProperties; + private String moduleSetTag; + + /** + * Builds Dmi Operation Cm Handle object with all its associated properties. + */ + public static DmiOperationCmHandle buildDmiOperationCmHandle(final String cmHandleId, + final Map dmiProperties, + final String moduleSetTag) { + return DmiOperationCmHandle.builder().id(cmHandleId) + .dmiProperties(dmiProperties).moduleSetTag(moduleSetTag) + .build(); + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/utils/DataOperationEventCreator.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/utils/DataOperationEventCreator.java new file mode 100644 index 0000000000..d74abb9935 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/utils/DataOperationEventCreator.java @@ -0,0 +1,99 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2023-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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.impl.data.utils; + +import io.cloudevents.CloudEvent; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.onap.cps.ncmp.api.NcmpResponseStatus; +import org.onap.cps.ncmp.events.async1_0_0.Data; +import org.onap.cps.ncmp.events.async1_0_0.DataOperationEvent; +import org.onap.cps.ncmp.events.async1_0_0.Response; +import org.onap.cps.ncmp.impl.data.models.DmiDataOperation; +import org.onap.cps.ncmp.utils.events.NcmpEvent; +import org.springframework.util.MultiValueMap; + +@Slf4j +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class DataOperationEventCreator { + + /** + * Creates data operation event. + * + * @param clientTopic topic the client wants to use for responses + * @param requestId unique identifier per request + * @param cmHandleIdsPerResponseCodesPerOperation map of cm handles per operation response per response code + * @return Cloud Event + */ + public static CloudEvent createDataOperationEvent(final String clientTopic, + final String requestId, + final MultiValueMap>> + cmHandleIdsPerResponseCodesPerOperation) { + final DataOperationEvent dataOperationEvent = new DataOperationEvent(); + final Data data = createPayloadFromDataOperationResponses(cmHandleIdsPerResponseCodesPerOperation); + dataOperationEvent.setData(data); + final Map extensions = createDataOperationExtensions(requestId, clientTopic); + return NcmpEvent.builder().type(DataOperationEvent.class.getName()) + .data(dataOperationEvent).extensions(extensions).build().asCloudEvent(); + } + + private static Data createPayloadFromDataOperationResponses(final MultiValueMap>> cmHandleIdsPerResponseCodesPerOperation) { + final Data data = new Data(); + final List responses = new ArrayList<>(); + cmHandleIdsPerResponseCodesPerOperation.forEach((dmiDataOperation, cmHandleIdsPerResponseCodes) -> + cmHandleIdsPerResponseCodes.forEach(cmHandleIdsPerResponseCodeEntries -> + responses.addAll(createResponseFromDataOperationResponses( + dmiDataOperation, cmHandleIdsPerResponseCodeEntries)))); + data.setResponses(responses); + return data; + } + + private static List createResponseFromDataOperationResponses( + final DmiDataOperation dmiDataOperation, + final Map> cmHandleIdsPerResponseCodeEntries) { + final List responses = new ArrayList<>(); + cmHandleIdsPerResponseCodeEntries.forEach((ncmpEventResponseCode, cmHandleIds) -> { + final Response response = new Response(); + response.setOperationId(dmiDataOperation.getOperationId()); + response.setStatusCode(ncmpEventResponseCode.getCode()); + response.setStatusMessage(ncmpEventResponseCode.getMessage()); + response.setIds(cmHandleIds); + response.setResourceIdentifier(dmiDataOperation.getResourceIdentifier()); + response.setOptions(dmiDataOperation.getOptions()); + responses.add(response); + }); + return responses; + } + + private static Map createDataOperationExtensions(final String requestId, final String clientTopic) { + final Map extensions = new HashMap<>(); + extensions.put("correlationid", requestId); + extensions.put("destination", clientTopic); + return extensions; + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/utils/DmiDataOperationsHelper.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/utils/DmiDataOperationsHelper.java new file mode 100644 index 0000000000..ab2f106449 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/utils/DmiDataOperationsHelper.java @@ -0,0 +1,201 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2023-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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.impl.data.utils; + +import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLES_NOT_FOUND; +import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLES_NOT_READY; + +import io.cloudevents.CloudEvent; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.onap.cps.events.EventsPublisher; +import org.onap.cps.ncmp.api.NcmpResponseStatus; +import org.onap.cps.ncmp.api.data.models.DataOperationDefinition; +import org.onap.cps.ncmp.api.data.models.DataOperationRequest; +import org.onap.cps.ncmp.api.impl.utils.DmiServiceNameOrganizer; +import org.onap.cps.ncmp.api.impl.utils.context.CpsApplicationContext; +import org.onap.cps.ncmp.impl.data.models.DmiDataOperation; +import org.onap.cps.ncmp.impl.data.models.DmiOperationCmHandle; +import org.onap.cps.ncmp.impl.inventory.models.CmHandleState; +import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +@Slf4j +public class DmiDataOperationsHelper { + + private static final String UNKNOWN_SERVICE_NAME = null; + + /** + * Create a list of DMI data operation per DMI service (name). + * + * @param topicParamInQuery client given topic + * @param requestId unique identifier per request + * @param dataOperationRequestIn incoming data operation request details + * @param yangModelCmHandles involved cm handles represented as YangModelCmHandle (incl. metadata) + * @return {@code Map>} Create a list of DMI batch operation per DMI service (name). + */ + public static Map> processPerDefinitionInDataOperationsRequest( + final String topicParamInQuery, + final String requestId, + final DataOperationRequest dataOperationRequestIn, + final Collection yangModelCmHandles) { + + final Map> dmiDataOperationsOutPerDmiServiceName = new HashMap<>(); + final MultiValueMap>> cmHandleIdsPerResponseCodesPerOperation = new LinkedMultiValueMap<>(); + final Set nonReadyCmHandleIdsLookup = filterAndGetNonReadyCmHandleIds(yangModelCmHandles); + + final Map>> dmiPropertiesPerCmHandleIdPerServiceName = + DmiServiceNameOrganizer.getDmiPropertiesPerCmHandleIdPerServiceName(yangModelCmHandles); + + final Map dmiServiceNamesPerCmHandleId = + getDmiServiceNamesPerCmHandleId(dmiPropertiesPerCmHandleIdPerServiceName); + + final Map moduleSetTagPerCmHandle = getModuleSetTagPerCmHandleId(yangModelCmHandles); + + for (final DataOperationDefinition dataOperationDefinitionIn : + dataOperationRequestIn.getDataOperationDefinitions()) { + final List nonExistingCmHandleIds = new ArrayList<>(); + final List nonReadyCmHandleIds = new ArrayList<>(); + for (final String cmHandleId : dataOperationDefinitionIn.getCmHandleIds()) { + if (nonReadyCmHandleIdsLookup.contains(cmHandleId)) { + nonReadyCmHandleIds.add(cmHandleId); + } else { + final String dmiServiceName = dmiServiceNamesPerCmHandleId.get(cmHandleId); + final Map cmHandleIdProperties + = dmiPropertiesPerCmHandleIdPerServiceName.get(dmiServiceName).get(cmHandleId); + if (cmHandleIdProperties == null) { + nonExistingCmHandleIds.add(cmHandleId); + } else { + final DmiDataOperation dmiBatchOperationOut = getOrAddDmiBatchOperation(dmiServiceName, + dataOperationDefinitionIn, dmiDataOperationsOutPerDmiServiceName); + final DmiOperationCmHandle dmiOperationCmHandle = DmiOperationCmHandle + .buildDmiOperationCmHandle(cmHandleId, cmHandleIdProperties, + moduleSetTagPerCmHandle.get(cmHandleId)); + dmiBatchOperationOut.getCmHandles().add(dmiOperationCmHandle); + } + } + } + populateCmHandleIdsPerOperationIdPerResponseCode(cmHandleIdsPerResponseCodesPerOperation, + DmiDataOperation.buildDmiDataOperationRequestBodyWithoutCmHandles(dataOperationDefinitionIn), + CM_HANDLES_NOT_FOUND, nonExistingCmHandleIds); + populateCmHandleIdsPerOperationIdPerResponseCode(cmHandleIdsPerResponseCodesPerOperation, + DmiDataOperation.buildDmiDataOperationRequestBodyWithoutCmHandles(dataOperationDefinitionIn), + CM_HANDLES_NOT_READY, nonReadyCmHandleIds); + } + publishErrorMessageToClientTopic(topicParamInQuery, requestId, cmHandleIdsPerResponseCodesPerOperation); + return dmiDataOperationsOutPerDmiServiceName; + } + + private static Map getModuleSetTagPerCmHandleId( + final Collection yangModelCmHandles) { + final Map moduleSetTagPerCmHandle = new HashMap<>(yangModelCmHandles.size()); + yangModelCmHandles.forEach(yangModelCmHandle -> + moduleSetTagPerCmHandle.put(yangModelCmHandle.getId(), yangModelCmHandle.getModuleSetTag())); + return moduleSetTagPerCmHandle; + } + + /** + * Creates data operation cloud event and publish it to client topic. + * + * @param clientTopic client given topic + * @param requestId unique identifier per request + * @param cmHandleIdsPerResponseCodesPerOperation list of cm handle ids per operation with response code + */ + public static void publishErrorMessageToClientTopic(final String clientTopic, + final String requestId, + final MultiValueMap>> + cmHandleIdsPerResponseCodesPerOperation) { + if (!cmHandleIdsPerResponseCodesPerOperation.isEmpty()) { + final CloudEvent dataOperationCloudEvent = DataOperationEventCreator.createDataOperationEvent(clientTopic, + requestId, cmHandleIdsPerResponseCodesPerOperation); + final EventsPublisher eventsPublisher = CpsApplicationContext.getCpsBean(EventsPublisher.class); + log.warn("publishing error message to client topic: {} ,requestId: {}, data operation cloud event id: {}", + clientTopic, requestId, dataOperationCloudEvent.getId()); + eventsPublisher.publishCloudEvent(clientTopic, requestId, dataOperationCloudEvent); + } + } + + private static Map getDmiServiceNamesPerCmHandleId( + final Map>> dmiDmiPropertiesPerCmHandleIdPerServiceName) { + final Map dmiServiceNamesPerCmHandleId = new HashMap<>(); + for (final Map.Entry>> dmiDmiPropertiesEntry + : dmiDmiPropertiesPerCmHandleIdPerServiceName.entrySet()) { + final String dmiServiceName = dmiDmiPropertiesEntry.getKey(); + final Set cmHandleIds = dmiDmiPropertiesPerCmHandleIdPerServiceName.get(dmiServiceName).keySet(); + for (final String cmHandleId : cmHandleIds) { + dmiServiceNamesPerCmHandleId.put(cmHandleId, dmiServiceName); + } + } + dmiDmiPropertiesPerCmHandleIdPerServiceName.put(UNKNOWN_SERVICE_NAME, Collections.emptyMap()); + return dmiServiceNamesPerCmHandleId; + } + + private static DmiDataOperation getOrAddDmiBatchOperation(final String dmiServiceName, + final DataOperationDefinition + dataOperationDefinitionIn, + final Map> + dmiBatchOperationsOutPerDmiServiceName) { + dmiBatchOperationsOutPerDmiServiceName + .computeIfAbsent(dmiServiceName, dmiServiceNameAsKey -> new ArrayList<>()); + final List dmiBatchOperationsOut + = dmiBatchOperationsOutPerDmiServiceName.get(dmiServiceName); + final boolean isNewOperation = dmiBatchOperationsOut.isEmpty() + || !dmiBatchOperationsOut.get(dmiBatchOperationsOut.size() - 1).getOperationId() + .equals(dataOperationDefinitionIn.getOperationId()); + if (isNewOperation) { + final DmiDataOperation newDmiBatchOperationOut = + DmiDataOperation.buildDmiDataOperationRequestBodyWithoutCmHandles(dataOperationDefinitionIn); + dmiBatchOperationsOut.add(newDmiBatchOperationOut); + return newDmiBatchOperationOut; + } + return dmiBatchOperationsOut.get(dmiBatchOperationsOut.size() - 1); + } + + private static Set filterAndGetNonReadyCmHandleIds(final Collection yangModelCmHandles) { + return yangModelCmHandles.stream() + .filter(yangModelCmHandle -> yangModelCmHandle.getCompositeState().getCmHandleState() + != CmHandleState.READY).map(YangModelCmHandle::getId).collect(Collectors.toSet()); + } + + private static void populateCmHandleIdsPerOperationIdPerResponseCode(final MultiValueMap>> cmHandleIdsPerResponseCodesPerOperation, + final DmiDataOperation dmiDataOperation, + final NcmpResponseStatus + ncmpResponseStatus, + final List cmHandleIds) { + if (!cmHandleIds.isEmpty()) { + cmHandleIdsPerResponseCodesPerOperation.add(dmiDataOperation, Map.of(ncmpResponseStatus, cmHandleIds)); + } + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DmiSubJobRequestHandler.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DmiSubJobRequestHandler.java index 8027e69d56..25144ad974 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DmiSubJobRequestHandler.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DmiSubJobRequestHandler.java @@ -25,6 +25,7 @@ import java.util.List; import java.util.Map; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.onap.cps.ncmp.api.data.models.OperationType; import org.onap.cps.ncmp.api.datajobs.models.DataJobMetadata; import org.onap.cps.ncmp.api.datajobs.models.DmiWriteOperation; import org.onap.cps.ncmp.api.datajobs.models.ProducerKey; @@ -32,9 +33,8 @@ import org.onap.cps.ncmp.api.datajobs.models.SubJobWriteRequest; import org.onap.cps.ncmp.api.datajobs.models.SubJobWriteResponse; import org.onap.cps.ncmp.api.impl.client.DmiRestClient; import org.onap.cps.ncmp.api.impl.config.DmiProperties; -import org.onap.cps.ncmp.api.impl.operations.OperationType; -import org.onap.cps.ncmp.api.impl.operations.RequiredDmiService; import org.onap.cps.ncmp.api.impl.utils.DmiServiceUrlBuilder; +import org.onap.cps.ncmp.impl.models.RequiredDmiService; import org.onap.cps.utils.JsonObjectMapper; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/AlternateIdChecker.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/AlternateIdChecker.java new file mode 100644 index 0000000000..1096980e1d --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/AlternateIdChecker.java @@ -0,0 +1,151 @@ +/* + * ============LICENSE_START======================================================== + * Copyright (c) 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an 'AS IS' BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.impl.inventory; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle; +import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; +import org.onap.cps.spi.exceptions.DataNodeNotFoundException; +import org.springframework.stereotype.Service; + +@Service +@Slf4j +@RequiredArgsConstructor +public class AlternateIdChecker { + + public enum Operation { + CREATE, UPDATE + } + + private final InventoryPersistence inventoryPersistence; + + private static final String NO_CURRENT_ALTERNATE_ID = ""; + + /** + * Check if the alternate can be applied to the given cm handle (id). + * Conditions: + * - proposed alternate is blank (it wil be ignored) + * - proposed alternate is same as current (no change) + * - proposed alternate is not in use for a different cm handle (in the DB) + * + * @param cmHandleId cm handle id + * @param proposedAlternateId proposed alternate id + * @return true if the new alternate id not in use or equal to current alternate id, false otherwise + */ + public boolean canApplyAlternateId(final String cmHandleId, final String proposedAlternateId) { + String currentAlternateId = ""; + try { + final YangModelCmHandle yangModelCmHandle = inventoryPersistence.getYangModelCmHandle(cmHandleId); + currentAlternateId = yangModelCmHandle.getAlternateId(); + } catch (final DataNodeNotFoundException dataNodeNotFoundException) { + // work with blank current alternate id + } + return this.canApplyAlternateId(cmHandleId, currentAlternateId, proposedAlternateId); + } + + /** + * Check if the alternate can be applied to the given cm handle. + * Conditions: + * - proposed alternate is blank (it wil be ignored) + * - proposed alternate is same as current (no change) + * - proposed alternate is not in use for a different cm handle (in the DB) + * + * @param cmHandleId cm handle id + * @param currentAlternateId current alternate id + * @param proposedAlternateId new alternate id + * @return true if the new alternate id not in use or equal to current alternate id, false otherwise + */ + public boolean canApplyAlternateId(final String cmHandleId, + final String currentAlternateId, + final String proposedAlternateId) { + if (StringUtils.isBlank(currentAlternateId)) { + if (alternateIdAlreadyInDb(proposedAlternateId)) { + log.warn("Alternate id update ignored, cannot update cm handle {}, alternate id is already " + + "assigned to a different cm handle", cmHandleId); + return false; + } + return true; + } + if (currentAlternateId.equals(proposedAlternateId)) { + return true; + } + log.warn("Alternate id update ignored, cannot update cm handle {}, already has an alternate id of {}", + cmHandleId, currentAlternateId); + return false; + } + + /** + * Check all alternate ids of a batch of cm handles. + * Includes cross-checks in the batch itself for duplicates. Only the first entry encountered wil be accepted. + * + * @param newNcmpServiceCmHandles the proposed new cm handles + * @param operation type of operation being executed + * @return collection of cm handles ids which are acceptable + */ + public Collection getIdsOfCmHandlesWithRejectedAlternateId( + final Collection newNcmpServiceCmHandles, + final Operation operation) { + final Set acceptedAlternateIds = new HashSet<>(newNcmpServiceCmHandles.size()); + final Collection rejectedCmHandleIds = new ArrayList<>(); + for (final NcmpServiceCmHandle ncmpServiceCmHandle : newNcmpServiceCmHandles) { + final String cmHandleId = ncmpServiceCmHandle.getCmHandleId(); + final String proposedAlternateId = ncmpServiceCmHandle.getAlternateId(); + if (isProposedAlternateIdAcceptable(proposedAlternateId, operation, acceptedAlternateIds, cmHandleId)) { + acceptedAlternateIds.add(proposedAlternateId); + } else { + rejectedCmHandleIds.add(cmHandleId); + } + } + return rejectedCmHandleIds; + } + + private boolean isProposedAlternateIdAcceptable(final String proposedAlternateId, final Operation operation, + final Set acceptedAlternateIds, final String cmHandleId) { + if (StringUtils.isEmpty(proposedAlternateId)) { + return true; + } + if (acceptedAlternateIds.contains(proposedAlternateId)) { + log.warn("Alternate id update ignored, cannot update cm handle {}, alternate id is already " + + "assigned to a different cm handle (in this batch)", cmHandleId); + return false; + } + if (Operation.CREATE.equals(operation)) { + return canApplyAlternateId(cmHandleId, NO_CURRENT_ALTERNATE_ID, proposedAlternateId); + } + return canApplyAlternateId(cmHandleId, proposedAlternateId); + } + + private boolean alternateIdAlreadyInDb(final String alternateId) { + try { + inventoryPersistence.getCmHandleDataNodeByAlternateId(alternateId); + } catch (final DataNodeNotFoundException dataNodeNotFoundException) { + return false; + } + return true; + } + +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationService.java index 78feca56f4..d6ddd108ea 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationService.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationService.java @@ -47,7 +47,6 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.onap.cps.api.CpsDataService; -import org.onap.cps.ncmp.api.impl.utils.AlternateIdChecker; import org.onap.cps.ncmp.api.inventory.models.CmHandleRegistrationResponse; import org.onap.cps.ncmp.api.inventory.models.CompositeState; import org.onap.cps.ncmp.api.inventory.models.CompositeStateBuilder; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServicePropertyHandler.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServicePropertyHandler.java index fe47c0e2f2..c9981dba9a 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServicePropertyHandler.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServicePropertyHandler.java @@ -45,7 +45,6 @@ import java.util.regex.Pattern; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.onap.cps.api.CpsDataService; -import org.onap.cps.ncmp.api.impl.utils.AlternateIdChecker; import org.onap.cps.ncmp.api.inventory.models.CmHandleRegistrationResponse; import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle; import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/YangModelCmHandle.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/YangModelCmHandle.java index d96c9c7206..b10155c4a9 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/YangModelCmHandle.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/YangModelCmHandle.java @@ -34,9 +34,9 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import org.apache.commons.lang3.StringUtils; -import org.onap.cps.ncmp.api.impl.operations.RequiredDmiService; import org.onap.cps.ncmp.api.inventory.models.CompositeState; import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle; +import org.onap.cps.ncmp.impl.models.RequiredDmiService; /** * Cm Handle which follows the Yang resource dmi registry model when persisting data to DMI or the DB. diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperations.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperations.java new file mode 100644 index 0000000000..6a49360b9d --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperations.java @@ -0,0 +1,186 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021-2024 Nordix Foundation + * Modifications Copyright (C) 2022 Bell Canada + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.impl.inventory.sync; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import lombok.RequiredArgsConstructor; +import org.onap.cps.ncmp.api.data.models.OperationType; +import org.onap.cps.ncmp.api.impl.client.DmiRestClient; +import org.onap.cps.ncmp.api.impl.config.DmiProperties; +import org.onap.cps.ncmp.api.impl.utils.DmiServiceUrlBuilder; +import org.onap.cps.ncmp.api.inventory.models.YangResource; +import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; +import org.onap.cps.ncmp.impl.models.DmiRequestBody; +import org.onap.cps.ncmp.impl.models.RequiredDmiService; +import org.onap.cps.spi.model.ModuleReference; +import org.onap.cps.utils.JsonObjectMapper; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; + +/** + * Operations class for DMI Model. + */ +@RequiredArgsConstructor +@Service +public class DmiModelOperations { + + private final JsonObjectMapper jsonObjectMapper; + private final DmiProperties dmiProperties; + private final DmiRestClient dmiRestClient; + + /** + * Retrieves module references. + * + * @param yangModelCmHandle the yang model cm handle + * @return module references + */ + public List getModuleReferences(final YangModelCmHandle yangModelCmHandle) { + final DmiRequestBody dmiRequestBody = DmiRequestBody.builder() + .moduleSetTag(yangModelCmHandle.getModuleSetTag()).build(); + dmiRequestBody.asDmiProperties(yangModelCmHandle.getDmiProperties()); + final ResponseEntity dmiFetchModulesResponseEntity = getResourceFromDmiWithJsonData( + yangModelCmHandle.resolveDmiServiceName(RequiredDmiService.MODEL), + jsonObjectMapper.asJsonString(dmiRequestBody), yangModelCmHandle.getId(), "modules"); + return toModuleReferences((Map) dmiFetchModulesResponseEntity.getBody()); + } + + /** + * Retrieve yang resources from dmi for any modules that CPS-NCMP hasn't cached before. + * + * @param yangModelCmHandle the yangModelCmHandle + * @param newModuleReferences the unknown module references + * @return yang resources as map of module name to yang(re)source + */ + public Map getNewYangResourcesFromDmi(final YangModelCmHandle yangModelCmHandle, + final Collection newModuleReferences) { + if (newModuleReferences.isEmpty()) { + return Collections.emptyMap(); + } + final String jsonWithDataAndDmiProperties = getRequestBodyToFetchYangResources(newModuleReferences, + yangModelCmHandle.getDmiProperties(), yangModelCmHandle.getModuleSetTag()); + final ResponseEntity responseEntity = getResourceFromDmiWithJsonData( + yangModelCmHandle.resolveDmiServiceName(RequiredDmiService.MODEL), + jsonWithDataAndDmiProperties, + yangModelCmHandle.getId(), + "moduleResources"); + return asModuleNameToYangResourceMap(responseEntity); + } + + /** + * Get resources from DMI for modules. + * + * @param dmiServiceName dmi service name + * @param jsonRequestBody module names and revisions as JSON + * @param cmHandle cmHandle + * @param resourceName name of the resource(s) + * @return {@code ResponseEntity} response entity + */ + private ResponseEntity getResourceFromDmiWithJsonData(final String dmiServiceName, + final String jsonRequestBody, + final String cmHandle, + final String resourceName) { + final String dmiUrl = DmiServiceUrlBuilder.newInstance() + .pathSegment("ch") + .variablePathSegment("cmHandleId", cmHandle) + .variablePathSegment("resourceName", resourceName) + .build(dmiServiceName, dmiProperties.getDmiBasePath()); + return dmiRestClient.synchronousPostOperationWithJsonData(RequiredDmiService.MODEL, dmiUrl, jsonRequestBody, + OperationType.READ, null); + } + + private static String getRequestBodyToFetchYangResources(final Collection newModuleReferences, + final List dmiProperties, + final String moduleSetTag) { + final JsonArray moduleReferencesAsJson = getModuleReferencesAsJson(newModuleReferences); + final JsonObject data = new JsonObject(); + data.add("modules", moduleReferencesAsJson); + final JsonObject jsonRequestObject = new JsonObject(); + if (!moduleSetTag.isEmpty()) { + final JsonElement moduleSetTagAsJson = JsonParser.parseString(moduleSetTag); + jsonRequestObject.add("moduleSetTag", moduleSetTagAsJson); + } + jsonRequestObject.add("data", data); + jsonRequestObject.add("cmHandleProperties", toJsonObject(dmiProperties)); + return jsonRequestObject.toString(); + } + + private static JsonArray getModuleReferencesAsJson(final Collection unknownModuleReferences) { + final JsonArray moduleReferences = new JsonArray(); + + for (final ModuleReference moduleReference : unknownModuleReferences) { + final JsonObject moduleReferenceAsJson = new JsonObject(); + moduleReferenceAsJson.addProperty("name", moduleReference.getModuleName()); + moduleReferenceAsJson.addProperty("revision", moduleReference.getRevision()); + moduleReferences.add(moduleReferenceAsJson); + } + return moduleReferences; + } + + private static JsonObject toJsonObject(final List + dmiProperties) { + final JsonObject asJsonObject = new JsonObject(); + for (final YangModelCmHandle.Property additionalProperty : dmiProperties) { + asJsonObject.addProperty(additionalProperty.getName(), additionalProperty.getValue()); + } + return asJsonObject; + } + + private List toModuleReferences(final Map dmiFetchModulesResponseAsMap) { + final List moduleReferences = new ArrayList<>(); + + if (dmiFetchModulesResponseAsMap != null) { + final List moduleReferencesAsList = (List) dmiFetchModulesResponseAsMap.get("schemas"); + if (moduleReferencesAsList != null) { + moduleReferencesAsList.forEach(moduleReferenceAsMap -> { + final ModuleReference moduleReference = + jsonObjectMapper.convertToValueType(moduleReferenceAsMap, ModuleReference.class); + moduleReferences.add(moduleReference); + }); + } + } + return moduleReferences; + } + + private Map asModuleNameToYangResourceMap(final ResponseEntity responseEntity) { + final Map yangResourcesModuleNameToContentMap = new HashMap<>(); + final List> yangResourcesAsList = (List) responseEntity.getBody(); + + if (yangResourcesAsList != null) { + yangResourcesAsList.forEach(yangResourceAsMap -> { + final YangResource yangResource = + jsonObjectMapper.convertToValueType(yangResourceAsMap, YangResource.class); + yangResourcesModuleNameToContentMap.put(yangResource.getModuleName(), + yangResource.getYangSource()); + }); + } + return yangResourcesModuleNameToContentMap; + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleOperationsUtils.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleOperationsUtils.java index e344be8e1f..69fb7f59f5 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleOperationsUtils.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleOperationsUtils.java @@ -36,8 +36,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations; import org.onap.cps.ncmp.api.inventory.models.CompositeState; +import org.onap.cps.ncmp.impl.data.DmiDataOperations; import org.onap.cps.ncmp.impl.inventory.CmHandleQueryService; import org.onap.cps.ncmp.impl.inventory.DataStoreSyncState; import org.onap.cps.ncmp.impl.inventory.models.CmHandleState; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncService.java index 57d28aa743..d2bc3ada86 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncService.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncService.java @@ -38,7 +38,6 @@ import org.apache.commons.lang3.StringUtils; import org.onap.cps.api.CpsAnchorService; import org.onap.cps.api.CpsDataService; import org.onap.cps.api.CpsModuleService; -import org.onap.cps.ncmp.api.impl.operations.DmiModelOperations; import org.onap.cps.ncmp.impl.inventory.CmHandleQueryService; import org.onap.cps.ncmp.impl.inventory.models.CmHandleState; import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManager.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManager.java index 22311c6b5a..44079c0bc9 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManager.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManager.java @@ -24,10 +24,10 @@ import java.util.Collection; import java.util.Map; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.onap.cps.ncmp.api.impl.operations.RequiredDmiService; import org.onap.cps.ncmp.api.inventory.models.TrustLevel; import org.onap.cps.ncmp.impl.inventory.InventoryPersistence; import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; +import org.onap.cps.ncmp.impl.models.RequiredDmiService; import org.onap.cps.ncmp.utils.events.CmAvcEventPublisher; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/models/DmiRequestBody.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/models/DmiRequestBody.java new file mode 100644 index 0000000000..6b05385693 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/models/DmiRequestBody.java @@ -0,0 +1,62 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021-2023 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.impl.models; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import lombok.Builder; +import lombok.Getter; +import org.onap.cps.ncmp.api.data.models.OperationType; +import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@Getter +@Builder +@JsonPropertyOrder({"operation", "dataType", "data", "cmHandleProperties", "requestId", "moduleSetTag"}) +public class DmiRequestBody { + + @JsonProperty("operation") + private OperationType operationType; + private String dataType; + private String data; + @JsonProperty("cmHandleProperties") + private Map dmiProperties; + private String requestId; + private String moduleSetTag; + + /** + * Set DMI Properties by converting a list of YangModelCmHandle.Property objects. + * + * @param yangModelCmHandleProperties list of cm handle dmi properties + */ + public void asDmiProperties( + final List yangModelCmHandleProperties) { + dmiProperties = new LinkedHashMap<>(); + for (final YangModelCmHandle.Property dmiProperty : yangModelCmHandleProperties) { + dmiProperties.put(dmiProperty.getName(), dmiProperty.getValue()); + } + } + +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/models/RequiredDmiService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/models/RequiredDmiService.java new file mode 100644 index 0000000000..c0c4f73f2a --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/models/RequiredDmiService.java @@ -0,0 +1,28 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.impl.models; + +/** + * Enmm to determine if the required service is for a data or model operation. + */ +public enum RequiredDmiService { + DATA, MODEL +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/CmDataSubscriptionModelLoader.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/CmDataSubscriptionModelLoader.java index 130defb306..2592703449 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/CmDataSubscriptionModelLoader.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/CmDataSubscriptionModelLoader.java @@ -29,8 +29,8 @@ import org.onap.cps.api.CpsAnchorService; import org.onap.cps.api.CpsDataService; import org.onap.cps.api.CpsDataspaceService; import org.onap.cps.api.CpsModuleService; +import org.onap.cps.ncmp.api.data.models.DatastoreType; import org.onap.cps.ncmp.api.impl.exception.NcmpStartUpException; -import org.onap.cps.ncmp.api.impl.operations.DatastoreType; import org.onap.cps.spi.exceptions.AlreadyDefinedException; import org.springframework.stereotype.Service; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/CmAvcEventPublisher.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/CmAvcEventPublisher.java index 2a9717cc1a..06269d5177 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/CmAvcEventPublisher.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/CmAvcEventPublisher.java @@ -29,6 +29,7 @@ import org.onap.cps.events.EventsPublisher; import org.onap.cps.ncmp.events.avc.ncmp_to_client.Avc; import org.onap.cps.ncmp.events.avc.ncmp_to_client.AvcEvent; import org.onap.cps.ncmp.events.avc.ncmp_to_client.Data; +import org.onap.cps.ncmp.utils.events.NcmpEvent; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; -- cgit