From 37d82d5d54ede4c05862fe648911c383d253cec3 Mon Sep 17 00:00:00 2001 From: ToineSiebelink Date: Mon, 24 Jun 2024 13:24:57 +0100 Subject: Repackage Inventory Feature - decided that cm handle queries is part of 'inventory' feature - a lot of files (~100 total) have changes because of some files have been moved. - The reviewers should probably just focus on the MOVED/renamed (~30) files - New packages (top level only): -- org.onap.cps.ncmp.api.inventory -- org.onap.cps.ncmp.impl.inventory -- org.onap.cps.ncmp.impl.models (common models NOT used in API, this was unforeseen) -- org.onap.cps.ncmp.impl.utils - I am NOT updating copyright years as part of this commit since there are no real code changes and it is simply NOT worth the effort TODO: - extend scope to 'TrustLevel' as an 'internal feature' (TBD) Issue-ID: CPS-2255 Signed-off-by: ToineSiebelink Change-Id: I40b4efc8326068ab9ae1f31b77f46b2fe8579431 --- .../api/ParameterizedCmHandleQueryService.java | 72 ---- .../ncmp/api/impl/CmHandleRegistrationService.java | 404 --------------------- ...CmHandleRegistrationServicePropertyHandler.java | 246 ------------- .../api/impl/NetworkCmProxyInventoryFacade.java | 207 ----------- .../api/impl/NetworkCmProxyQueryServiceImpl.java | 2 +- .../ParameterizedCmHandleQueryServiceImpl.java | 286 --------------- .../embeddedcache/SynchronizationCacheConfig.java | 77 ---- .../DmiCmNotificationSubscriptionCacheHandler.java | 6 +- ...CmNotificationSubscriptionDmiInEventMapper.java | 2 +- .../events/lcm/LcmEventsCmHandleStateHandler.java | 4 +- .../LcmEventsCmHandleStateHandlerAsyncHelper.java | 6 +- .../lcm/LcmEventsCmHandleStateHandlerImpl.java | 22 +- .../ncmp/api/impl/events/lcm/LcmEventsCreator.java | 4 +- .../impl/events/lcm/LcmEventsCreatorHelper.java | 4 +- .../api/impl/inventory/CmHandleQueryService.java | 105 ------ .../impl/inventory/CmHandleQueryServiceImpl.java | 192 ---------- .../cps/ncmp/api/impl/inventory/CmHandleState.java | 25 -- .../ncmp/api/impl/inventory/CompositeState.java | 144 -------- .../api/impl/inventory/CompositeStateBuilder.java | 154 -------- .../api/impl/inventory/CompositeStateUtils.java | 96 ----- .../api/impl/inventory/DataStoreSyncState.java | 25 -- .../api/impl/inventory/InventoryPersistence.java | 147 -------- .../impl/inventory/InventoryPersistenceImpl.java | 210 ----------- .../api/impl/inventory/LockReasonCategory.java | 28 -- .../impl/inventory/ModelledDmiServiceLeaves.java | 38 -- .../api/impl/inventory/NcmpPersistenceImpl.java | 120 ------ .../api/impl/inventory/enums/PropertyType.java | 34 -- .../api/impl/inventory/sync/DataSyncWatchdog.java | 102 ------ .../impl/inventory/sync/ModuleOperationsUtils.java | 262 ------------- .../api/impl/inventory/sync/ModuleSyncService.java | 153 -------- .../api/impl/inventory/sync/ModuleSyncTasks.java | 131 ------- .../impl/inventory/sync/ModuleSyncWatchdog.java | 140 ------- .../sync/config/WatchdogSchedulingConfigurer.java | 56 --- .../inventory/sync/executor/AsyncTaskExecutor.java | 77 ---- .../api/impl/ncmppersistence/NcmpPersistence.java | 116 ------ .../api/impl/operations/DmiDataOperations.java | 6 +- .../api/impl/operations/DmiModelOperations.java | 4 +- .../ncmp/api/impl/operations/DmiRequestBody.java | 2 +- .../api/impl/trustlevel/TrustLevelManager.java | 4 +- .../dmiavailability/DmiPluginWatchDog.java | 2 +- .../ncmp/api/impl/utils/AlternateIdChecker.java | 6 +- .../api/impl/utils/CmHandleQueryConditions.java | 43 --- .../api/impl/utils/DmiServiceNameOrganizer.java | 2 +- .../api/impl/utils/InventoryQueryConditions.java | 42 --- .../impl/utils/RestQueryParametersValidator.java | 125 ------- .../cps/ncmp/api/impl/utils/YangDataConverter.java | 159 -------- .../ResourceDataOperationRequestUtils.java | 4 +- .../api/impl/yangmodels/YangModelCmHandle.java | 175 --------- .../inventory/NetworkCmProxyInventoryFacade.java | 208 +++++++++++ .../models/CmHandleQueryApiParameters.java | 43 +++ .../models/CmHandleQueryServiceParameters.java | 42 +++ .../models/CmHandleRegistrationResponse.java | 147 ++++++++ .../ncmp/api/inventory/models/CompositeState.java | 147 ++++++++ .../inventory/models/CompositeStateBuilder.java | 157 ++++++++ .../inventory/models/ConditionApiProperties.java | 44 +++ .../inventory/models/DmiPluginRegistration.java | 89 +++++ .../models/DmiPluginRegistrationResponse.java | 36 ++ .../api/inventory/models/NcmpServiceCmHandle.java | 65 ++++ .../api/inventory/models/UpgradedCmHandles.java | 36 ++ .../ncmp/api/inventory/models/YangResource.java | 34 ++ .../api/models/CmHandleQueryApiParameters.java | 43 --- .../api/models/CmHandleQueryServiceParameters.java | 42 --- .../api/models/CmHandleRegistrationResponse.java | 147 -------- .../ncmp/api/models/ConditionApiProperties.java | 44 --- .../cps/ncmp/api/models/DmiPluginRegistration.java | 89 ----- .../api/models/DmiPluginRegistrationResponse.java | 36 -- .../cps/ncmp/api/models/NcmpServiceCmHandle.java | 66 ---- .../cps/ncmp/api/models/UpgradedCmHandles.java | 36 -- .../org/onap/cps/ncmp/api/models/YangResource.java | 34 -- .../ncmp/impl/datajobs/WriteRequestExaminer.java | 8 +- .../CmHandleQueryParametersValidator.java | 125 +++++++ .../ncmp/impl/inventory/CmHandleQueryService.java | 106 ++++++ .../impl/inventory/CmHandleQueryServiceImpl.java | 194 ++++++++++ .../inventory/CmHandleRegistrationService.java | 401 ++++++++++++++++++++ ...CmHandleRegistrationServicePropertyHandler.java | 245 +++++++++++++ .../ncmp/impl/inventory/CompositeStateUtils.java | 98 +++++ .../ncmp/impl/inventory/DataStoreSyncState.java | 25 ++ .../ncmp/impl/inventory/InventoryPersistence.java | 147 ++++++++ .../impl/inventory/InventoryPersistenceImpl.java | 212 +++++++++++ .../cps/ncmp/impl/inventory/NcmpPersistence.java | 116 ++++++ .../ncmp/impl/inventory/NcmpPersistenceImpl.java | 119 ++++++ .../ParameterizedCmHandleQueryService.java | 72 ++++ .../ParameterizedCmHandleQueryServiceImpl.java | 283 +++++++++++++++ .../inventory/models/CmHandleQueryConditions.java | 43 +++ .../ncmp/impl/inventory/models/CmHandleState.java | 25 ++ .../inventory/models/InventoryQueryConditions.java | 42 +++ .../impl/inventory/models/LockReasonCategory.java | 28 ++ .../inventory/models/ModelledDmiServiceLeaves.java | 38 ++ .../ncmp/impl/inventory/models/PropertyType.java | 34 ++ .../impl/inventory/models/YangModelCmHandle.java | 175 +++++++++ .../impl/inventory/sync/AsyncTaskExecutor.java | 77 ++++ .../ncmp/impl/inventory/sync/DataSyncWatchdog.java | 101 ++++++ .../impl/inventory/sync/ModuleOperationsUtils.java | 262 +++++++++++++ .../impl/inventory/sync/ModuleSyncService.java | 153 ++++++++ .../ncmp/impl/inventory/sync/ModuleSyncTasks.java | 131 +++++++ .../impl/inventory/sync/ModuleSyncWatchdog.java | 138 +++++++ .../inventory/sync/SynchronizationCacheConfig.java | 77 ++++ .../sync/WatchdogSchedulingConfigurer.java | 56 +++ .../cps/ncmp/impl/utils/AlternateIdMatcher.java | 63 ++++ .../cps/ncmp/impl/utils/YangDataConverter.java | 159 ++++++++ .../ncmp/init/CmDataSubscriptionModelLoader.java | 2 +- .../onap/cps/ncmp/init/InventoryModelLoader.java | 6 +- .../onap/cps/ncmp/utils/AlternateIdMatcher.java | 63 ---- 103 files changed, 4841 insertions(+), 4839 deletions(-) delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/ParameterizedCmHandleQueryService.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/CmHandleRegistrationService.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/CmHandleRegistrationServicePropertyHandler.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyInventoryFacade.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/ParameterizedCmHandleQueryServiceImpl.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/embeddedcache/SynchronizationCacheConfig.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueryService.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueryServiceImpl.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleState.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeState.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeStateBuilder.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeStateUtils.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/DataStoreSyncState.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/InventoryPersistence.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/InventoryPersistenceImpl.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/LockReasonCategory.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/ModelledDmiServiceLeaves.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/NcmpPersistenceImpl.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/enums/PropertyType.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/DataSyncWatchdog.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleOperationsUtils.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncService.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncTasks.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncWatchdog.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/config/WatchdogSchedulingConfigurer.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/executor/AsyncTaskExecutor.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/ncmppersistence/NcmpPersistence.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/CmHandleQueryConditions.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/InventoryQueryConditions.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/RestQueryParametersValidator.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/YangDataConverter.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandle.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/NetworkCmProxyInventoryFacade.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CmHandleQueryApiParameters.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CmHandleQueryServiceParameters.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CmHandleRegistrationResponse.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CompositeState.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CompositeStateBuilder.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/ConditionApiProperties.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/DmiPluginRegistration.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/DmiPluginRegistrationResponse.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/NcmpServiceCmHandle.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/UpgradedCmHandles.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/YangResource.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandleQueryApiParameters.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandleQueryServiceParameters.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandleRegistrationResponse.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/ConditionApiProperties.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DmiPluginRegistration.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DmiPluginRegistrationResponse.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/NcmpServiceCmHandle.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/UpgradedCmHandles.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/YangResource.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryParametersValidator.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryService.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImpl.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationService.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServicePropertyHandler.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CompositeStateUtils.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/DataStoreSyncState.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistence.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImpl.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/NcmpPersistence.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/NcmpPersistenceImpl.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryService.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryServiceImpl.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/CmHandleQueryConditions.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/CmHandleState.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/InventoryQueryConditions.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/LockReasonCategory.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/ModelledDmiServiceLeaves.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/PropertyType.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/YangModelCmHandle.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/AsyncTaskExecutor.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DataSyncWatchdog.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleOperationsUtils.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncService.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncTasks.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncWatchdog.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/SynchronizationCacheConfig.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/WatchdogSchedulingConfigurer.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/AlternateIdMatcher.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/YangDataConverter.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/AlternateIdMatcher.java (limited to 'cps-ncmp-service/src/main/java/org/onap') diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/ParameterizedCmHandleQueryService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/ParameterizedCmHandleQueryService.java deleted file mode 100644 index a9ade24c72..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/ParameterizedCmHandleQueryService.java +++ /dev/null @@ -1,72 +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.ncmp.api.models.CmHandleQueryServiceParameters; -import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; - -public interface ParameterizedCmHandleQueryService { - /** - * Query and return cm handle ids that match the given query parameters. - * Supported query types: - * public properties - * modules - * cps-path - * - * @param cmHandleQueryServiceParameters the cm handle query parameters - * @return collection of cm handle ids - */ - Collection queryCmHandleIds(CmHandleQueryServiceParameters cmHandleQueryServiceParameters); - - /** - * Query and return cm handle ids that match the given query parameters. - * Supported query types: - * public properties - * private (additional) properties - * dmi-names - * The inventory interface also allows conditions on private (additional) properties and dmi names - * - * @param cmHandleQueryServiceParameters the cm handle query parameters - * @return collection of cm handle ids - */ - Collection queryCmHandleIdsForInventory(CmHandleQueryServiceParameters cmHandleQueryServiceParameters); - - /** - * Query and return cm handle objects that match the given query parameters. - * Supported query types: - * public properties - * modules - * cps-path - * - * @param cmHandleQueryServiceParameters the cm handle query parameters - * @return collection of cm handles - */ - Collection queryCmHandles(CmHandleQueryServiceParameters cmHandleQueryServiceParameters); - - /** - * Get all cm handle objects. - * Note: it is similar to all the queries above but simply no conditions and hence not 'parameterized' - * - * @return collection of cm handles - */ - Collection getAllCmHandles(); -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/CmHandleRegistrationService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/CmHandleRegistrationService.java deleted file mode 100644 index 6f78e6cb34..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/CmHandleRegistrationService.java +++ /dev/null @@ -1,404 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * 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.NcmpResponseStatus.ALTERNATE_ID_ALREADY_ASSOCIATED; -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 static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLE_ALREADY_EXIST; -import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLE_INVALID_ID; -import static org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory.MODULE_UPGRADE; -import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT; -import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME; - -import com.google.common.collect.Lists; -import com.hazelcast.map.IMap; -import java.time.OffsetDateTime; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; -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.config.embeddedcache.TrustLevelCacheConfig; -import org.onap.cps.ncmp.api.impl.events.lcm.LcmEventsCmHandleStateHandler; -import org.onap.cps.ncmp.api.impl.inventory.CmHandleState; -import org.onap.cps.ncmp.api.impl.inventory.CompositeState; -import org.onap.cps.ncmp.api.impl.inventory.CompositeStateBuilder; -import org.onap.cps.ncmp.api.impl.inventory.CompositeStateUtils; -import org.onap.cps.ncmp.api.impl.inventory.DataStoreSyncState; -import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence; -import org.onap.cps.ncmp.api.impl.inventory.sync.ModuleOperationsUtils; -import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevel; -import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevelManager; -import org.onap.cps.ncmp.api.impl.utils.AlternateIdChecker; -import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse; -import org.onap.cps.ncmp.api.models.DmiPluginRegistration; -import org.onap.cps.ncmp.api.models.DmiPluginRegistrationResponse; -import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; -import org.onap.cps.spi.exceptions.AlreadyDefinedException; -import org.onap.cps.spi.exceptions.CpsException; -import org.onap.cps.spi.exceptions.DataNodeNotFoundException; -import org.onap.cps.spi.exceptions.DataValidationException; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.stereotype.Service; - -@Slf4j -@Service -@RequiredArgsConstructor -public class CmHandleRegistrationService { - - private static final int DELETE_BATCH_SIZE = 100; - - private final CmHandleRegistrationServicePropertyHandler cmHandleRegistrationServicePropertyHandler; - private final InventoryPersistence inventoryPersistence; - private final CpsDataService cpsDataService; - private final LcmEventsCmHandleStateHandler lcmEventsCmHandleStateHandler; - private final IMap moduleSyncStartedOnCmHandles; - - @Qualifier(TrustLevelCacheConfig.TRUST_LEVEL_PER_DMI_PLUGIN) - private final Map trustLevelPerDmiPlugin; - private final TrustLevelManager trustLevelManager; - - private final AlternateIdChecker alternateIdChecker; - - /** - * Registration of Created, Removed, Updated or Upgraded CM Handles. - * - * @param dmiPluginRegistration Dmi Plugin Registration details - * @return dmiPluginRegistrationResponse - */ - public DmiPluginRegistrationResponse updateDmiRegistrationAndSyncModule( - final DmiPluginRegistration dmiPluginRegistration) { - - dmiPluginRegistration.validateDmiPluginRegistration(); - final DmiPluginRegistrationResponse dmiPluginRegistrationResponse = new DmiPluginRegistrationResponse(); - - setTrustLevelPerDmiPlugin(dmiPluginRegistration); - - processRemovedCmHandles(dmiPluginRegistration, dmiPluginRegistrationResponse); - - processCreatedCmHandles(dmiPluginRegistration, dmiPluginRegistrationResponse); - - processUpdatedCmHandles(dmiPluginRegistration, dmiPluginRegistrationResponse); - - processUpgradedCmHandles(dmiPluginRegistration, dmiPluginRegistrationResponse); - - return dmiPluginRegistrationResponse; - } - - /** - * Set the data sync enabled flag, along with the data sync state - * based on the data sync enabled boolean for the cm handle id provided. - * - * @param cmHandleId cm handle id - * @param dataSyncEnabledTargetValue data sync enabled flag - */ - public void setDataSyncEnabled(final String cmHandleId, final Boolean dataSyncEnabledTargetValue) { - final CompositeState compositeState = inventoryPersistence.getCmHandleState(cmHandleId); - if (dataSyncEnabledTargetValue.equals(compositeState.getDataSyncEnabled())) { - log.info("Data-Sync Enabled flag is already: {} ", dataSyncEnabledTargetValue); - return; - } - if (CmHandleState.READY.equals(compositeState.getCmHandleState())) { - final DataStoreSyncState dataStoreSyncState = compositeState.getDataStores() - .getOperationalDataStore().getDataStoreSyncState(); - if (Boolean.FALSE.equals(dataSyncEnabledTargetValue) - && DataStoreSyncState.SYNCHRONIZED.equals(dataStoreSyncState)) { - // TODO : This is hard-coded for onap dmi that need to be addressed - cpsDataService.deleteDataNode(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId, - "/netconf-state", OffsetDateTime.now()); - } - CompositeStateUtils.setDataSyncEnabledFlagWithDataSyncState(dataSyncEnabledTargetValue, compositeState); - inventoryPersistence.saveCmHandleState(cmHandleId, compositeState); - } else { - throw new CpsException("State mismatch exception.", "Cm-Handle not in READY state. Cm handle state is: " - + compositeState.getCmHandleState()); - } - } - - protected void processRemovedCmHandles(final DmiPluginRegistration dmiPluginRegistration, - final DmiPluginRegistrationResponse dmiPluginRegistrationResponse) { - final List tobeRemovedCmHandleIds = dmiPluginRegistration.getRemovedCmHandles(); - final List cmHandleRegistrationResponses = - new ArrayList<>(tobeRemovedCmHandleIds.size()); - final Collection yangModelCmHandles = - inventoryPersistence.getYangModelCmHandles(tobeRemovedCmHandleIds); - updateCmHandleStateBatch(yangModelCmHandles, CmHandleState.DELETING); - - final Set notDeletedCmHandles = new HashSet<>(); - for (final List tobeRemovedCmHandleBatch : Lists.partition(tobeRemovedCmHandleIds, DELETE_BATCH_SIZE)) { - try { - batchDeleteCmHandlesFromDbAndModuleSyncMap(tobeRemovedCmHandleBatch); - tobeRemovedCmHandleBatch.forEach(cmHandleId -> - cmHandleRegistrationResponses.add(CmHandleRegistrationResponse.createSuccessResponse(cmHandleId))); - - } catch (final RuntimeException batchException) { - log.error("Unable to de-register cm-handle batch, retrying on each cm handle"); - for (final String cmHandleId : tobeRemovedCmHandleBatch) { - final CmHandleRegistrationResponse cmHandleRegistrationResponse = - deleteCmHandleAndGetCmHandleRegistrationResponse(cmHandleId); - cmHandleRegistrationResponses.add(cmHandleRegistrationResponse); - if (cmHandleRegistrationResponse.getStatus() != CmHandleRegistrationResponse.Status.SUCCESS) { - notDeletedCmHandles.add(cmHandleId); - } - } - } - } - yangModelCmHandles.removeIf(yangModelCmHandle -> notDeletedCmHandles.contains(yangModelCmHandle.getId())); - updateCmHandleStateBatch(yangModelCmHandles, CmHandleState.DELETED); - dmiPluginRegistrationResponse.setRemovedCmHandles(cmHandleRegistrationResponses); - } - - protected void processCreatedCmHandles(final DmiPluginRegistration dmiPluginRegistration, - final DmiPluginRegistrationResponse dmiPluginRegistrationResponse) { - final List ncmpServiceCmHandles = dmiPluginRegistration.getCreatedCmHandles(); - final List failedCmHandleRegistrationResponses = new ArrayList<>(); - - try { - final Collection rejectedCmHandleIds - = checkAlternateIds(ncmpServiceCmHandles, failedCmHandleRegistrationResponses); - - final Collection succeededCmHandleIds = persistCmHandlesWithState(dmiPluginRegistration, - dmiPluginRegistrationResponse, ncmpServiceCmHandles, rejectedCmHandleIds); - - processTrustLevels(ncmpServiceCmHandles, succeededCmHandleIds); - - } catch (final AlreadyDefinedException alreadyDefinedException) { - failedCmHandleRegistrationResponses.addAll(CmHandleRegistrationResponse.createFailureResponsesFromXpaths( - alreadyDefinedException.getAlreadyDefinedObjectNames(), CM_HANDLE_ALREADY_EXIST)); - } catch (final Exception exception) { - final Collection cmHandleIds = - ncmpServiceCmHandles.stream().map(NcmpServiceCmHandle::getCmHandleId).collect(Collectors.toList()); - failedCmHandleRegistrationResponses.addAll(CmHandleRegistrationResponse - .createFailureResponses(cmHandleIds, exception)); - } - final List mergedCmHandleRegistrationResponses - = new ArrayList<>(failedCmHandleRegistrationResponses); - mergedCmHandleRegistrationResponses.addAll(dmiPluginRegistrationResponse.getCreatedCmHandles()); - - dmiPluginRegistrationResponse.setCreatedCmHandles(mergedCmHandleRegistrationResponses); - } - - protected void processUpdatedCmHandles(final DmiPluginRegistration dmiPluginRegistration, - final DmiPluginRegistrationResponse dmiPluginRegistrationResponse) { - dmiPluginRegistrationResponse.setUpdatedCmHandles(cmHandleRegistrationServicePropertyHandler - .updateCmHandleProperties(dmiPluginRegistration.getUpdatedCmHandles())); - } - - protected void processUpgradedCmHandles( - final DmiPluginRegistration dmiPluginRegistration, - final DmiPluginRegistrationResponse dmiPluginRegistrationResponse) { - - final List cmHandleIds = dmiPluginRegistration.getUpgradedCmHandles().getCmHandles(); - final String upgradedModuleSetTag = dmiPluginRegistration.getUpgradedCmHandles().getModuleSetTag(); - final Map acceptedCmHandleStatePerCmHandle - = new HashMap<>(cmHandleIds.size()); - final List cmHandleUpgradeResponses = new ArrayList<>(cmHandleIds.size()); - - for (final String cmHandleId : cmHandleIds) { - try { - final YangModelCmHandle yangModelCmHandle = inventoryPersistence.getYangModelCmHandle(cmHandleId); - if (yangModelCmHandle.getCompositeState().getCmHandleState() == CmHandleState.READY) { - if (moduleUpgradeCanBeSkipped(yangModelCmHandle, upgradedModuleSetTag)) { - cmHandleUpgradeResponses.add(CmHandleRegistrationResponse.createSuccessResponse(cmHandleId)); - } else { - updateYangModelCmHandleForUpgrade(yangModelCmHandle, upgradedModuleSetTag); - acceptedCmHandleStatePerCmHandle.put(yangModelCmHandle, CmHandleState.LOCKED); - } - } else { - cmHandleUpgradeResponses.add( - CmHandleRegistrationResponse.createFailureResponse(cmHandleId, CM_HANDLES_NOT_READY)); - } - } catch (final DataNodeNotFoundException dataNodeNotFoundException) { - log.error("Unable to find data node for cm handle id : {} , caused by : {}", - cmHandleId, dataNodeNotFoundException.getMessage()); - cmHandleUpgradeResponses.add( - CmHandleRegistrationResponse.createFailureResponse(cmHandleId, CM_HANDLES_NOT_FOUND)); - } catch (final DataValidationException dataValidationException) { - log.error("Unable to upgrade cm handle id: {}, caused by : {}", - cmHandleId, dataValidationException.getMessage()); - cmHandleUpgradeResponses.add( - CmHandleRegistrationResponse.createFailureResponse(cmHandleId, CM_HANDLE_INVALID_ID)); - } - } - cmHandleUpgradeResponses.addAll(upgradeCmHandles(acceptedCmHandleStatePerCmHandle)); - dmiPluginRegistrationResponse.setUpgradedCmHandles(cmHandleUpgradeResponses); - } - - private void processTrustLevels(final Collection cmHandlesToBeCreated, - final Collection succeededCmHandleIds) { - final Map initialTrustLevelPerCmHandleId = new HashMap<>(cmHandlesToBeCreated.size()); - for (final NcmpServiceCmHandle ncmpServiceCmHandle: cmHandlesToBeCreated) { - if (succeededCmHandleIds.contains(ncmpServiceCmHandle.getCmHandleId())) { - initialTrustLevelPerCmHandleId.put(ncmpServiceCmHandle.getCmHandleId(), - ncmpServiceCmHandle.getRegistrationTrustLevel()); - } - } - trustLevelManager.handleInitialRegistrationOfTrustLevels(initialTrustLevelPerCmHandleId); - } - - private static boolean moduleUpgradeCanBeSkipped(final YangModelCmHandle yangModelCmHandle, - final String upgradedModuleSetTag) { - if (StringUtils.isBlank(upgradedModuleSetTag)) { - return false; - } - return yangModelCmHandle.getModuleSetTag().equals(upgradedModuleSetTag); - } - - private static void updateYangModelCmHandleForUpgrade(final YangModelCmHandle yangModelCmHandle, - final String upgradedModuleSetTag) { - final String lockReasonWithModuleSetTag = String.format(ModuleOperationsUtils.MODULE_SET_TAG_MESSAGE_FORMAT, - upgradedModuleSetTag); - yangModelCmHandle.setCompositeState(new CompositeStateBuilder().withCmHandleState(CmHandleState.READY) - .withLockReason(MODULE_UPGRADE, lockReasonWithModuleSetTag).build()); - } - - private CmHandleRegistrationResponse deleteCmHandleAndGetCmHandleRegistrationResponse(final String cmHandleId) { - try { - deleteCmHandleFromDbAndModuleSyncMap(cmHandleId); - return CmHandleRegistrationResponse.createSuccessResponse(cmHandleId); - } catch (final DataNodeNotFoundException dataNodeNotFoundException) { - log.error("Unable to find dataNode for cmHandleId : {} , caused by : {}", - cmHandleId, dataNodeNotFoundException.getMessage()); - return CmHandleRegistrationResponse.createFailureResponse(cmHandleId, CM_HANDLES_NOT_FOUND); - } catch (final DataValidationException dataValidationException) { - log.error("Unable to de-register cm-handle id: {}, caused by: {}", - cmHandleId, dataValidationException.getMessage()); - return CmHandleRegistrationResponse.createFailureResponse(cmHandleId, CM_HANDLE_INVALID_ID); - } catch (final Exception exception) { - log.error("Unable to de-register cm-handle id : {} , caused by : {}", cmHandleId, exception.getMessage()); - return CmHandleRegistrationResponse.createFailureResponse(cmHandleId, exception); - } - } - - private void updateCmHandleStateBatch(final Collection yangModelCmHandles, - final CmHandleState cmHandleState) { - final Map cmHandleStatePerCmHandle = new HashMap<>(yangModelCmHandles.size()); - yangModelCmHandles.forEach(yangModelCmHandle -> cmHandleStatePerCmHandle.put(yangModelCmHandle, cmHandleState)); - lcmEventsCmHandleStateHandler.updateCmHandleStateBatch(cmHandleStatePerCmHandle); - } - - private void deleteCmHandleFromDbAndModuleSyncMap(final String cmHandleId) { - inventoryPersistence.deleteSchemaSetWithCascade(cmHandleId); - inventoryPersistence.deleteDataNode(NCMP_DMI_REGISTRY_PARENT + "/cm-handles[@id='" + cmHandleId + "']"); - removeDeletedCmHandleFromModuleSyncMap(cmHandleId); - } - - private void batchDeleteCmHandlesFromDbAndModuleSyncMap(final Collection cmHandleIds) { - inventoryPersistence.deleteSchemaSetsWithCascade(cmHandleIds); - inventoryPersistence.deleteDataNodes(mapCmHandleIdsToXpaths(cmHandleIds)); - cmHandleIds.forEach(this::removeDeletedCmHandleFromModuleSyncMap); - } - - private Collection mapCmHandleIdsToXpaths(final Collection cmHandles) { - return cmHandles.stream() - .map(cmHandleId -> NCMP_DMI_REGISTRY_PARENT + "/cm-handles[@id='" + cmHandleId + "']") - .collect(Collectors.toSet()); - } - - // CPS-1239 Robustness cleaning of in progress cache - private void removeDeletedCmHandleFromModuleSyncMap(final String cmHandleId) { - if (moduleSyncStartedOnCmHandles.remove(cmHandleId) != null) { - log.debug("{} removed from in progress map", cmHandleId); - } - } - - private List upgradeCmHandles(final Map - cmHandleStatePerCmHandle) { - final List cmHandleIds = getCmHandleIds(cmHandleStatePerCmHandle); - log.info("Moving cm handles : {} into locked (for upgrade) state.", cmHandleIds); - try { - lcmEventsCmHandleStateHandler.updateCmHandleStateBatch(cmHandleStatePerCmHandle); - return CmHandleRegistrationResponse.createSuccessResponses(cmHandleIds); - } catch (final Exception e) { - log.error("Unable to update cmHandleIds : {} , caused by : {}", cmHandleIds, e.getMessage()); - return CmHandleRegistrationResponse.createFailureResponses(cmHandleIds, e); - } - } - - private static List getCmHandleIds(final Map cmHandleStatePerCmHandle) { - return cmHandleStatePerCmHandle.keySet().stream().map(YangModelCmHandle::getId).toList(); - } - - private void setTrustLevelPerDmiPlugin(final DmiPluginRegistration dmiPluginRegistration) { - if (DmiPluginRegistration.isNullEmptyOrBlank(dmiPluginRegistration.getDmiDataPlugin())) { - trustLevelPerDmiPlugin.put(dmiPluginRegistration.getDmiPlugin(), TrustLevel.COMPLETE); - } else { - trustLevelPerDmiPlugin.put(dmiPluginRegistration.getDmiDataPlugin(), TrustLevel.COMPLETE); - } - } - - private Collection checkAlternateIds( - final List cmHandlesToBeCreated, - final List cmHandleRegistrationResponses) { - final Collection rejectedCmHandleIds = alternateIdChecker - .getIdsOfCmHandlesWithRejectedAlternateId(cmHandlesToBeCreated, AlternateIdChecker.Operation.CREATE); - cmHandleRegistrationResponses.addAll(CmHandleRegistrationResponse.createFailureResponses( - rejectedCmHandleIds, ALTERNATE_ID_ALREADY_ASSOCIATED)); - return rejectedCmHandleIds; - } - - private List persistCmHandlesWithState(final DmiPluginRegistration dmiPluginRegistration, - final DmiPluginRegistrationResponse dmiPluginRegistrationResponse, - final List cmHandlesToBeCreated, - final Collection rejectedCmHandleIds) { - final List succeededCmHandleIds = new ArrayList<>(cmHandlesToBeCreated.size()); - final List yangModelCmHandlesToRegister = new ArrayList<>(cmHandlesToBeCreated.size()); - final List cmHandleRegistrationResponses = - new ArrayList<>(cmHandlesToBeCreated.size()); - for (final NcmpServiceCmHandle ncmpServiceCmHandle: cmHandlesToBeCreated) { - if (!rejectedCmHandleIds.contains(ncmpServiceCmHandle.getCmHandleId())) { - yangModelCmHandlesToRegister.add(getYangModelCmHandle(dmiPluginRegistration, ncmpServiceCmHandle)); - cmHandleRegistrationResponses.add( - CmHandleRegistrationResponse.createSuccessResponse(ncmpServiceCmHandle.getCmHandleId())); - succeededCmHandleIds.add(ncmpServiceCmHandle.getCmHandleId()); - } - } - lcmEventsCmHandleStateHandler.initiateStateAdvised(yangModelCmHandlesToRegister); - dmiPluginRegistrationResponse.setCreatedCmHandles(cmHandleRegistrationResponses); - return succeededCmHandleIds; - } - - private YangModelCmHandle getYangModelCmHandle(final DmiPluginRegistration dmiPluginRegistration, - final NcmpServiceCmHandle ncmpServiceCmHandle) { - return YangModelCmHandle.toYangModelCmHandle( - dmiPluginRegistration.getDmiPlugin(), - dmiPluginRegistration.getDmiDataPlugin(), - dmiPluginRegistration.getDmiModelPlugin(), - ncmpServiceCmHandle, - ncmpServiceCmHandle.getModuleSetTag(), - ncmpServiceCmHandle.getAlternateId(), - ncmpServiceCmHandle.getDataProducerIdentifier()); - } - - -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/CmHandleRegistrationServicePropertyHandler.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/CmHandleRegistrationServicePropertyHandler.java deleted file mode 100644 index 1dac33f670..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/CmHandleRegistrationServicePropertyHandler.java +++ /dev/null @@ -1,246 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022-2024 Nordix Foundation - * Modifications Copyright (C) 2022 Bell Canada - * Modifications Copyright (C) 2024 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.NcmpResponseStatus.ALTERNATE_ID_ALREADY_ASSOCIATED; -import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLES_NOT_FOUND; -import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLE_INVALID_ID; -import static org.onap.cps.ncmp.api.impl.CmHandleRegistrationServicePropertyHandler.PropertyType.DMI_PROPERTY; -import static org.onap.cps.ncmp.api.impl.CmHandleRegistrationServicePropertyHandler.PropertyType.PUBLIC_PROPERTY; -import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME; -import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR; -import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT; - -import com.google.common.collect.ImmutableMap; -import java.time.OffsetDateTime; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.regex.Matcher; -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.inventory.InventoryPersistence; -import org.onap.cps.ncmp.api.impl.utils.AlternateIdChecker; -import org.onap.cps.ncmp.api.impl.utils.YangDataConverter; -import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse; -import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; -import org.onap.cps.spi.exceptions.DataNodeNotFoundException; -import org.onap.cps.spi.exceptions.DataValidationException; -import org.onap.cps.spi.model.DataNode; -import org.onap.cps.spi.model.DataNodeBuilder; -import org.onap.cps.utils.ContentType; -import org.onap.cps.utils.JsonObjectMapper; -import org.springframework.stereotype.Service; -import org.springframework.util.StringUtils; - -@Slf4j -@Service -@RequiredArgsConstructor -//Accepting the security hotspot as the string checked is generated from inside code and not user input. -@SuppressWarnings("squid:S5852") -public class CmHandleRegistrationServicePropertyHandler { - - private final InventoryPersistence inventoryPersistence; - private final CpsDataService cpsDataService; - private final JsonObjectMapper jsonObjectMapper; - private final AlternateIdChecker alternateIdChecker; - - /** - * Iterates over incoming updatedNcmpServiceCmHandles and update the dataNodes based on the updated attributes. - * The attributes which are not passed will remain as is. - * - * @param updatedNcmpServiceCmHandles collection of CmHandles - */ - public List updateCmHandleProperties( - final Collection updatedNcmpServiceCmHandles) { - final Collection rejectedCmHandleIds = alternateIdChecker - .getIdsOfCmHandlesWithRejectedAlternateId(updatedNcmpServiceCmHandles, AlternateIdChecker.Operation.UPDATE); - final List failureResponses = - CmHandleRegistrationResponse.createFailureResponses(rejectedCmHandleIds, ALTERNATE_ID_ALREADY_ASSOCIATED); - final List cmHandleRegistrationResponses = new ArrayList<>(failureResponses); - for (final NcmpServiceCmHandle updatedNcmpServiceCmHandle : updatedNcmpServiceCmHandles) { - final String cmHandleId = updatedNcmpServiceCmHandle.getCmHandleId(); - if (!rejectedCmHandleIds.contains(cmHandleId)) { - try { - final DataNode existingCmHandleDataNode = inventoryPersistence - .getCmHandleDataNodeByCmHandleId(cmHandleId).iterator().next(); - processUpdates(existingCmHandleDataNode, updatedNcmpServiceCmHandle); - cmHandleRegistrationResponses.add(CmHandleRegistrationResponse.createSuccessResponse(cmHandleId)); - } catch (final DataNodeNotFoundException e) { - log.error("Unable to find dataNode for cmHandleId : {} , caused by : {}", cmHandleId, - e.getMessage()); - cmHandleRegistrationResponses.add( - CmHandleRegistrationResponse.createFailureResponse(cmHandleId, CM_HANDLES_NOT_FOUND)); - } catch (final DataValidationException e) { - log.error("Unable to update cm handle : {}, caused by : {}", cmHandleId, e.getMessage()); - cmHandleRegistrationResponses.add( - CmHandleRegistrationResponse.createFailureResponse(cmHandleId, CM_HANDLE_INVALID_ID)); - } catch (final Exception exception) { - log.error("Unable to update cmHandle : {} , caused by : {}", cmHandleId, exception.getMessage()); - cmHandleRegistrationResponses.add( - CmHandleRegistrationResponse.createFailureResponse(cmHandleId, exception)); - } - } - } - return cmHandleRegistrationResponses; - } - - private void processUpdates(final DataNode existingCmHandleDataNode, - final NcmpServiceCmHandle updatedNcmpServiceCmHandle) { - setAndUpdateCmHandleField( - updatedNcmpServiceCmHandle.getCmHandleId(), "alternate-id", updatedNcmpServiceCmHandle.getAlternateId()); - updateDataProducerIdentifier(existingCmHandleDataNode, updatedNcmpServiceCmHandle); - if (!updatedNcmpServiceCmHandle.getPublicProperties().isEmpty()) { - updateProperties(existingCmHandleDataNode, PUBLIC_PROPERTY, - updatedNcmpServiceCmHandle.getPublicProperties()); - } - if (!updatedNcmpServiceCmHandle.getDmiProperties().isEmpty()) { - updateProperties(existingCmHandleDataNode, DMI_PROPERTY, updatedNcmpServiceCmHandle.getDmiProperties()); - } - } - - private void updateDataProducerIdentifier(final DataNode cmHandleDataNode, - final NcmpServiceCmHandle ncmpServiceCmHandle) { - final String newDataProducerIdentifier = ncmpServiceCmHandle.getDataProducerIdentifier(); - if (StringUtils.hasText(newDataProducerIdentifier)) { - final YangModelCmHandle yangModelCmHandle = - YangDataConverter.convertCmHandleToYangModel(cmHandleDataNode); - final String existingDataProducerIdentifier = yangModelCmHandle.getDataProducerIdentifier(); - if (StringUtils.hasText(existingDataProducerIdentifier)) { - if (!existingDataProducerIdentifier.equals(newDataProducerIdentifier)) { - log.warn("Unable to update dataProducerIdentifier for cmHandle {}. " - + "Value for dataProducerIdentifier has been set previously.", - ncmpServiceCmHandle.getCmHandleId()); - } else { - log.debug("dataProducerIdentifier for cmHandle {} is already set to {}.", - ncmpServiceCmHandle.getCmHandleId(), newDataProducerIdentifier); - } - } else { - setAndUpdateCmHandleField( - yangModelCmHandle.getId(), "data-producer-identifier", newDataProducerIdentifier); - } - } - } - - private void updateProperties(final DataNode existingCmHandleDataNode, final PropertyType propertyType, - final Map updatedProperties) { - final Collection replacementPropertyDataNodes = - getReplacementDataNodes(existingCmHandleDataNode, propertyType, updatedProperties); - replacementPropertyDataNodes.addAll( - getUnchangedPropertyDataNodes(existingCmHandleDataNode, propertyType, updatedProperties)); - if (replacementPropertyDataNodes.isEmpty()) { - removeAllProperties(existingCmHandleDataNode, propertyType); - } else { - inventoryPersistence.replaceListContent(existingCmHandleDataNode.getXpath(), replacementPropertyDataNodes); - } - } - - private void removeAllProperties(final DataNode existingCmHandleDataNode, final PropertyType propertyType) { - existingCmHandleDataNode.getChildDataNodes().forEach(dataNode -> { - final Matcher matcher = propertyType.propertyXpathPattern.matcher(dataNode.getXpath()); - if (matcher.find()) { - log.info("Deleting dataNode with xpath : [{}]", dataNode.getXpath()); - inventoryPersistence.deleteDataNode(dataNode.getXpath()); - } - }); - } - - private Collection getUnchangedPropertyDataNodes(final DataNode existingCmHandleDataNode, - final PropertyType propertyType, - final Map updatedProperties) { - final Collection unchangedPropertyDataNodes = new HashSet<>(); - for (final DataNode existingPropertyDataNode : existingCmHandleDataNode.getChildDataNodes()) { - final Matcher matcher = propertyType.propertyXpathPattern.matcher(existingPropertyDataNode.getXpath()); - if (matcher.find()) { - final String keyName = matcher.group(2); - if (!updatedProperties.containsKey(keyName)) { - unchangedPropertyDataNodes.add(existingPropertyDataNode); - } - } - } - return unchangedPropertyDataNodes; - } - - private Collection getReplacementDataNodes(final DataNode existingCmHandleDataNode, - final PropertyType propertyType, - final Map updatedProperties) { - final Collection replacementPropertyDataNodes = new HashSet<>(); - updatedProperties.forEach((updatedAttributeKey, updatedAttributeValue) -> { - final String propertyXpath = getAttributeXpath(existingCmHandleDataNode, propertyType, updatedAttributeKey); - if (updatedAttributeValue != null) { - log.info("Creating a new DataNode with xpath {} , key : {} and value : {}", propertyXpath, - updatedAttributeKey, updatedAttributeValue); - replacementPropertyDataNodes.add( - buildDataNode(propertyXpath, updatedAttributeKey, updatedAttributeValue)); - } - }); - return replacementPropertyDataNodes; - } - - private String getAttributeXpath(final DataNode cmHandle, final PropertyType propertyType, - final String attributeKey) { - return cmHandle.getXpath() + "/" + propertyType.xpathPrefix + String.format("[@name='%s']", attributeKey); - } - - private DataNode buildDataNode(final String xpath, final String attributeKey, final String attributeValue) { - final Map updatedLeaves = new LinkedHashMap<>(1); - updatedLeaves.put("name", attributeKey); - updatedLeaves.put("value", attributeValue); - log.debug("Building a new node with xpath {} with leaves (name : {} , value : {})", xpath, attributeKey, - attributeValue); - return new DataNodeBuilder().withXpath(xpath).withLeaves(ImmutableMap.copyOf(updatedLeaves)).build(); - } - - private void setAndUpdateCmHandleField(final String cmHandleIdToUpdate, final String fieldName, - final String newFieldValue) { - final Map> dmiRegistryData = new HashMap<>(1); - final Map cmHandleData = new HashMap<>(2); - cmHandleData.put("id", cmHandleIdToUpdate); - cmHandleData.put(fieldName, newFieldValue); - dmiRegistryData.put("cm-handles", cmHandleData); - cpsDataService.updateNodeLeaves(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, NCMP_DMI_REGISTRY_PARENT, - jsonObjectMapper.asJsonString(dmiRegistryData), OffsetDateTime.now(), ContentType.JSON); - log.debug("Updating {} for cmHandle {} with value : {})", fieldName, cmHandleIdToUpdate, newFieldValue); - } - - enum PropertyType { - DMI_PROPERTY("additional-properties"), PUBLIC_PROPERTY("public-properties"); - - private static final String LIST_INDEX_PATTERN = "\\[@(\\w+)[^\\/]'([^']+)']"; - - final String xpathPrefix; - final Pattern propertyXpathPattern; - - PropertyType(final String xpathPrefix) { - this.xpathPrefix = xpathPrefix; - this.propertyXpathPattern = Pattern.compile(xpathPrefix + LIST_INDEX_PATTERN); - } - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyInventoryFacade.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyInventoryFacade.java deleted file mode 100644 index 5b439ebcfe..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyInventoryFacade.java +++ /dev/null @@ -1,207 +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.utils.RestQueryParametersValidator.validateCmHandleQueryParameters; - -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.onap.cps.ncmp.api.ParameterizedCmHandleQueryService; -import org.onap.cps.ncmp.api.impl.inventory.CmHandleQueryService; -import org.onap.cps.ncmp.api.impl.inventory.CompositeState; -import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence; -import org.onap.cps.ncmp.api.impl.utils.CmHandleQueryConditions; -import org.onap.cps.ncmp.api.impl.utils.InventoryQueryConditions; -import org.onap.cps.ncmp.api.impl.utils.YangDataConverter; -import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.ncmp.api.models.CmHandleQueryApiParameters; -import org.onap.cps.ncmp.api.models.CmHandleQueryServiceParameters; -import org.onap.cps.ncmp.api.models.DmiPluginRegistration; -import org.onap.cps.ncmp.api.models.DmiPluginRegistrationResponse; -import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; -import org.onap.cps.spi.model.ModuleDefinition; -import org.onap.cps.spi.model.ModuleReference; -import org.onap.cps.utils.JsonObjectMapper; -import org.springframework.stereotype.Service; - -@Slf4j -@Service -@RequiredArgsConstructor -public class NetworkCmProxyInventoryFacade { - - private final CmHandleRegistrationService cmHandleRegistrationService; - private final CmHandleQueryService cmHandleQueryService; - private final ParameterizedCmHandleQueryService parameterizedCmHandleQueryService; - private final InventoryPersistence inventoryPersistence; - private final JsonObjectMapper jsonObjectMapper; - - /** - * Registration of Created, Removed, Updated or Upgraded CM Handles. - * - * @param dmiPluginRegistration Dmi Plugin Registration details - * @return dmiPluginRegistrationResponse - */ - - public DmiPluginRegistrationResponse updateDmiRegistrationAndSyncModule( - final DmiPluginRegistration dmiPluginRegistration) { - return cmHandleRegistrationService.updateDmiRegistrationAndSyncModule(dmiPluginRegistration); - } - - /** - * Get all cm handle IDs by DMI plugin identifier. - * - * @param dmiPluginIdentifier DMI plugin identifier - * @return collection of cm handle IDs - */ - public Collection getAllCmHandleIdsByDmiPluginIdentifier(final String dmiPluginIdentifier) { - return cmHandleQueryService.getCmHandleIdsByDmiPluginIdentifier(dmiPluginIdentifier); - } - - /** - * Get all cm handle IDs by various properties. - * - * @param cmHandleQueryServiceParameters cm handle query parameters - * @return collection of cm handle IDs - */ - public Collection executeParameterizedCmHandleIdSearch( - final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) { - validateCmHandleQueryParameters(cmHandleQueryServiceParameters, InventoryQueryConditions.ALL_CONDITION_NAMES); - return parameterizedCmHandleQueryService.queryCmHandleIdsForInventory(cmHandleQueryServiceParameters); - } - - - /** - * Retrieve module references for the given cm handle. - * - * @param cmHandleId cm handle identifier - * @return a collection of modules names and revisions - */ - public Collection getYangResourcesModuleReferences(final String cmHandleId) { - return inventoryPersistence.getYangResourcesModuleReferences(cmHandleId); - } - - /** - * Retrieve module definitions for the given cm handle. - * - * @param cmHandleId cm handle identifier - * @return a collection of module definition (moduleName, revision and yang resource content) - */ - public Collection getModuleDefinitionsByCmHandleId(final String cmHandleId) { - return inventoryPersistence.getModuleDefinitionsByCmHandleId(cmHandleId); - } - - /** - * Get module definitions for the given parameters. - * - * @param cmHandleId cm-handle identifier - * @param moduleName module name - * @param moduleRevision the revision of the module - * @return list of module definitions (module name, revision, yang resource content) - */ - public Collection getModuleDefinitionsByCmHandleAndModule(final String cmHandleId, - final String moduleName, - final String moduleRevision) { - return inventoryPersistence.getModuleDefinitionsByCmHandleAndModule(cmHandleId, moduleName, moduleRevision); - } - - /** - * Retrieve cm handles with details for the given query parameters. - * - * @param cmHandleQueryApiParameters cm handle query parameters - * @return cm handles with details - */ - public Collection executeCmHandleSearch( - final CmHandleQueryApiParameters cmHandleQueryApiParameters) { - final CmHandleQueryServiceParameters cmHandleQueryServiceParameters = jsonObjectMapper.convertToValueType( - cmHandleQueryApiParameters, CmHandleQueryServiceParameters.class); - validateCmHandleQueryParameters(cmHandleQueryServiceParameters, CmHandleQueryConditions.ALL_CONDITION_NAMES); - return parameterizedCmHandleQueryService.queryCmHandles(cmHandleQueryServiceParameters); - } - - /** - * Retrieve cm handle ids for the given query parameters. - * - * @param cmHandleQueryApiParameters cm handle query parameters - * @return cm handle ids - */ - public Collection executeCmHandleIdSearch(final CmHandleQueryApiParameters cmHandleQueryApiParameters) { - final CmHandleQueryServiceParameters cmHandleQueryServiceParameters = jsonObjectMapper.convertToValueType( - cmHandleQueryApiParameters, CmHandleQueryServiceParameters.class); - validateCmHandleQueryParameters(cmHandleQueryServiceParameters, CmHandleQueryConditions.ALL_CONDITION_NAMES); - return parameterizedCmHandleQueryService.queryCmHandleIds(cmHandleQueryServiceParameters); - } - - /** - * Set the data sync enabled flag, along with the data sync state - * based on the data sync enabled boolean for the cm handle id provided. - * - * @param cmHandleId cm handle id - * @param dataSyncEnabledTargetValue data sync enabled flag - */ - public void setDataSyncEnabled(final String cmHandleId, final Boolean dataSyncEnabledTargetValue) { - cmHandleRegistrationService.setDataSyncEnabled(cmHandleId, dataSyncEnabledTargetValue); - } - - /** - * Retrieve cm handle details for a given cm handle. - * - * @param cmHandleId cm handle identifier - * @return cm handle details - */ - public NcmpServiceCmHandle getNcmpServiceCmHandle(final String cmHandleId) { - return YangDataConverter.convertYangModelCmHandleToNcmpServiceCmHandle( - inventoryPersistence.getYangModelCmHandle(cmHandleId)); - } - - /** - * Get cm handle public properties for a given cm handle id. - * - * @param cmHandleId cm handle identifier - * @return cm handle public properties - */ - public Map getCmHandlePublicProperties(final String cmHandleId) { - final YangModelCmHandle yangModelCmHandle = inventoryPersistence.getYangModelCmHandle(cmHandleId); - final List yangModelPublicProperties = yangModelCmHandle.getPublicProperties(); - final Map cmHandlePublicProperties = new HashMap<>(); - YangDataConverter.asPropertiesMap(yangModelPublicProperties, cmHandlePublicProperties); - return cmHandlePublicProperties; - } - - /** - * Get cm handle composite state for a given cm handle id. - * - * @param cmHandleId cm handle identifier - * @return cm handle state - */ - public CompositeState getCmHandleCompositeState(final String cmHandleId) { - return inventoryPersistence.getYangModelCmHandle(cmHandleId).getCompositeState(); - } - - -} 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 index 8d3b6ed8f7..8507fb773f 100644 --- 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 @@ -20,7 +20,7 @@ package org.onap.cps.ncmp.api.impl; -import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME; +import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME; import java.util.Collection; import lombok.RequiredArgsConstructor; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/ParameterizedCmHandleQueryServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/ParameterizedCmHandleQueryServiceImpl.java deleted file mode 100644 index b8418bea33..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/ParameterizedCmHandleQueryServiceImpl.java +++ /dev/null @@ -1,286 +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.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT; -import static org.onap.cps.ncmp.api.impl.utils.CmHandleQueryConditions.HAS_ALL_MODULES; -import static org.onap.cps.ncmp.api.impl.utils.CmHandleQueryConditions.HAS_ALL_PROPERTIES; -import static org.onap.cps.ncmp.api.impl.utils.CmHandleQueryConditions.WITH_CPS_PATH; -import static org.onap.cps.ncmp.api.impl.utils.CmHandleQueryConditions.WITH_TRUST_LEVEL; -import static org.onap.cps.ncmp.api.impl.utils.RestQueryParametersValidator.validateCpsPathConditionProperties; -import static org.onap.cps.ncmp.api.impl.utils.RestQueryParametersValidator.validateModuleNameConditionProperties; -import static org.onap.cps.ncmp.api.impl.utils.YangDataConverter.convertYangModelCmHandleToNcmpServiceCmHandle; -import static org.onap.cps.spi.FetchDescendantsOption.DIRECT_CHILDREN_ONLY; -import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS; - -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.function.Function; -import java.util.stream.Collectors; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.onap.cps.cpspath.parser.PathParsingException; -import org.onap.cps.ncmp.api.ParameterizedCmHandleQueryService; -import org.onap.cps.ncmp.api.impl.inventory.CmHandleQueryService; -import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence; -import org.onap.cps.ncmp.api.impl.inventory.enums.PropertyType; -import org.onap.cps.ncmp.api.impl.utils.InventoryQueryConditions; -import org.onap.cps.ncmp.api.impl.utils.YangDataConverter; -import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.ncmp.api.models.CmHandleQueryServiceParameters; -import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; -import org.onap.cps.spi.exceptions.DataValidationException; -import org.onap.cps.spi.model.ConditionProperties; -import org.onap.cps.spi.model.DataNode; -import org.springframework.stereotype.Service; - -@Service -@Slf4j -@RequiredArgsConstructor -public class ParameterizedCmHandleQueryServiceImpl implements ParameterizedCmHandleQueryService { - - private static final Collection NO_QUERY_TO_EXECUTE = null; - private final CmHandleQueryService cmHandleQueryService; - private final InventoryPersistence inventoryPersistence; - - @Override - public Collection queryCmHandleIds( - final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) { - return executeQueries(cmHandleQueryServiceParameters, - this::executeCpsPathQuery, - this::queryCmHandlesByPublicProperties, - this::executeModuleNameQuery, - this::queryCmHandlesByTrustLevel); - } - - @Override - public Collection queryCmHandleIdsForInventory( - final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) { - return executeQueries(cmHandleQueryServiceParameters, - this::queryCmHandlesByPublicProperties, - this::queryCmHandlesByPrivateProperties, - this::queryCmHandlesByDmiPlugin); - } - - @Override - public Collection queryCmHandles( - final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) { - - if (cmHandleQueryServiceParameters.getCmHandleQueryParameters().isEmpty()) { - return getAllCmHandles(); - } - - final Collection cmHandleIds = queryCmHandleIds(cmHandleQueryServiceParameters); - - return getNcmpServiceCmHandles(cmHandleIds); - } - - @Override - public Collection getAllCmHandles() { - final DataNode dataNode = inventoryPersistence.getDataNode(NCMP_DMI_REGISTRY_PARENT).iterator().next(); - return dataNode.getChildDataNodes().stream().map(this::createNcmpServiceCmHandle).collect(Collectors.toSet()); - } - - private Collection queryCmHandlesByDmiPlugin( - final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) { - final Map dmiPropertyQueryPairs = - getPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters(), - InventoryQueryConditions.CM_HANDLE_WITH_DMI_PLUGIN.getName()); - if (dmiPropertyQueryPairs.isEmpty()) { - return NO_QUERY_TO_EXECUTE; - } - - final String dmiPluginIdentifierValue = dmiPropertyQueryPairs - .get(PropertyType.DMI_PLUGIN.getYangContainerName()); - - return cmHandleQueryService.getCmHandleIdsByDmiPluginIdentifier(dmiPluginIdentifierValue); - } - - private Collection queryCmHandlesByPrivateProperties( - final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) { - - final Map privatePropertyQueryPairs = - getPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters(), - InventoryQueryConditions.HAS_ALL_ADDITIONAL_PROPERTIES.getName()); - - if (privatePropertyQueryPairs.isEmpty()) { - return NO_QUERY_TO_EXECUTE; - } - return cmHandleQueryService.queryCmHandleAdditionalProperties(privatePropertyQueryPairs); - } - - private Collection queryCmHandlesByPublicProperties( - final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) { - - final Map publicPropertyQueryPairs = - getPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters(), - HAS_ALL_PROPERTIES.getConditionName()); - - if (publicPropertyQueryPairs.isEmpty()) { - return NO_QUERY_TO_EXECUTE; - } - return cmHandleQueryService.queryCmHandlePublicProperties(publicPropertyQueryPairs); - } - - private Collection queryCmHandlesByTrustLevel(final CmHandleQueryServiceParameters - cmHandleQueryServiceParameters) { - - final Map trustLevelPropertyQueryPairs = - getPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters(), - WITH_TRUST_LEVEL.getConditionName()); - - if (trustLevelPropertyQueryPairs.isEmpty()) { - return NO_QUERY_TO_EXECUTE; - } - return cmHandleQueryService.queryCmHandlesByTrustLevel(trustLevelPropertyQueryPairs); - } - - private Collection executeModuleNameQuery( - final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) { - final Collection moduleNamesForQuery = - getModuleNamesForQuery(cmHandleQueryServiceParameters.getCmHandleQueryParameters()); - if (moduleNamesForQuery.isEmpty()) { - return NO_QUERY_TO_EXECUTE; - } - return inventoryPersistence.getCmHandleIdsWithGivenModules(moduleNamesForQuery); - } - - private Collection executeCpsPathQuery( - final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) { - final Map cpsPathCondition - = getCpsPathCondition(cmHandleQueryServiceParameters.getCmHandleQueryParameters()); - if (!validateCpsPathConditionProperties(cpsPathCondition)) { - return Collections.emptySet(); - } - final Collection cpsPathQueryResult; - if (cpsPathCondition.isEmpty()) { - return NO_QUERY_TO_EXECUTE; - } - try { - cpsPathQueryResult = collectCmHandleIdsFromDataNodes( - cmHandleQueryService.queryCmHandleAncestorsByCpsPath( - cpsPathCondition.get("cpsPath"), OMIT_DESCENDANTS)); - } catch (final PathParsingException pathParsingException) { - throw new DataValidationException(pathParsingException.getMessage(), pathParsingException.getDetails(), - pathParsingException); - } - return cpsPathQueryResult; - } - - private Collection getModuleNamesForQuery(final List conditionProperties) { - final List result = new ArrayList<>(); - getConditions(conditionProperties, HAS_ALL_MODULES.getConditionName()).forEach( - conditionProperty -> { - validateModuleNameConditionProperties(conditionProperty); - result.add(conditionProperty.get("moduleName")); - }); - return result; - } - - private Map getCpsPathCondition(final List conditionProperties) { - final Map result = new HashMap<>(); - getConditions(conditionProperties, WITH_CPS_PATH.getConditionName()).forEach(result::putAll); - return result; - } - - private Map getPropertyPairs(final List conditionProperties, - final String queryProperty) { - final Map result = new HashMap<>(); - getConditions(conditionProperties, queryProperty).forEach(result::putAll); - return result; - } - - private List> getConditions(final List conditionProperties, - final String name) { - for (final ConditionProperties conditionProperty : conditionProperties) { - if (conditionProperty.getConditionName().equals(name)) { - return conditionProperty.getConditionParameters(); - } - } - return Collections.emptyList(); - } - - private Collection getAllCmHandleIds() { - final DataNode dataNode = inventoryPersistence.getDataNode(NCMP_DMI_REGISTRY_PARENT, DIRECT_CHILDREN_ONLY) - .iterator().next(); - return collectCmHandleIdsFromDataNodes(dataNode.getChildDataNodes()); - } - - private Collection getNcmpServiceCmHandles(final Collection cmHandleIds) { - final Collection yangModelcmHandles - = inventoryPersistence.getYangModelCmHandles(cmHandleIds); - - final Collection ncmpServiceCmHandles = new ArrayList<>(yangModelcmHandles.size()); - - yangModelcmHandles.forEach(yangModelcmHandle -> - ncmpServiceCmHandles.add(YangDataConverter.convertYangModelCmHandleToNcmpServiceCmHandle(yangModelcmHandle)) - ); - return ncmpServiceCmHandles; - } - - private NcmpServiceCmHandle createNcmpServiceCmHandle(final DataNode dataNode) { - return convertYangModelCmHandleToNcmpServiceCmHandle(YangDataConverter.convertCmHandleToYangModel(dataNode)); - } - - private Collection executeQueries(final CmHandleQueryServiceParameters cmHandleQueryServiceParameters, - final Function>... - queryFunctions) { - if (cmHandleQueryServiceParameters.getCmHandleQueryParameters().isEmpty()) { - return getAllCmHandleIds(); - } - Collection combinedQueryResult = NO_QUERY_TO_EXECUTE; - for (final Function> queryFunction : queryFunctions) { - final Collection queryResult = queryFunction.apply(cmHandleQueryServiceParameters); - if (noEntriesFoundCanStopQuerying(queryResult)) { - return Collections.emptySet(); - } - combinedQueryResult = combineCmHandleQueryResults(combinedQueryResult, queryResult); - } - return combinedQueryResult; - } - - private boolean noEntriesFoundCanStopQuerying(final Collection queryResult) { - return queryResult != NO_QUERY_TO_EXECUTE && queryResult.isEmpty(); - } - - private Collection combineCmHandleQueryResults(final Collection firstQuery, - final Collection secondQuery) { - if (firstQuery == NO_QUERY_TO_EXECUTE && secondQuery == NO_QUERY_TO_EXECUTE) { - return NO_QUERY_TO_EXECUTE; - } else if (firstQuery == NO_QUERY_TO_EXECUTE) { - return secondQuery; - } else if (secondQuery == NO_QUERY_TO_EXECUTE) { - return firstQuery; - } else { - firstQuery.retainAll(secondQuery); - return firstQuery; - } - } - - private Collection collectCmHandleIdsFromDataNodes(final Collection dataNodes) { - return dataNodes.stream().map(dataNode -> (String) dataNode.getLeaves().get("id")).collect(Collectors.toSet()); - } - -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/embeddedcache/SynchronizationCacheConfig.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/embeddedcache/SynchronizationCacheConfig.java deleted file mode 100644 index 62a380ca5c..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/embeddedcache/SynchronizationCacheConfig.java +++ /dev/null @@ -1,77 +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.config.embeddedcache; - -import com.hazelcast.config.MapConfig; -import com.hazelcast.config.QueueConfig; -import com.hazelcast.map.IMap; -import java.util.concurrent.BlockingQueue; -import lombok.extern.slf4j.Slf4j; -import org.onap.cps.cache.HazelcastCacheConfig; -import org.onap.cps.spi.model.DataNode; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -/** - * Core infrastructure of the hazelcast distributed caches for Module Sync and Data Sync use cases. - */ -@Slf4j -@Configuration -public class SynchronizationCacheConfig extends HazelcastCacheConfig { - - public static final int MODULE_SYNC_STARTED_TTL_SECS = 600; - public static final int DATA_SYNC_SEMAPHORE_TTL_SECS = 1800; - - private static final QueueConfig commonQueueConfig = createQueueConfig("defaultQueueConfig"); - private static final MapConfig moduleSyncStartedConfig = createMapConfig("moduleSyncStartedConfig"); - private static final MapConfig dataSyncSemaphoresConfig = createMapConfig("dataSyncSemaphoresConfig"); - - /** - * Module Sync Distributed Queue Instance. - * - * @return queue of cm handles (data nodes) that need module sync - */ - @Bean - public BlockingQueue moduleSyncWorkQueue() { - return createHazelcastInstance("moduleSyncWorkQueue", commonQueueConfig).getQueue("moduleSyncWorkQueue"); - } - - /** - * Module Sync started (and maybe finished) on cm handles (ids). - * - * @return Map of cm handles (ids) and objects (not used really) for which module sync has started or been completed - */ - @Bean - public IMap moduleSyncStartedOnCmHandles() { - return createHazelcastInstance("moduleSyncStartedOnCmHandles", moduleSyncStartedConfig).getMap( - "moduleSyncStartedOnCmHandles"); - } - - /** - * Data Sync Distributed Map Instance. - * - * @return configured map of data sync semaphores - */ - @Bean - public IMap dataSyncSemaphores() { - return createHazelcastInstance("dataSyncSemaphores", dataSyncSemaphoresConfig).getMap("dataSyncSemaphores"); - } -} 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 368e27a7d1..21c26228bc 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 @@ -35,10 +35,10 @@ import org.onap.cps.ncmp.api.impl.events.cmsubscription.model.CmNotificationSubs 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.inventory.InventoryPersistence; import org.onap.cps.ncmp.api.impl.operations.DatastoreType; -import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; 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; import org.springframework.stereotype.Component; @Component @@ -216,4 +216,4 @@ public class DmiCmNotificationSubscriptionCacheHandler { return dmiCmNotificationSubscription.getCmNotificationSubscriptionStatus().toString().equals("ACCEPTED") || dmiCmNotificationSubscription.getCmNotificationSubscriptionStatus().toString().equals("REJECTED"); } -} \ No newline at end of file +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/mapper/CmNotificationSubscriptionDmiInEventMapper.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/mapper/CmNotificationSubscriptionDmiInEventMapper.java index 7610687480..7263891a21 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/mapper/CmNotificationSubscriptionDmiInEventMapper.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/mapper/CmNotificationSubscriptionDmiInEventMapper.java @@ -28,12 +28,12 @@ import java.util.Map; import java.util.Set; import lombok.RequiredArgsConstructor; import org.onap.cps.ncmp.api.impl.events.cmsubscription.model.DmiCmNotificationSubscriptionPredicate; -import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence; import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.ncmp_to_dmi.CmHandle; import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.ncmp_to_dmi.CmNotificationSubscriptionDmiInEvent; import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.ncmp_to_dmi.Data; import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.ncmp_to_dmi.Predicate; import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.ncmp_to_dmi.ScopeFilter; +import org.onap.cps.ncmp.impl.inventory.InventoryPersistence; import org.springframework.stereotype.Component; @Component diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandler.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandler.java index 8274772d2c..3a49957864 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandler.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandler.java @@ -22,8 +22,8 @@ package org.onap.cps.ncmp.api.impl.events.lcm; import java.util.Collection; import java.util.Map; -import org.onap.cps.ncmp.api.impl.inventory.CmHandleState; -import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; +import org.onap.cps.ncmp.impl.inventory.models.CmHandleState; +import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; /** * The implementation of it should handle the persisting of composite state and delegate the request to publish the diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerAsyncHelper.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerAsyncHelper.java index 3742719e26..b7e6a7457c 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerAsyncHelper.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerAsyncHelper.java @@ -22,11 +22,11 @@ package org.onap.cps.ncmp.api.impl.events.lcm; import java.util.Collection; import lombok.RequiredArgsConstructor; -import org.onap.cps.ncmp.api.impl.utils.YangDataConverter; -import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; +import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle; import org.onap.cps.ncmp.events.lcm.v1.LcmEvent; import org.onap.cps.ncmp.events.lcm.v1.LcmEventHeader; +import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; +import org.onap.cps.ncmp.impl.utils.YangDataConverter; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerImpl.java index 0ed95adff2..97e5193512 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerImpl.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerImpl.java @@ -20,10 +20,10 @@ package org.onap.cps.ncmp.api.impl.events.lcm; -import static org.onap.cps.ncmp.api.impl.inventory.CmHandleState.ADVISED; -import static org.onap.cps.ncmp.api.impl.inventory.CmHandleState.DELETED; -import static org.onap.cps.ncmp.api.impl.inventory.CmHandleState.LOCKED; -import static org.onap.cps.ncmp.api.impl.inventory.CmHandleState.READY; +import static org.onap.cps.ncmp.impl.inventory.models.CmHandleState.ADVISED; +import static org.onap.cps.ncmp.impl.inventory.models.CmHandleState.DELETED; +import static org.onap.cps.ncmp.impl.inventory.models.CmHandleState.LOCKED; +import static org.onap.cps.ncmp.impl.inventory.models.CmHandleState.READY; import io.micrometer.core.annotation.Timed; import java.util.ArrayList; @@ -37,13 +37,13 @@ import lombok.NoArgsConstructor; import lombok.RequiredArgsConstructor; import lombok.Setter; import lombok.extern.slf4j.Slf4j; -import org.onap.cps.ncmp.api.impl.inventory.CmHandleState; -import org.onap.cps.ncmp.api.impl.inventory.CompositeState; -import org.onap.cps.ncmp.api.impl.inventory.CompositeStateUtils; -import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence; -import org.onap.cps.ncmp.api.impl.utils.YangDataConverter; -import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; +import org.onap.cps.ncmp.api.inventory.models.CompositeState; +import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle; +import org.onap.cps.ncmp.impl.inventory.CompositeStateUtils; +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.utils.YangDataConverter; import org.springframework.stereotype.Service; @Slf4j diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCreator.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCreator.java index fa27be158a..4231c99678 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCreator.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCreator.java @@ -27,7 +27,7 @@ import lombok.RequiredArgsConstructor; import lombok.Setter; import lombok.extern.slf4j.Slf4j; import org.onap.cps.ncmp.api.impl.utils.EventDateTimeFormatter; -import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; +import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle; import org.onap.cps.ncmp.events.lcm.v1.Event; import org.onap.cps.ncmp.events.lcm.v1.LcmEvent; import org.onap.cps.ncmp.events.lcm.v1.LcmEventHeader; @@ -128,4 +128,4 @@ public class LcmEventsCreator { private Values newValues; } -} \ No newline at end of file +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCreatorHelper.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCreatorHelper.java index 19d9ba5c0d..7c7a9722ce 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCreatorHelper.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCreatorHelper.java @@ -23,7 +23,7 @@ package org.onap.cps.ncmp.api.impl.events.lcm; import static org.onap.cps.ncmp.api.impl.events.lcm.LcmEventType.CREATE; import static org.onap.cps.ncmp.api.impl.events.lcm.LcmEventType.DELETE; import static org.onap.cps.ncmp.api.impl.events.lcm.LcmEventType.UPDATE; -import static org.onap.cps.ncmp.api.impl.inventory.CmHandleState.DELETED; +import static org.onap.cps.ncmp.impl.inventory.models.CmHandleState.DELETED; import com.google.common.collect.MapDifference; import com.google.common.collect.Maps; @@ -33,7 +33,7 @@ import java.util.Map; import lombok.AccessLevel; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; +import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle; import org.onap.cps.ncmp.events.lcm.v1.Values; /** diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueryService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueryService.java deleted file mode 100644 index 970c36bb63..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueryService.java +++ /dev/null @@ -1,105 +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.inventory; - -import java.util.Collection; -import java.util.List; -import java.util.Map; -import org.onap.cps.spi.FetchDescendantsOption; -import org.onap.cps.spi.model.DataNode; - -public interface CmHandleQueryService { - - /** - * Query Cm Handles based on additional (private) properties. - * - * @param additionalPropertyQueryPairs private properties for query - * @return Ids of Cm Handles which have these private properties - */ - Collection queryCmHandleAdditionalProperties(Map additionalPropertyQueryPairs); - - /** - * Query Cm Handles based on public properties. - * - * @param publicPropertyQueryPairs public properties for query - * @return CmHandles which have these public properties - */ - Collection queryCmHandlePublicProperties(Map publicPropertyQueryPairs); - - /** - * Query Cm Handles based on Trust Level. - * - * @param trustLevelPropertyQueryPairs trust level properties for query - * @return Ids of Cm Handles which have desired trust level - */ - Collection queryCmHandlesByTrustLevel(Map trustLevelPropertyQueryPairs); - - /** - * Method which returns cm handles by the cm handles state. - * - * @param cmHandleState cm handle state - * @return a list of data nodes representing the cm handles. - */ - List queryCmHandlesByState(CmHandleState cmHandleState); - - /** - * Method to return data nodes with ancestor representing the cm handles. - * - * @param cpsPath cps path for which the cmHandle is requested - * @return a list of data nodes representing the cm handles. - */ - List queryCmHandleAncestorsByCpsPath(String cpsPath, - FetchDescendantsOption fetchDescendantsOption); - - /** - * Method to return data nodes representing the cm handles. - * - * @param cpsPath cps path for which the cmHandle is requested - * @return a list of data nodes representing the cm handles. - */ - List queryNcmpRegistryByCpsPath(String cpsPath, FetchDescendantsOption fetchDescendantsOption); - - /** - * Method to check the state of a cm handle with given id. - * - * @param cmHandleId cm handle id - * @param requiredCmHandleState the required state of the cm handle - * @return a boolean, true if the state is equal to the required state - */ - boolean cmHandleHasState(String cmHandleId, CmHandleState requiredCmHandleState); - - /** - * Method which returns cm handles by the operational sync state of cm handle. - * - * @param dataStoreSyncState sync state - * @return a list of data nodes representing the cm handles. - */ - List queryCmHandlesByOperationalSyncState(DataStoreSyncState dataStoreSyncState); - - /** - * Get all cm handles ids by DMI plugin identifier. - * - * @param dmiPluginIdentifier DMI plugin identifier - * @return collection of cm handle ids - */ - Collection getCmHandleIdsByDmiPluginIdentifier(String dmiPluginIdentifier); - -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueryServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueryServiceImpl.java deleted file mode 100644 index 4350cc6fdf..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueryServiceImpl.java +++ /dev/null @@ -1,192 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022-2024 Nordix Foundation - * 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.inventory; - -import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME; -import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR; -import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT; -import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS; -import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS; - -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import lombok.RequiredArgsConstructor; -import org.onap.cps.ncmp.api.impl.config.embeddedcache.TrustLevelCacheConfig; -import org.onap.cps.ncmp.api.impl.inventory.enums.PropertyType; -import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevel; -import org.onap.cps.spi.CpsDataPersistenceService; -import org.onap.cps.spi.FetchDescendantsOption; -import org.onap.cps.spi.model.DataNode; -import org.onap.cps.spi.utils.CpsValidator; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.stereotype.Component; - -@RequiredArgsConstructor -@Component -public class CmHandleQueryServiceImpl implements CmHandleQueryService { - - private static final String DESCENDANT_PATH = "//"; - private static final String ANCESTOR_CM_HANDLES = "/ancestor::cm-handles"; - private final CpsDataPersistenceService cpsDataPersistenceService; - - @Qualifier(TrustLevelCacheConfig.TRUST_LEVEL_PER_DMI_PLUGIN) - private final Map trustLevelPerDmiPlugin; - - @Qualifier(TrustLevelCacheConfig.TRUST_LEVEL_PER_CM_HANDLE) - private final Map trustLevelPerCmHandle; - - private final CpsValidator cpsValidator; - - @Override - public Collection queryCmHandleAdditionalProperties(final Map privatePropertyQueryPairs) { - return queryCmHandleAnyProperties(privatePropertyQueryPairs, PropertyType.ADDITIONAL); - } - - @Override - public Collection queryCmHandlePublicProperties(final Map publicPropertyQueryPairs) { - return queryCmHandleAnyProperties(publicPropertyQueryPairs, PropertyType.PUBLIC); - } - - @Override - public Collection queryCmHandlesByTrustLevel(final Map trustLevelPropertyQueryPairs) { - final String trustLevelProperty = trustLevelPropertyQueryPairs.values().iterator().next(); - final TrustLevel targetTrustLevel = TrustLevel.valueOf(trustLevelProperty); - - return getCmHandleIdsByTrustLevel(targetTrustLevel); - } - - @Override - public List queryCmHandlesByState(final CmHandleState cmHandleState) { - return queryCmHandleAncestorsByCpsPath("//state[@cm-handle-state=\"" + cmHandleState + "\"]", - INCLUDE_ALL_DESCENDANTS); - } - - @Override - public List queryNcmpRegistryByCpsPath(final String cpsPath, - final FetchDescendantsOption fetchDescendantsOption) { - return cpsDataPersistenceService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, - cpsPath, fetchDescendantsOption); - } - - @Override - public List queryCmHandleAncestorsByCpsPath(final String cpsPath, - final FetchDescendantsOption fetchDescendantsOption) { - return queryNcmpRegistryByCpsPath(cpsPath + ANCESTOR_CM_HANDLES, fetchDescendantsOption); - } - - @Override - public boolean cmHandleHasState(final String cmHandleId, final CmHandleState requiredCmHandleState) { - final DataNode stateDataNode = getCmHandleState(cmHandleId); - final String cmHandleStateAsString = (String) stateDataNode.getLeaves().get("cm-handle-state"); - return CmHandleState.valueOf(cmHandleStateAsString).equals(requiredCmHandleState); - } - - @Override - public List queryCmHandlesByOperationalSyncState(final DataStoreSyncState dataStoreSyncState) { - return queryCmHandleAncestorsByCpsPath("//state/datastores" + "/operational[@sync-state=\"" - + dataStoreSyncState + "\"]", FetchDescendantsOption.OMIT_DESCENDANTS); - } - - @Override - public Collection getCmHandleIdsByDmiPluginIdentifier(final String dmiPluginIdentifier) { - final Collection cmHandleIds = new HashSet<>(); - for (final ModelledDmiServiceLeaves modelledDmiServiceLeaf : ModelledDmiServiceLeaves.values()) { - for (final DataNode cmHandleAsDataNode: getCmHandlesByDmiPluginIdentifierAndDmiProperty( - dmiPluginIdentifier, - modelledDmiServiceLeaf.getLeafName())) { - cmHandleIds.add(cmHandleAsDataNode.getLeaves().get("id").toString()); - } - } - return cmHandleIds; - } - - private Collection getCmHandleIdsByTrustLevel(final TrustLevel targetTrustLevel) { - final Collection selectedCmHandleIds = new HashSet<>(); - - for (final Map.Entry mapEntry : trustLevelPerDmiPlugin.entrySet()) { - final String dmiPluginIdentifier = mapEntry.getKey(); - final TrustLevel dmiTrustLevel = mapEntry.getValue(); - final Collection candidateCmHandleIds = getCmHandleIdsByDmiPluginIdentifier(dmiPluginIdentifier); - for (final String candidateCmHandleId : candidateCmHandleIds) { - final TrustLevel candidateCmHandleTrustLevel = trustLevelPerCmHandle.get(candidateCmHandleId); - final TrustLevel effectiveTrustlevel = - candidateCmHandleTrustLevel.getEffectiveTrustLevel(dmiTrustLevel); - if (targetTrustLevel.equals(effectiveTrustlevel)) { - selectedCmHandleIds.add(candidateCmHandleId); - } - } - } - - return selectedCmHandleIds; - } - - private Collection collectCmHandleIdsFromDataNodes(final Collection dataNodes) { - return dataNodes.stream().map(dataNode -> (String) dataNode.getLeaves().get("id")).collect(Collectors.toSet()); - } - - private Collection queryCmHandleAnyProperties( - final Map propertyQueryPairs, - final PropertyType propertyType) { - if (propertyQueryPairs.isEmpty()) { - return Collections.emptySet(); - } - Collection cmHandleIds = null; - for (final Map.Entry publicPropertyQueryPair : propertyQueryPairs.entrySet()) { - final String cpsPath = DESCENDANT_PATH + propertyType.getYangContainerName() + "[@name=\"" - + publicPropertyQueryPair.getKey() - + "\" and @value=\"" + publicPropertyQueryPair.getValue() + "\"]"; - - final Collection dataNodes = queryCmHandleAncestorsByCpsPath(cpsPath, - OMIT_DESCENDANTS); - if (cmHandleIds == null) { - cmHandleIds = collectCmHandleIdsFromDataNodes(dataNodes); - } else { - final Collection cmHandleIdsToRetain = collectCmHandleIdsFromDataNodes(dataNodes); - cmHandleIds.retainAll(cmHandleIdsToRetain); - } - if (cmHandleIds.isEmpty()) { - break; - } - } - return cmHandleIds; - } - - private List getCmHandlesByDmiPluginIdentifierAndDmiProperty(final String dmiPluginIdentifier, - final String dmiProperty) { - return cpsDataPersistenceService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, - NCMP_DMI_REGISTRY_PARENT + "/cm-handles[@" + dmiProperty + "='" + dmiPluginIdentifier + "']", - OMIT_DESCENDANTS); - } - - private DataNode getCmHandleState(final String cmHandleId) { - cpsValidator.validateNameCharacters(cmHandleId); - final String xpath = NCMP_DMI_REGISTRY_PARENT + "/cm-handles[@id='" + cmHandleId + "']/state"; - return cpsDataPersistenceService.getDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, - xpath, OMIT_DESCENDANTS).iterator().next(); - } -} - - diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleState.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleState.java deleted file mode 100644 index 5485ee7e80..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleState.java +++ /dev/null @@ -1,25 +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.inventory; - -public enum CmHandleState { - ADVISED, READY, LOCKED, DELETING, DELETED -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeState.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeState.java deleted file mode 100644 index 5b88f560eb..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeState.java +++ /dev/null @@ -1,144 +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.inventory; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.time.OffsetDateTime; -import java.time.format.DateTimeFormatter; -import lombok.Builder; -import lombok.Data; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -/** - * State Model to store state corresponding to the Yang resource dmi-registry model. - */ -@Getter -@Setter -@NoArgsConstructor -@JsonInclude(JsonInclude.Include.NON_NULL) -public class CompositeState { - - @JsonProperty("cm-handle-state") - private CmHandleState cmHandleState; - - @JsonProperty("lock-reason") - private LockReason lockReason; - - @JsonProperty("last-update-time") - private String lastUpdateTime; - - @JsonProperty("data-sync-enabled") - private Boolean dataSyncEnabled; - - @JsonProperty("datastores") - private DataStores dataStores; - - /** - * Date and Time in the format of yyyy-MM-dd'T'HH:mm:ss.SSSZ - */ - private static final DateTimeFormatter dateTimeFormatter = - DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); - - /** - * Composite State copy constructor. - * - * @param compositeState Composite State - */ - public CompositeState(final CompositeState compositeState) { - this.cmHandleState = compositeState.getCmHandleState(); - this.lockReason = compositeState.getLockReason(); - this.lastUpdateTime = compositeState.getLastUpdateTime(); - this.dataSyncEnabled = compositeState.getDataSyncEnabled(); - this.dataStores = compositeState.getDataStores(); - } - - - /** - * This will specify the latest lock reason for a specific cm handle. If a cm handle is in a state other than LOCKED - * it specifies the last lock reason. - * This can be used to track retry attempts as part of the lock details. - */ - @Data - @Builder - @JsonInclude(JsonInclude.Include.NON_NULL) - public static class LockReason { - - @JsonProperty("reason") - private LockReasonCategory lockReasonCategory; - - @JsonProperty("details") - private String details; - - } - - @Data - @Builder - @JsonInclude(JsonInclude.Include.NON_NULL) - public static class DataStores { - - @JsonProperty("operational") - private Operational operationalDataStore; - } - - @Data - @Builder - @JsonInclude(JsonInclude.Include.NON_NULL) - public static class Operational { - - @JsonProperty("sync-state") - private DataStoreSyncState dataStoreSyncState; - - @JsonProperty("last-sync-time") - private String lastSyncTime; - } - - @Data - @Builder - @JsonInclude(JsonInclude.Include.NON_NULL) - public static class Running { - - @JsonProperty("sync-state") - private String syncState; - - @JsonProperty("last-sync-time") - private String lastSyncTime; - } - - /** - * The date and time format used for the cm handle sync state. - * - * @return the date and time in the format of yyyy-MM-dd'T'HH:mm:ss.SSSZ - */ - public static String nowInSyncTimeFormat() { - return dateTimeFormatter.format(OffsetDateTime.now()); - } - - /** - * Sets the last updated date and time for the cm handle sync state. - */ - public void setLastUpdateTimeNow() { - lastUpdateTime = CompositeState.nowInSyncTimeFormat(); - } - -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeStateBuilder.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeStateBuilder.java deleted file mode 100644 index 2fbe2b2f78..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeStateBuilder.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022 Bell Canada - * Modifications 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.inventory; - -import org.onap.cps.ncmp.api.impl.inventory.CompositeState.DataStores; -import org.onap.cps.ncmp.api.impl.inventory.CompositeState.LockReason; -import org.onap.cps.ncmp.api.impl.inventory.CompositeState.Operational; -import org.onap.cps.spi.model.DataNode; - -public class CompositeStateBuilder { - - private CmHandleState cmHandleState; - private LockReason lockReason; - private DataStores datastores; - private String lastUpdatedTime; - private Boolean dataSyncEnabled; - - /** - * To create the {@link CompositeState}. - * - * @return {@link DataNode} - */ - public CompositeState build() { - final CompositeState compositeState = new CompositeState(); - compositeState.setCmHandleState(cmHandleState); - compositeState.setLockReason(lockReason); - compositeState.setDataStores(datastores); - compositeState.setLastUpdateTime(lastUpdatedTime); - compositeState.setDataSyncEnabled(dataSyncEnabled); - return compositeState; - } - - /** - * To use attributes for creating {@link CompositeState}. - * - * @param cmHandleState for the data node - * @return CompositeStateBuilder - */ - public CompositeStateBuilder withCmHandleState(final CmHandleState cmHandleState) { - this.cmHandleState = cmHandleState; - return this; - } - - /** - * To use attributes for creating {@link CompositeState}. - * - * @param reason for the locked state - * @param details for the locked state - * @return CompositeStateBuilder - */ - public CompositeStateBuilder withLockReason(final LockReasonCategory reason, final String details) { - this.lockReason = LockReason.builder().lockReasonCategory(reason).details(details).build(); - return this; - } - - /** - * To use attributes for creating {@link CompositeState}. - * - * @param time for the state change - * @return CompositeStateBuilder - */ - public CompositeStateBuilder withLastUpdatedTime(final String time) { - this.lastUpdatedTime = time; - return this; - } - - /** - * To use attributes for creating {@link CompositeState}. - * - * @return composite state builder - */ - public CompositeStateBuilder withLastUpdatedTimeNow() { - this.lastUpdatedTime = CompositeState.nowInSyncTimeFormat(); - return this; - } - - /** - * To use attributes for creating {@link CompositeState}. - * - * @param dataStoreSyncState for the locked state - * @param lastSyncTime for the locked state - * @return CompositeStateBuilder - */ - public CompositeStateBuilder withOperationalDataStores(final DataStoreSyncState dataStoreSyncState, - final String lastSyncTime) { - this.datastores = DataStores.builder().operationalDataStore( - Operational.builder().dataStoreSyncState(dataStoreSyncState).lastSyncTime(lastSyncTime).build()).build(); - return this; - } - - /** - * To use dataNode for creating {@link CompositeState}. - * - * @param dataNode for the dataNode - * @return CompositeState - */ - public CompositeStateBuilder fromDataNode(final DataNode dataNode) { - this.cmHandleState = CmHandleState.valueOf((String) dataNode.getLeaves() - .get("cm-handle-state")); - this.lastUpdatedTime = (String) dataNode.getLeaves().get("last-update-time"); - if (this.cmHandleState == CmHandleState.READY) { - this.dataSyncEnabled = (Boolean) dataNode.getLeaves().get("data-sync-enabled"); - } - for (final DataNode stateChildNode : dataNode.getChildDataNodes()) { - if (stateChildNode.getXpath().endsWith("/lock-reason")) { - this.lockReason = getLockReason(stateChildNode); - } - if (stateChildNode.getXpath().endsWith("/datastores")) { - for (final DataNode dataStoreNodes : stateChildNode.getChildDataNodes()) { - Operational operationalDataStore = null; - if (dataStoreNodes.getXpath().contains("/operational")) { - operationalDataStore = getOperationalDataStore(dataStoreNodes); - } - this.datastores = DataStores.builder().operationalDataStore(operationalDataStore).build(); - } - } - } - return this; - } - - private Operational getOperationalDataStore(final DataNode dataStoreNodes) { - return Operational.builder() - .dataStoreSyncState(DataStoreSyncState.valueOf((String) dataStoreNodes.getLeaves().get("sync-state"))) - .lastSyncTime((String) dataStoreNodes.getLeaves().get("last-sync-time")) - .build(); - } - - private LockReason getLockReason(final DataNode stateChildNode) { - final boolean isLockReasonExists = stateChildNode.getLeaves().containsKey("reason"); - return new LockReason(isLockReasonExists - ? LockReasonCategory.valueOf((String) stateChildNode.getLeaves().get("reason")) - : null, (String) stateChildNode.getLeaves().get("details")); - } - -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeStateUtils.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeStateUtils.java deleted file mode 100644 index 35ad54fdef..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeStateUtils.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.inventory; - -import lombok.AccessLevel; -import lombok.NoArgsConstructor; -import lombok.extern.slf4j.Slf4j; - -/** - * It will have all the utility method responsible for handling the composite state. - */ -@Slf4j -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public class CompositeStateUtils { - - /** - * Sets the cmHandleState to the provided state and updates the timestamp. - */ - public static void setCompositeState(final CmHandleState cmHandleState, - final CompositeState compositeState) { - compositeState.setCmHandleState(cmHandleState); - compositeState.setLastUpdateTimeNow(); - } - - /** - * Set the Operational datastore sync state based on the global flag. - */ - public static void setInitialDataStoreSyncState(final CompositeState compositeState) { - compositeState.setDataSyncEnabled(false); - final CompositeState.Operational operational = - getInitialDataStoreSyncState(compositeState.getDataSyncEnabled()); - final CompositeState.DataStores dataStores = - CompositeState.DataStores.builder().operationalDataStore(operational).build(); - compositeState.setDataStores(dataStores); - } - - /** - * Set the data sync enabled flag, along with the data store sync state based on this flag. - * - * @param dataSyncEnabled data sync enabled flag - * @param compositeState cm handle composite state - */ - public static void setDataSyncEnabledFlagWithDataSyncState(final boolean dataSyncEnabled, - final CompositeState compositeState) { - compositeState.setDataSyncEnabled(dataSyncEnabled); - compositeState.setLastUpdateTimeNow(); - final CompositeState.Operational operational = getInitialDataStoreSyncState(dataSyncEnabled); - final CompositeState.DataStores dataStores = - CompositeState.DataStores.builder().operationalDataStore(operational).build(); - compositeState.setDataStores(dataStores); - } - - /** - * Get initial data sync state based on data sync enabled boolean flag. - * - * @param dataSyncEnabled data sync enabled boolean flag - * @return the data store sync state - */ - private static CompositeState.Operational getInitialDataStoreSyncState(final boolean dataSyncEnabled) { - final DataStoreSyncState dataStoreSyncState = - dataSyncEnabled ? DataStoreSyncState.UNSYNCHRONIZED : DataStoreSyncState.NONE_REQUESTED; - return CompositeState.Operational.builder().dataStoreSyncState(dataStoreSyncState).build(); - } - - /** - * Sets the cmHandleState to ADVISED and retain the lock details. Used in retry scenarios. - */ - public static void setCompositeStateForRetry(final CompositeState compositeState) { - compositeState.setCmHandleState(CmHandleState.ADVISED); - compositeState.setLastUpdateTimeNow(); - final String oldLockReasonDetails = compositeState.getLockReason().getDetails(); - final CompositeState.LockReason lockReason = - CompositeState.LockReason.builder() - .lockReasonCategory(compositeState.getLockReason().getLockReasonCategory()) - .details(oldLockReasonDetails).build(); - compositeState.setLockReason(lockReason); - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/DataStoreSyncState.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/DataStoreSyncState.java deleted file mode 100644 index b92d152bfa..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/DataStoreSyncState.java +++ /dev/null @@ -1,25 +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.inventory; - -public enum DataStoreSyncState { - SYNCHRONIZED, UNSYNCHRONIZED, NONE_REQUESTED -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/InventoryPersistence.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/InventoryPersistence.java deleted file mode 100644 index e230b3fcb3..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/InventoryPersistence.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022-2024 Nordix Foundation - * 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.inventory; - -import java.util.Collection; -import java.util.List; -import java.util.Map; -import org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence; -import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.spi.model.DataNode; -import org.onap.cps.spi.model.ModuleDefinition; -import org.onap.cps.spi.model.ModuleReference; - -public interface InventoryPersistence extends NcmpPersistence { - - /** - * Get the Cm Handle Composite State from the data node. - * - * @param cmHandleId cm handle id - * @return the cm handle composite state - */ - CompositeState getCmHandleState(String cmHandleId); - - /** - * Save the cm handles state. - * - * @param cmHandleId cm handle id - * @param compositeState composite state - */ - void saveCmHandleState(String cmHandleId, CompositeState compositeState); - - /** - * Save all cm handles states in batch. - * - * @param cmHandleStatePerCmHandleId contains cm handle id and updated state - */ - void saveCmHandleStateBatch(Map cmHandleStatePerCmHandleId); - - /** - * This method retrieves DMI service name, DMI properties and the state for a given cm handle. - * - * @param cmHandleId the id of the cm handle - * @return yang model cm handle - */ - YangModelCmHandle getYangModelCmHandle(String cmHandleId); - - /** - * This method retrieves DMI service name, DMI properties and the state for a given cm handle. - * - * @param cmHandleIds a list of the ids of the cm handles - * @return collection of yang model cm handles - */ - Collection getYangModelCmHandles(Collection cmHandleIds); - - /** - * Method to return module definitions by cmHandleId. - * - * @param cmHandleId cm handle ID - * @return a collection of module definitions (moduleName, revision and yang resource content) - */ - Collection getModuleDefinitionsByCmHandleId(String cmHandleId); - - /** - * Method to return module definitions for the given parameters. - * - * @param cmHandleId cm-handle identifier - * @param moduleName module name - * @param moduleRevision the revision of the module - * @return list of module definitions (module name, revision, yang resource content) - */ - Collection getModuleDefinitionsByCmHandleAndModule(String cmHandleId, - String moduleName, - String moduleRevision); - - /** - * Method to return module references by cmHandleId. - * - * @param cmHandleId cm handle ID - * @return a collection of module references (moduleName and revision) - */ - Collection getYangResourcesModuleReferences(String cmHandleId); - - /** - * Method to save cmHandle. - * - * @param yangModelCmHandle cmHandle represented as Yang Model - */ - void saveCmHandle(YangModelCmHandle yangModelCmHandle); - - /** - * Method to save batch of cm handles. - * - * @param yangModelCmHandles cm handle represented as Yang Models - */ - void saveCmHandleBatch(List yangModelCmHandles); - - /** - * Get data node with the given cm handle id. - * - * @param cmHandleId cmHandle ID - * @return data node - */ - Collection getCmHandleDataNodeByCmHandleId(String cmHandleId); - - /** - * Get data node with the given alternate id. - * - * @param alternateId alternate ID - * @return data node - */ - DataNode getCmHandleDataNodeByAlternateId(String alternateId); - - /** - * Get collection of data nodes of given cm handles. - * - * @param cmHandleIds collection of cmHandle IDs - * @return collection of data nodes - */ - Collection getCmHandleDataNodes(Collection cmHandleIds); - - /** - * get CM handles that has given module names. - * - * @param moduleNamesForQuery module names - * @return Collection of CM handle Ids - */ - Collection getCmHandleIdsWithGivenModules(Collection moduleNamesForQuery); -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/InventoryPersistenceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/InventoryPersistenceImpl.java deleted file mode 100644 index 55fe35de2f..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/InventoryPersistenceImpl.java +++ /dev/null @@ -1,210 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022-2024 Nordix Foundation - * Modifications Copyright (C) 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.inventory; - -import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS; - -import com.google.common.collect.Lists; -import java.time.OffsetDateTime; -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.extern.slf4j.Slf4j; -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.utils.YangDataConverter; -import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.spi.FetchDescendantsOption; -import org.onap.cps.spi.exceptions.DataNodeNotFoundException; -import org.onap.cps.spi.exceptions.DataValidationException; -import org.onap.cps.spi.model.DataNode; -import org.onap.cps.spi.model.ModuleDefinition; -import org.onap.cps.spi.model.ModuleReference; -import org.onap.cps.spi.utils.CpsValidator; -import org.onap.cps.utils.JsonObjectMapper; -import org.springframework.stereotype.Component; - -@Slf4j -@Component -public class InventoryPersistenceImpl extends NcmpPersistenceImpl implements InventoryPersistence { - - private static final int CMHANDLE_BATCH_SIZE = 100; - - private final CpsModuleService cpsModuleService; - private final CpsAnchorService cpsAnchorService; - private final CpsValidator cpsValidator; - private final CmHandleQueryService cmHandleQueryService; - - /** - * initialize an inventory persistence object. - * - * @param jsonObjectMapper json mapper object - * @param cpsDataService cps data service instance - * @param cpsModuleService cps module service instance - * @param cpsValidator cps validation service instance - * @param cpsAnchorService cps anchor service instance - */ - public InventoryPersistenceImpl(final JsonObjectMapper jsonObjectMapper, final CpsDataService cpsDataService, - final CpsModuleService cpsModuleService, final CpsValidator cpsValidator, - final CpsAnchorService cpsAnchorService, - final CmHandleQueryService cmHandleQueryService) { - super(jsonObjectMapper, cpsDataService, cpsModuleService, cpsValidator); - this.cpsModuleService = cpsModuleService; - this.cpsAnchorService = cpsAnchorService; - this.cpsValidator = cpsValidator; - this.cmHandleQueryService = cmHandleQueryService; - } - - - @Override - public CompositeState getCmHandleState(final String cmHandleId) { - final DataNode stateAsDataNode = cpsDataService.getDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, - getXPathForCmHandleById(cmHandleId) + "/state", FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) - .iterator().next(); - cpsValidator.validateNameCharacters(cmHandleId); - return new CompositeStateBuilder().fromDataNode(stateAsDataNode).build(); - } - - @Override - public void saveCmHandleState(final String cmHandleId, final CompositeState compositeState) { - final String cmHandleJsonData = createStateJsonData(jsonObjectMapper.asJsonString(compositeState)); - cpsDataService.updateDataNodeAndDescendants(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, - getXPathForCmHandleById(cmHandleId), cmHandleJsonData, OffsetDateTime.now()); - } - - @Override - public void saveCmHandleStateBatch(final Map cmHandleStatePerCmHandleId) { - final Map cmHandlesJsonDataMap = new HashMap<>(); - cmHandleStatePerCmHandleId.forEach((cmHandleId, compositeState) -> cmHandlesJsonDataMap.put( - getXPathForCmHandleById(cmHandleId), - createStateJsonData(jsonObjectMapper.asJsonString(compositeState)))); - cpsDataService.updateDataNodesAndDescendants(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, - cmHandlesJsonDataMap, OffsetDateTime.now()); - } - - @Override - public YangModelCmHandle getYangModelCmHandle(final String cmHandleId) { - cpsValidator.validateNameCharacters(cmHandleId); - final DataNode dataNode = getCmHandleDataNodeByCmHandleId(cmHandleId).iterator().next(); - return YangDataConverter.convertCmHandleToYangModel(dataNode); - } - - @Override - public Collection getYangModelCmHandles(final Collection cmHandleIds) { - final Collection validCmHandleIds = new ArrayList<>(cmHandleIds.size()); - cmHandleIds.forEach(cmHandleId -> { - try { - cpsValidator.validateNameCharacters(cmHandleId); - validCmHandleIds.add(cmHandleId); - } catch (final DataValidationException dataValidationException) { - log.error("DataValidationException in CmHandleId {} to be ignored", - dataValidationException.getMessage()); - } - }); - return YangDataConverter.convertDataNodesToYangModelCmHandles(getCmHandleDataNodes(validCmHandleIds)); - } - - @Override - public Collection getModuleDefinitionsByCmHandleId(final String cmHandleId) { - return cpsModuleService.getModuleDefinitionsByAnchorName(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId); - } - - @Override - public Collection getModuleDefinitionsByCmHandleAndModule(final String cmHandleId, - final String moduleName, - final String moduleRevision) { - cpsValidator.validateNameCharacters(cmHandleId, moduleName); - return cpsModuleService.getModuleDefinitionsByAnchorAndModule(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, - cmHandleId, moduleName, moduleRevision); - } - - @Override - public Collection getYangResourcesModuleReferences(final String cmHandleId) { - cpsValidator.validateNameCharacters(cmHandleId); - return cpsModuleService.getYangResourcesModuleReferences(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId); - } - - @Override - public void saveCmHandle(final YangModelCmHandle yangModelCmHandle) { - saveCmHandleBatch(Collections.singletonList(yangModelCmHandle)); - } - - @Override - public void saveCmHandleBatch(final List yangModelCmHandles) { - for (final List yangModelCmHandleBatch : - Lists.partition(yangModelCmHandles, CMHANDLE_BATCH_SIZE)) { - final String cmHandlesJsonData = createCmHandlesJsonData(yangModelCmHandleBatch); - cpsDataService.saveListElements(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, - NCMP_DMI_REGISTRY_PARENT, cmHandlesJsonData, NO_TIMESTAMP); - } - } - - @Override - public Collection getCmHandleDataNodeByCmHandleId(final String cmHandleId) { - return this.getDataNode(getXPathForCmHandleById(cmHandleId)); - } - - @Override - public DataNode getCmHandleDataNodeByAlternateId(final String alternateId) { - final String cpsPathForCmHandleByAlternateId = getCpsPathForCmHandleByAlternateId(alternateId); - final Collection dataNodes = cmHandleQueryService - .queryNcmpRegistryByCpsPath(cpsPathForCmHandleByAlternateId, OMIT_DESCENDANTS); - if (dataNodes.isEmpty()) { - throw new DataNodeNotFoundException(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, - cpsPathForCmHandleByAlternateId); - } - return dataNodes.iterator().next(); - } - - @Override - public Collection getCmHandleDataNodes(final Collection cmHandleIds) { - final Collection xpaths = new ArrayList<>(cmHandleIds.size()); - cmHandleIds.forEach(cmHandleId -> xpaths.add(getXPathForCmHandleById(cmHandleId))); - return this.getDataNodes(xpaths); - } - - @Override - public Collection getCmHandleIdsWithGivenModules(final Collection moduleNamesForQuery) { - return cpsAnchorService.queryAnchorNames(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, moduleNamesForQuery); - } - - private static String getXPathForCmHandleById(final String cmHandleId) { - return NCMP_DMI_REGISTRY_PARENT + "/cm-handles[@id='" + cmHandleId + "']"; - } - - private static String getCpsPathForCmHandleByAlternateId(final String alternateId) { - return NCMP_DMI_REGISTRY_PARENT + "/cm-handles[@alternate-id='" + alternateId + "']"; - } - - private static String createStateJsonData(final String state) { - return "{\"state\":" + state + "}"; - } - - private String createCmHandlesJsonData(final List yangModelCmHandles) { - return "{\"cm-handles\":" + jsonObjectMapper.asJsonString(yangModelCmHandles) + "}"; - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/LockReasonCategory.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/LockReasonCategory.java deleted file mode 100644 index e2b2c6b4ae..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/LockReasonCategory.java +++ /dev/null @@ -1,28 +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.inventory; - -public enum LockReasonCategory { - MODULE_SYNC_FAILED, - MODULE_UPGRADE, - MODULE_UPGRADE_FAILED, - LOCKED_MISBEHAVING -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/ModelledDmiServiceLeaves.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/ModelledDmiServiceLeaves.java deleted file mode 100644 index b8a1ba02db..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/ModelledDmiServiceLeaves.java +++ /dev/null @@ -1,38 +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.inventory; - -public enum ModelledDmiServiceLeaves { - DMI_SERVICE_NAME("dmi-service-name"), - DMI_DATA_SERVICE_NAME("dmi-data-service-name"), - DMI_MODEL_SERVICE_NAME("dmi-model-service-name"); - - private String leafName; - - ModelledDmiServiceLeaves(final String dmiPluginIdentifierKey) { - this.leafName = dmiPluginIdentifierKey; - } - - public String getLeafName() { - return leafName; - } - -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/NcmpPersistenceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/NcmpPersistenceImpl.java deleted file mode 100644 index 6a2d6d810b..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/NcmpPersistenceImpl.java +++ /dev/null @@ -1,120 +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.inventory; - -import static org.onap.cps.spi.CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED; -import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS; - -import io.micrometer.core.annotation.Timed; -import java.util.Collection; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.onap.cps.api.CpsDataService; -import org.onap.cps.api.CpsModuleService; -import org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence; -import org.onap.cps.spi.FetchDescendantsOption; -import org.onap.cps.spi.exceptions.SchemaSetNotFoundException; -import org.onap.cps.spi.model.DataNode; -import org.onap.cps.spi.utils.CpsValidator; -import org.onap.cps.utils.JsonObjectMapper; -import org.springframework.stereotype.Component; - -@Slf4j -@RequiredArgsConstructor -@Component -public class NcmpPersistenceImpl implements NcmpPersistence { - - protected final JsonObjectMapper jsonObjectMapper; - protected final CpsDataService cpsDataService; - private final CpsModuleService cpsModuleService; - private final CpsValidator cpsValidator; - - @Override - public void deleteListOrListElement(final String listElementXpath) { - cpsDataService.deleteListOrListElement(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, listElementXpath, - NO_TIMESTAMP); - } - - @Override - @Timed(value = "cps.ncmp.inventory.persistence.schemaset.delete", - description = "Time taken to delete a schemaset") - public void deleteSchemaSetWithCascade(final String schemaSetName) { - try { - cpsValidator.validateNameCharacters(schemaSetName); - cpsModuleService.deleteSchemaSet(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, schemaSetName, - CASCADE_DELETE_ALLOWED); - } catch (final SchemaSetNotFoundException schemaSetNotFoundException) { - log.warn("Schema set {} does not exist or already deleted", schemaSetName); - } - } - - @Override - @Timed(value = "cps.ncmp.inventory.persistence.schemaset.delete.batch", - description = "Time taken to delete multiple schemaset") - public void deleteSchemaSetsWithCascade(final Collection schemaSetNames) { - cpsValidator.validateNameCharacters(schemaSetNames); - cpsModuleService.deleteSchemaSetsWithCascade(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, schemaSetNames); - } - - @Override - @Timed(value = "cps.ncmp.inventory.persistence.datanode.get", - description = "Time taken to get a data node (from ncmp dmi registry)") - public Collection getDataNode(final String xpath) { - return getDataNode(xpath, INCLUDE_ALL_DESCENDANTS); - } - - @Override - @Timed(value = "cps.ncmp.inventory.persistence.datanode.get", - description = "Time taken to get a data node (from ncmp dmi registry)") - public Collection getDataNode(final String xpath, final FetchDescendantsOption fetchDescendantsOption) { - return cpsDataService.getDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, xpath, - fetchDescendantsOption); - } - - @Override - public Collection getDataNodes(final Collection xpaths) { - return getDataNodes(xpaths, INCLUDE_ALL_DESCENDANTS); - } - - @Override - public Collection getDataNodes(final Collection xpaths, - final FetchDescendantsOption fetchDescendantsOption) { - return cpsDataService.getDataNodesForMultipleXpaths(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, xpaths, - fetchDescendantsOption); - } - - @Override - public void replaceListContent(final String parentNodeXpath, final Collection dataNodes) { - cpsDataService.replaceListContent(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, parentNodeXpath, dataNodes, - NO_TIMESTAMP); - } - - @Override - public void deleteDataNode(final String dataNodeXpath) { - cpsDataService.deleteDataNode(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, dataNodeXpath, NO_TIMESTAMP); - } - - @Override - public void deleteDataNodes(final Collection dataNodeXpaths) { - cpsDataService.deleteDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, dataNodeXpaths, NO_TIMESTAMP); - } - -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/enums/PropertyType.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/enums/PropertyType.java deleted file mode 100644 index 08bfe98e5c..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/enums/PropertyType.java +++ /dev/null @@ -1,34 +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.inventory.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -@Getter -@AllArgsConstructor -public enum PropertyType { - ADDITIONAL("additional-properties"), - PUBLIC("public-properties"), - DMI_PLUGIN("dmiPluginName"); - - private final String yangContainerName; -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/DataSyncWatchdog.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/DataSyncWatchdog.java deleted file mode 100644 index 6f089a57fb..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/DataSyncWatchdog.java +++ /dev/null @@ -1,102 +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.inventory.sync; - -import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME; - -import com.hazelcast.map.IMap; -import java.time.OffsetDateTime; -import java.util.concurrent.TimeUnit; -import java.util.function.Consumer; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.onap.cps.api.CpsDataService; -import org.onap.cps.ncmp.api.impl.config.embeddedcache.SynchronizationCacheConfig; -import org.onap.cps.ncmp.api.impl.inventory.CompositeState; -import org.onap.cps.ncmp.api.impl.inventory.DataStoreSyncState; -import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Service; - -@Slf4j -@RequiredArgsConstructor -@Service -public class DataSyncWatchdog { - - private static final boolean DATA_SYNC_IN_PROGRESS = false; - private static final boolean DATA_SYNC_DONE = true; - - private final InventoryPersistence inventoryPersistence; - - private final CpsDataService cpsDataService; - - private final ModuleOperationsUtils moduleOperationsUtils; - - private final IMap dataSyncSemaphores; - - /** - * Execute Cm Handle poll which queries the cm handle state in 'READY' and Operational Datastore Sync State in - * 'UNSYNCHRONIZED'. - */ - @Scheduled(fixedDelayString = "${ncmp.timers.cm-handle-data-sync.sleep-time-ms:30000}") - public void executeUnSynchronizedReadyCmHandlePoll() { - moduleOperationsUtils.getUnsynchronizedReadyCmHandles().forEach(unSynchronizedReadyCmHandle -> { - final String cmHandleId = unSynchronizedReadyCmHandle.getId(); - if (hasPushedIntoSemaphoreMap(cmHandleId)) { - log.debug("Executing data sync on {}", cmHandleId); - final CompositeState compositeState = inventoryPersistence - .getCmHandleState(cmHandleId); - final String resourceData = moduleOperationsUtils.getResourceData(cmHandleId); - if (resourceData == null) { - log.debug("Error retrieving resource data for Cm-Handle: {}", cmHandleId); - } else { - cpsDataService.saveData(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId, - resourceData, OffsetDateTime.now()); - setSyncStateToSynchronized().accept(compositeState); - inventoryPersistence.saveCmHandleState(cmHandleId, compositeState); - updateDataSyncSemaphoreMap(cmHandleId); - } - } else { - log.debug("{} already processed by another instance", cmHandleId); - } - }); - log.debug("No Cm-Handles currently found in READY State and Operational Sync State is UNSYNCHRONIZED"); - } - - private Consumer setSyncStateToSynchronized() { - return compositeState -> { - compositeState.setLastUpdateTimeNow(); - compositeState.getDataStores() - .setOperationalDataStore(CompositeState.Operational.builder() - .dataStoreSyncState(DataStoreSyncState.SYNCHRONIZED) - .lastSyncTime(CompositeState.nowInSyncTimeFormat()).build()); - }; - } - - private void updateDataSyncSemaphoreMap(final String cmHandleId) { - dataSyncSemaphores.replace(cmHandleId, DATA_SYNC_DONE); - } - - private boolean hasPushedIntoSemaphoreMap(final String cmHandleId) { - return dataSyncSemaphores.putIfAbsent(cmHandleId, DATA_SYNC_IN_PROGRESS, - SynchronizationCacheConfig.DATA_SYNC_SEMAPHORE_TTL_SECS, TimeUnit.SECONDS) == null; - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleOperationsUtils.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleOperationsUtils.java deleted file mode 100644 index e00a49f57a..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleOperationsUtils.java +++ /dev/null @@ -1,262 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022-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.inventory.sync; - -import com.fasterxml.jackson.databind.JsonNode; -import java.time.Duration; -import java.time.OffsetDateTime; -import java.time.format.DateTimeFormatter; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.UUID; -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.inventory.CmHandleQueryService; -import org.onap.cps.ncmp.api.impl.inventory.CmHandleState; -import org.onap.cps.ncmp.api.impl.inventory.CompositeState; -import org.onap.cps.ncmp.api.impl.inventory.DataStoreSyncState; -import org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory; -import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations; -import org.onap.cps.ncmp.api.impl.utils.YangDataConverter; -import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.spi.FetchDescendantsOption; -import org.onap.cps.spi.model.DataNode; -import org.onap.cps.utils.JsonObjectMapper; -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Service; - -@Slf4j -@Service -@RequiredArgsConstructor -public class ModuleOperationsUtils { - - private final CmHandleQueryService cmHandleQueryService; - private final DmiDataOperations dmiDataOperations; - private final JsonObjectMapper jsonObjectMapper; - private static final String RETRY_ATTEMPT_KEY = "attempt"; - private static final String MODULE_SET_TAG_KEY = "moduleSetTag"; - public static final String MODULE_SET_TAG_MESSAGE_FORMAT = "Upgrade to ModuleSetTag: %s"; - private static final String LOCK_REASON_DETAILS_MSG_FORMAT = - MODULE_SET_TAG_MESSAGE_FORMAT + " Attempt #%d failed: %s"; - private static final Pattern retryAttemptPattern = Pattern.compile("Attempt #(\\d+) failed:.+"); - private static final Pattern moduleSetTagPattern = Pattern.compile("Upgrade to ModuleSetTag: (\\S+)"); - private static final String CPS_PATH_CM_HANDLES_MODEL_SYNC_FAILED_OR_UPGRADE = """ - //lock-reason[@reason="MODULE_SYNC_FAILED" - or @reason="MODULE_UPGRADE" - or @reason="MODULE_UPGRADE_FAILED"]"""; - - /** - * Query data nodes for cm handles with an "ADVISED" cm handle state. - * - * @return cm handles (data nodes) in ADVISED state (empty list if none found) - */ - public List getAdvisedCmHandles() { - final List advisedCmHandlesAsDataNodes = - cmHandleQueryService.queryCmHandlesByState(CmHandleState.ADVISED); - log.debug("Total number of fetched advised cm handle(s) is (are) {}", advisedCmHandlesAsDataNodes.size()); - return advisedCmHandlesAsDataNodes; - } - - /** - * First query data nodes for cm handles with CM Handle Operational Sync State in "UNSYNCHRONIZED" and - * randomly select a CM Handle and query the data nodes for CM Handle State in "READY". - * - * @return a randomized yang model cm handle list with State in READY and Operation Sync State in "UNSYNCHRONIZED", - * return empty list if not found - */ - public List getUnsynchronizedReadyCmHandles() { - final List unsynchronizedCmHandles = cmHandleQueryService - .queryCmHandlesByOperationalSyncState(DataStoreSyncState.UNSYNCHRONIZED); - - final List yangModelCmHandles = new ArrayList<>(); - for (final DataNode unsynchronizedCmHandle : unsynchronizedCmHandles) { - final String cmHandleId = unsynchronizedCmHandle.getLeaves().get("id").toString(); - if (cmHandleQueryService.cmHandleHasState(cmHandleId, CmHandleState.READY)) { - yangModelCmHandles.addAll(convertCmHandlesDataNodesToYangModelCmHandles( - Collections.singletonList(unsynchronizedCmHandle))); - } - } - Collections.shuffle(yangModelCmHandles); - return yangModelCmHandles; - } - - /** - * Query data nodes for cm handles with an "LOCKED" cm handle state with reason. - * - * @return a random LOCKED yang model cm handle, return null if not found - */ - public List getCmHandlesThatFailedModelSyncOrUpgrade() { - final List lockedCmHandlesAsDataNodeList - = cmHandleQueryService.queryCmHandleAncestorsByCpsPath(CPS_PATH_CM_HANDLES_MODEL_SYNC_FAILED_OR_UPGRADE, - FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS); - return convertCmHandlesDataNodesToYangModelCmHandles(lockedCmHandlesAsDataNodeList); - } - - /** - * Update Composite State attempts counter and set new lock reason and details. - * - * @param lockReasonCategory lock reason category - * @param errorMessage error message - */ - public void updateLockReasonDetailsAndAttempts(final CompositeState compositeState, - final LockReasonCategory lockReasonCategory, - final String errorMessage) { - int attempt = 1; - final Map compositeStateDetails - = getLockedCompositeStateDetails(compositeState.getLockReason()); - if (!compositeStateDetails.isEmpty() && compositeStateDetails.containsKey(RETRY_ATTEMPT_KEY)) { - attempt = 1 + Integer.parseInt(compositeStateDetails.get(RETRY_ATTEMPT_KEY)); - } - final String moduleSetTag = compositeStateDetails.getOrDefault(MODULE_SET_TAG_KEY, ""); - compositeState.setLockReason(CompositeState.LockReason.builder() - .details(String.format(LOCK_REASON_DETAILS_MSG_FORMAT, moduleSetTag, attempt, errorMessage)) - .lockReasonCategory(lockReasonCategory) - .build()); - } - - /** - * Extract lock reason details as key-value pair. - * - * @param compositeStateLockReason lock reason having all the details - * @return a map of lock reason details - */ - public static Map getLockedCompositeStateDetails(final CompositeState.LockReason - compositeStateLockReason) { - if (compositeStateLockReason != null) { - final Map compositeStateDetails = new HashMap<>(2); - final String lockedCompositeStateReasonDetails = compositeStateLockReason.getDetails(); - final Matcher retryAttemptMatcher = retryAttemptPattern.matcher(lockedCompositeStateReasonDetails); - if (retryAttemptMatcher.find()) { - final int attemptsRegexGroupId = 1; - compositeStateDetails.put(RETRY_ATTEMPT_KEY, retryAttemptMatcher.group(attemptsRegexGroupId)); - } - final Matcher moduleSetTagMatcher = moduleSetTagPattern.matcher(lockedCompositeStateReasonDetails); - if (moduleSetTagMatcher.find()) { - final int moduleSetTagRegexGroupId = 1; - compositeStateDetails.put(MODULE_SET_TAG_KEY, moduleSetTagMatcher.group(moduleSetTagRegexGroupId)); - } - return compositeStateDetails; - } - return Collections.emptyMap(); - } - - - /** - * Check if a module sync retry is needed. - * - * @param compositeState the composite state currently in the locked state - * @return if the retry mechanism should be attempted - */ - public boolean needsModuleSyncRetryOrUpgrade(final CompositeState compositeState) { - final OffsetDateTime time = OffsetDateTime.parse(compositeState.getLastUpdateTime(), - DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ")); - final CompositeState.LockReason lockReason = compositeState.getLockReason(); - - final boolean moduleUpgrade = LockReasonCategory.MODULE_UPGRADE == lockReason.getLockReasonCategory(); - if (moduleUpgrade) { - log.info("Locked for module upgrade"); - return true; - } - - final boolean failedDuringModuleSync = LockReasonCategory.MODULE_SYNC_FAILED - == lockReason.getLockReasonCategory(); - final boolean failedDuringModuleUpgrade = LockReasonCategory.MODULE_UPGRADE_FAILED - == lockReason.getLockReasonCategory(); - - if (failedDuringModuleSync || failedDuringModuleUpgrade) { - log.info("Locked for module {} (last attempt failed).", failedDuringModuleSync ? "sync" : "upgrade"); - return isRetryDue(lockReason, time); - } - log.info("Locked for other reason"); - return false; - } - - /** - * Get the Resource Data from Node through DMI Passthrough service. - * - * @param cmHandleId cm handle id - * @return optional string containing the resource data - */ - public String getResourceData(final String cmHandleId) { - final ResponseEntity resourceDataResponseEntity = dmiDataOperations.getAllResourceDataFromDmi( - cmHandleId, UUID.randomUUID().toString()); - if (resourceDataResponseEntity.getStatusCode().is2xxSuccessful()) { - return getFirstResource(resourceDataResponseEntity.getBody()); - } - return null; - } - - /** - * Checks if cm handle state module is in upgrade or upgrade failed. - * - * @param compositeState current lock reason of cm handle - * @return true or false based on lock reason category - */ - public static boolean inUpgradeOrUpgradeFailed(final CompositeState compositeState) { - return compositeState.getLockReason() != null - && (LockReasonCategory.MODULE_UPGRADE.equals(compositeState.getLockReason().getLockReasonCategory()) - || LockReasonCategory.MODULE_UPGRADE_FAILED.equals(compositeState.getLockReason() - .getLockReasonCategory())); - } - - public static String getUpgradedModuleSetTagFromLockReason(final CompositeState.LockReason lockReason) { - return getLockedCompositeStateDetails(lockReason).getOrDefault(MODULE_SET_TAG_KEY, ""); - } - - private String getFirstResource(final Object responseBody) { - final String jsonObjectAsString = jsonObjectMapper.asJsonString(responseBody); - final JsonNode overallJsonNode = jsonObjectMapper.convertToJsonNode(jsonObjectAsString); - final Iterator> overallJsonTreeMap = overallJsonNode.fields(); - final Map.Entry firstElement = overallJsonTreeMap.next(); - return jsonObjectMapper.asJsonString(Map.of(firstElement.getKey(), firstElement.getValue())); - } - - private List convertCmHandlesDataNodesToYangModelCmHandles( - final List cmHandlesAsDataNodeList) { - return cmHandlesAsDataNodeList.stream().map(YangDataConverter::convertCmHandleToYangModel).toList(); - } - - private boolean isRetryDue(final CompositeState.LockReason compositeStateLockReason, final OffsetDateTime time) { - final int timeInMinutesUntilNextAttempt; - final Map compositeStateDetails = getLockedCompositeStateDetails(compositeStateLockReason); - if (compositeStateDetails.isEmpty()) { - timeInMinutesUntilNextAttempt = 1; - log.info("First Attempt: no current attempts found."); - } else { - timeInMinutesUntilNextAttempt = (int) Math.pow(2, Integer.parseInt(compositeStateDetails - .get(RETRY_ATTEMPT_KEY))); - } - final int timeSinceLastAttempt = (int) Duration.between(time, OffsetDateTime.now()).toMinutes(); - if (timeInMinutesUntilNextAttempt >= timeSinceLastAttempt) { - log.info("Time until next attempt is {} minutes: ", timeInMinutesUntilNextAttempt - timeSinceLastAttempt); - return false; - } - log.info("Retry due now"); - return true; - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncService.java deleted file mode 100644 index a5f0ba017f..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncService.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022-2024 Nordix Foundation - * Modifications Copyright (C) 2024 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.inventory.sync; - -import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME; -import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR; -import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT; -import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME; - -import java.time.OffsetDateTime; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import lombok.AllArgsConstructor; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -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.inventory.CmHandleQueryService; -import org.onap.cps.ncmp.api.impl.inventory.CmHandleState; -import org.onap.cps.ncmp.api.impl.operations.DmiModelOperations; -import org.onap.cps.ncmp.api.impl.utils.YangDataConverter; -import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.spi.CascadeDeleteAllowed; -import org.onap.cps.spi.FetchDescendantsOption; -import org.onap.cps.spi.exceptions.SchemaSetNotFoundException; -import org.onap.cps.spi.model.DataNode; -import org.onap.cps.spi.model.ModuleReference; -import org.onap.cps.utils.ContentType; -import org.onap.cps.utils.JsonObjectMapper; -import org.springframework.stereotype.Service; - -@Slf4j -@Service -@RequiredArgsConstructor -public class ModuleSyncService { - - private final DmiModelOperations dmiModelOperations; - private final CpsModuleService cpsModuleService; - private final CmHandleQueryService cmHandleQueryService; - private final CpsDataService cpsDataService; - private final CpsAnchorService cpsAnchorService; - private final JsonObjectMapper jsonObjectMapper; - private static final Map NO_NEW_MODULES = Collections.emptyMap(); - - @AllArgsConstructor - private static final class ModuleDelta { - Collection allModuleReferences; - Map newModuleNameToContentMap; - } - - /** - * This method creates a cm handle and initiates modules sync. - * - * @param yangModelCmHandle the yang model of cm handle. - */ - public void syncAndCreateSchemaSetAndAnchor(final YangModelCmHandle yangModelCmHandle) { - final ModuleDelta moduleDelta = getModuleDelta(yangModelCmHandle, yangModelCmHandle.getModuleSetTag()); - final String cmHandleId = yangModelCmHandle.getId(); - cpsModuleService.createSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId, - moduleDelta.newModuleNameToContentMap, moduleDelta.allModuleReferences); - cpsAnchorService.createAnchor(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId, cmHandleId); - } - - /** - * This method upgrades a cm handle and initiates modules sync. - * - * @param yangModelCmHandle the yang model of cm handle. - */ - public void syncAndUpgradeSchemaSet(final YangModelCmHandle yangModelCmHandle) { - final String upgradedModuleSetTag = ModuleOperationsUtils.getUpgradedModuleSetTagFromLockReason( - yangModelCmHandle.getCompositeState().getLockReason()); - final ModuleDelta moduleDelta = getModuleDelta(yangModelCmHandle, upgradedModuleSetTag); - cpsModuleService.upgradeSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, - yangModelCmHandle.getId(), moduleDelta.newModuleNameToContentMap, moduleDelta.allModuleReferences); - setCmHandleModuleSetTag(yangModelCmHandle, upgradedModuleSetTag); - } - - /** - * Deletes the SchemaSet for schema set id if the SchemaSet Exists. - * - * @param schemaSetId the schema set id to be deleted - */ - public void deleteSchemaSetIfExists(final String schemaSetId) { - try { - cpsModuleService.deleteSchemaSet(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, schemaSetId, - CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED); - log.debug("SchemaSet for {} has been deleted. Ready to be recreated.", schemaSetId); - } catch (final SchemaSetNotFoundException e) { - log.debug("No SchemaSet for {}. Assuming CmHandle has not been previously Module Synced.", schemaSetId); - } - } - - private ModuleDelta getModuleDelta(final YangModelCmHandle yangModelCmHandle, final String targetModuleSetTag) { - final Collection allModuleReferences; - final Map newYangResources; - - final YangModelCmHandle cmHandleWithSameModuleSetTag = getAnyReadyCmHandleByModuleSetTag(targetModuleSetTag); - if (cmHandleWithSameModuleSetTag == null) { - allModuleReferences = dmiModelOperations.getModuleReferences(yangModelCmHandle); - newYangResources = dmiModelOperations.getNewYangResourcesFromDmi(yangModelCmHandle, - cpsModuleService.identifyNewModuleReferences(allModuleReferences)); - } else { - log.info("Found other cm handle having same module set tag: {}", targetModuleSetTag); - allModuleReferences = cpsModuleService.getYangResourcesModuleReferences( - NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleWithSameModuleSetTag.getId()); - newYangResources = NO_NEW_MODULES; - } - return new ModuleDelta(allModuleReferences, newYangResources); - } - - private YangModelCmHandle getAnyReadyCmHandleByModuleSetTag(final String moduleSetTag) { - if (StringUtils.isBlank(moduleSetTag)) { - return null; - } - final String escapedModuleSetTag = moduleSetTag.replace("'", "''"); - final List dataNodes = cmHandleQueryService.queryNcmpRegistryByCpsPath( - NCMP_DMI_REGISTRY_PARENT + "/cm-handles[@module-set-tag='" + escapedModuleSetTag + "']", - FetchDescendantsOption.DIRECT_CHILDREN_ONLY); - return dataNodes.stream().map(YangDataConverter::convertCmHandleToYangModel) - .filter(cmHandle -> cmHandle.getCompositeState().getCmHandleState() == CmHandleState.READY) - .findFirst().orElse(null); - } - - private void setCmHandleModuleSetTag(final YangModelCmHandle yangModelCmHandle, final String newModuleSetTag) { - final String jsonForUpdate = jsonObjectMapper.asJsonString(Map.of( - "cm-handles", Map.of("id", yangModelCmHandle.getId(), "module-set-tag", newModuleSetTag))); - cpsDataService.updateNodeLeaves(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, NCMP_DMI_REGISTRY_PARENT, - jsonForUpdate, OffsetDateTime.now(), ContentType.JSON); - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncTasks.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncTasks.java deleted file mode 100644 index 590cb56c48..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncTasks.java +++ /dev/null @@ -1,131 +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.inventory.sync; - -import com.hazelcast.map.IMap; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.atomic.AtomicInteger; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.onap.cps.ncmp.api.impl.events.lcm.LcmEventsCmHandleStateHandler; -import org.onap.cps.ncmp.api.impl.inventory.CmHandleState; -import org.onap.cps.ncmp.api.impl.inventory.CompositeState; -import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence; -import org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory; -import org.onap.cps.ncmp.api.impl.utils.YangDataConverter; -import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.spi.model.DataNode; -import org.springframework.stereotype.Component; - -@RequiredArgsConstructor -@Component -@Slf4j -public class ModuleSyncTasks { - private final InventoryPersistence inventoryPersistence; - private final ModuleOperationsUtils moduleOperationsUtils; - private final ModuleSyncService moduleSyncService; - private final LcmEventsCmHandleStateHandler lcmEventsCmHandleStateHandler; - private final IMap moduleSyncStartedOnCmHandles; - - /** - * Perform module sync on a batch of cm handles. - * - * @param cmHandlesAsDataNodes a batch of Data nodes representing cm handles to perform module sync on - * @param batchCounter the number of batches currently being processed, will be decreased when - * task is finished or fails - * @return completed future to handle post-processing - */ - public CompletableFuture performModuleSync(final Collection cmHandlesAsDataNodes, - final AtomicInteger batchCounter) { - try { - final Map cmHandelStatePerCmHandle - = new HashMap<>(cmHandlesAsDataNodes.size()); - for (final DataNode cmHandleAsDataNode : cmHandlesAsDataNodes) { - final String cmHandleId = String.valueOf(cmHandleAsDataNode.getLeaves().get("id")); - final YangModelCmHandle yangModelCmHandle = - YangDataConverter.convertCmHandleToYangModel(cmHandleAsDataNode); - final CompositeState compositeState = inventoryPersistence.getCmHandleState(cmHandleId); - final boolean inUpgrade = ModuleOperationsUtils.inUpgradeOrUpgradeFailed(compositeState); - try { - if (inUpgrade) { - moduleSyncService.syncAndUpgradeSchemaSet(yangModelCmHandle); - } else { - moduleSyncService.deleteSchemaSetIfExists(cmHandleId); - moduleSyncService.syncAndCreateSchemaSetAndAnchor(yangModelCmHandle); - } - yangModelCmHandle.getCompositeState().setLockReason(null); - cmHandelStatePerCmHandle.put(yangModelCmHandle, CmHandleState.READY); - } catch (final Exception e) { - log.warn("Processing of {} module failed due to reason {}.", cmHandleId, e.getMessage()); - final LockReasonCategory lockReasonCategory = inUpgrade ? LockReasonCategory.MODULE_UPGRADE_FAILED - : LockReasonCategory.MODULE_SYNC_FAILED; - moduleOperationsUtils.updateLockReasonDetailsAndAttempts(compositeState, - lockReasonCategory, e.getMessage()); - setCmHandleStateLocked(yangModelCmHandle, compositeState.getLockReason()); - cmHandelStatePerCmHandle.put(yangModelCmHandle, CmHandleState.LOCKED); - } - log.info("{} is now in {} state", cmHandleId, cmHandelStatePerCmHandle.get(yangModelCmHandle).name()); - } - lcmEventsCmHandleStateHandler.updateCmHandleStateBatch(cmHandelStatePerCmHandle); - } finally { - batchCounter.getAndDecrement(); - log.info("Processing module sync batch finished. {} batch(es) active.", batchCounter.get()); - } - return CompletableFuture.completedFuture(null); - } - - /** - * Reset state to "ADVISED" for any previously failed cm handles. - * - * @param failedCmHandles previously failed (locked) cm handles - */ - public void resetFailedCmHandles(final List failedCmHandles) { - final Map cmHandleStatePerCmHandle = new HashMap<>(failedCmHandles.size()); - for (final YangModelCmHandle failedCmHandle : failedCmHandles) { - final CompositeState compositeState = failedCmHandle.getCompositeState(); - final boolean isReadyForRetry = moduleOperationsUtils.needsModuleSyncRetryOrUpgrade(compositeState); - log.info("Retry for cmHandleId : {} is {}", failedCmHandle.getId(), isReadyForRetry); - if (isReadyForRetry) { - final String resetCmHandleId = failedCmHandle.getId(); - log.debug("Reset cm handle {} state to ADVISED to be re-attempted by module-sync watchdog", - resetCmHandleId); - cmHandleStatePerCmHandle.put(failedCmHandle, CmHandleState.ADVISED); - removeResetCmHandleFromModuleSyncMap(resetCmHandleId); - } - } - lcmEventsCmHandleStateHandler.updateCmHandleStateBatch(cmHandleStatePerCmHandle); - } - - private void setCmHandleStateLocked(final YangModelCmHandle advisedCmHandle, - final CompositeState.LockReason lockReason) { - advisedCmHandle.getCompositeState().setLockReason(lockReason); - } - - private void removeResetCmHandleFromModuleSyncMap(final String resetCmHandleId) { - if (moduleSyncStartedOnCmHandles.remove(resetCmHandleId) != null) { - log.info("{} removed from in progress map", resetCmHandleId); - } - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncWatchdog.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncWatchdog.java deleted file mode 100644 index 249232d230..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncWatchdog.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022-2023 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.inventory.sync; - -import com.hazelcast.map.IMap; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.onap.cps.ncmp.api.impl.config.embeddedcache.SynchronizationCacheConfig; -import org.onap.cps.ncmp.api.impl.inventory.sync.executor.AsyncTaskExecutor; -import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.spi.model.DataNode; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Service; - -@Slf4j -@RequiredArgsConstructor -@Service -public class ModuleSyncWatchdog { - - private final ModuleOperationsUtils moduleOperationsUtils; - private final BlockingQueue moduleSyncWorkQueue; - private final IMap moduleSyncStartedOnCmHandles; - private final ModuleSyncTasks moduleSyncTasks; - private final AsyncTaskExecutor asyncTaskExecutor; - private static final int MODULE_SYNC_BATCH_SIZE = 100; - private static final long PREVENT_CPU_BURN_WAIT_TIME_MILLIS = 10; - private static final String VALUE_FOR_HAZELCAST_IN_PROGRESS_MAP = "Started"; - private static final long ASYNC_TASK_TIMEOUT_IN_MILLISECONDS = TimeUnit.MINUTES.toMillis(5); - @Getter - private AtomicInteger batchCounter = new AtomicInteger(1); - - /** - * Check DB for any cm handles in 'ADVISED' state. - * Queue and create batches to process them asynchronously. - * This method will only finish when there are no more 'ADVISED' cm handles in the DB. - * This method wil be triggered on a configurable interval - */ - @Scheduled(fixedDelayString = "${ncmp.timers.advised-modules-sync.sleep-time-ms:5000}") - public void moduleSyncAdvisedCmHandles() { - log.info("Processing module sync watchdog waking up."); - populateWorkQueueIfNeeded(); - while (!moduleSyncWorkQueue.isEmpty()) { - if (batchCounter.get() <= asyncTaskExecutor.getAsyncTaskParallelismLevel()) { - final Collection nextBatch = prepareNextBatch(); - log.info("Processing module sync batch of {}. {} batch(es) active.", - nextBatch.size(), batchCounter.get()); - if (!nextBatch.isEmpty()) { - asyncTaskExecutor.executeTask(() -> - moduleSyncTasks.performModuleSync(nextBatch, batchCounter), - ASYNC_TASK_TIMEOUT_IN_MILLISECONDS); - batchCounter.getAndIncrement(); - } - } else { - preventBusyWait(); - } - } - } - - /** - * Find any failed (locked) cm handles and change state back to 'ADVISED'. - */ - @Scheduled(fixedDelayString = "${ncmp.timers.locked-modules-sync.sleep-time-ms:300000}") - public void resetPreviouslyFailedCmHandles() { - log.info("Processing module sync retry-watchdog waking up."); - final List failedCmHandles - = moduleOperationsUtils.getCmHandlesThatFailedModelSyncOrUpgrade(); - log.info("Retrying {} cmHandles", failedCmHandles.size()); - moduleSyncTasks.resetFailedCmHandles(failedCmHandles); - } - - private void preventBusyWait() { - try { - log.info("Busy waiting now"); - TimeUnit.MILLISECONDS.sleep(PREVENT_CPU_BURN_WAIT_TIME_MILLIS); - } catch (final InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - - private void populateWorkQueueIfNeeded() { - if (moduleSyncWorkQueue.isEmpty()) { - final List advisedCmHandles = moduleOperationsUtils.getAdvisedCmHandles(); - log.info("Processing module sync fetched {} advised cm handles from DB", advisedCmHandles.size()); - for (final DataNode advisedCmHandle : advisedCmHandles) { - if (!moduleSyncWorkQueue.offer(advisedCmHandle)) { - log.warn("Unable to add cm handle {} to the work queue", advisedCmHandle.getLeaves().get("id")); - } - } - log.info("Work Queue Size : {}", moduleSyncWorkQueue.size()); - } - } - - private Collection prepareNextBatch() { - final Collection nextBatchCandidates = new HashSet<>(MODULE_SYNC_BATCH_SIZE); - final Collection nextBatch = new HashSet<>(MODULE_SYNC_BATCH_SIZE); - moduleSyncWorkQueue.drainTo(nextBatchCandidates, MODULE_SYNC_BATCH_SIZE); - log.info("nextBatchCandidates size : {}", nextBatchCandidates.size()); - for (final DataNode batchCandidate : nextBatchCandidates) { - final String cmHandleId = String.valueOf(batchCandidate.getLeaves().get("id")); - final boolean alreadyAddedToInProgressMap = VALUE_FOR_HAZELCAST_IN_PROGRESS_MAP.equals( - moduleSyncStartedOnCmHandles.putIfAbsent(cmHandleId, VALUE_FOR_HAZELCAST_IN_PROGRESS_MAP, - SynchronizationCacheConfig.MODULE_SYNC_STARTED_TTL_SECS, TimeUnit.SECONDS)); - if (alreadyAddedToInProgressMap) { - log.info("module sync for {} already in progress by other instance", cmHandleId); - } else { - log.info("Adding cmHandle : {} to current batch", cmHandleId); - nextBatch.add(batchCandidate); - } - } - log.debug("nextBatch size : {}", nextBatch.size()); - return nextBatch; - } - -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/config/WatchdogSchedulingConfigurer.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/config/WatchdogSchedulingConfigurer.java deleted file mode 100644 index 1aaee2708f..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/config/WatchdogSchedulingConfigurer.java +++ /dev/null @@ -1,56 +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.inventory.sync.config; - -import java.util.concurrent.ThreadPoolExecutor; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.scheduling.TaskScheduler; -import org.springframework.scheduling.annotation.EnableScheduling; -import org.springframework.scheduling.annotation.SchedulingConfigurer; -import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; -import org.springframework.scheduling.config.ScheduledTaskRegistrar; - -@Configuration -@EnableScheduling -public class WatchdogSchedulingConfigurer implements SchedulingConfigurer { - - @Override - public void configureTasks(final ScheduledTaskRegistrar scheduledTaskRegistrar) { - scheduledTaskRegistrar.setTaskScheduler(taskScheduler()); - } - - /** - * Implementation of Spring's {@link TaskScheduler} interface, wrapping - * a native {@link org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler} for watchdogs. - */ - @Bean - public TaskScheduler taskScheduler() { - final ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler(); - taskScheduler.setPoolSize(10); - taskScheduler.setThreadNamePrefix("watchdog-th-"); - taskScheduler.setAwaitTerminationSeconds(60); - taskScheduler.setWaitForTasksToCompleteOnShutdown(true); - taskScheduler.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy()); - taskScheduler.initialize(); - return taskScheduler; - } -} \ No newline at end of file diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/executor/AsyncTaskExecutor.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/executor/AsyncTaskExecutor.java deleted file mode 100644 index 2d5e7a1abc..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/executor/AsyncTaskExecutor.java +++ /dev/null @@ -1,77 +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.inventory.sync.executor; - -import static java.util.concurrent.TimeUnit.MILLISECONDS; - -import jakarta.annotation.PostConstruct; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeoutException; -import java.util.function.Supplier; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Service; - -@Slf4j -@Service -public class AsyncTaskExecutor { - - @Value("${ncmp.modules-sync-watchdog.async-executor.parallelism-level:10}") - @Getter - private int asyncTaskParallelismLevel; - private ExecutorService executorService; - private static final int DEFAULT_PARALLELISM_LEVEL = 10; - - /** - * Set up executor service with thread-pool size as per configuration parameter. - * If modules-sync-watchdog.async-executor.parallelism-level not set a default of 10 threads will be applied. - */ - @PostConstruct - public void setupThreadPool() { - executorService = Executors.newWorkStealingPool( - asyncTaskParallelismLevel == 0 ? DEFAULT_PARALLELISM_LEVEL : asyncTaskParallelismLevel); - } - - /** - * Execute supplied task asynchronously. - * - * @param taskSupplier functional method is get() task need to executed asynchronously - * @param timeOutInMillis the task timeout value in milliseconds - */ - public void executeTask(final Supplier taskSupplier, final long timeOutInMillis) { - CompletableFuture.supplyAsync(taskSupplier::get, executorService) - .orTimeout(timeOutInMillis, MILLISECONDS) - .whenCompleteAsync(this::handleTaskCompletion); - } - - private void handleTaskCompletion(final Object response, final Throwable throwable) { - if (throwable != null) { - if (throwable instanceof TimeoutException) { - log.warn("Async task didn't completed within the required time."); - } else { - log.debug("Watchdog async batch failed. caused by : {}", throwable.getMessage()); - } - } - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/ncmppersistence/NcmpPersistence.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/ncmppersistence/NcmpPersistence.java deleted file mode 100644 index d72b5d58f1..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/ncmppersistence/NcmpPersistence.java +++ /dev/null @@ -1,116 +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.ncmppersistence; - -import java.time.OffsetDateTime; -import java.util.Collection; -import org.onap.cps.spi.FetchDescendantsOption; -import org.onap.cps.spi.model.DataNode; - -/** - * DmiRegistryConstants class to be strictly used for DMI Related constants only. - */ -public interface NcmpPersistence { - - String NCMP_DATASPACE_NAME = "NCMP-Admin"; - String NCMP_DMI_REGISTRY_ANCHOR = "ncmp-dmi-registry"; - String NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME = "NFP-Operational"; - String NCMP_DMI_REGISTRY_PARENT = "/dmi-registry"; - OffsetDateTime NO_TIMESTAMP = null; - - /** - * Method to delete a list or a list element. - * - * @param listElementXpath list element xPath - */ - void deleteListOrListElement(String listElementXpath); - - /** - * Method to delete a schema set. - * - * @param schemaSetName schema set name - */ - void deleteSchemaSetWithCascade(String schemaSetName); - - /** - * Method to delete multiple schema sets. - * - * @param schemaSetNames schema set names - */ - void deleteSchemaSetsWithCascade(Collection schemaSetNames); - - /** - * Get data node via xpath. - * - * @param xpath xpath - * @return data node - */ - Collection getDataNode(String xpath); - - /** - * Get data node via xpath. - * - * @param xpath xpath - * @param fetchDescendantsOption fetch descendants option - * @return data node - */ - Collection getDataNode(String xpath, FetchDescendantsOption fetchDescendantsOption); - - /** - * Get collection of data nodes via xpaths. - * - * @param xpaths collection of xpaths - * @return collection of data nodes - */ - Collection getDataNodes(Collection xpaths); - - /** - * Get collection of data nodes via xpaths. - * - * @param xpaths collection of xpaths - * @param fetchDescendantsOption fetch descendants option - * @return collection of data nodes - */ - Collection getDataNodes(Collection xpaths, - FetchDescendantsOption fetchDescendantsOption); - - /** - * Replaces list content by removing all existing elements and inserting the given new elements as data nodes. - * - * @param parentNodeXpath parent node xpath - * @param dataNodes datanodes representing the updated data - */ - void replaceListContent(String parentNodeXpath, Collection dataNodes); - - /** - * Deletes data node. - * - * @param dataNodeXpath data node xpath - */ - void deleteDataNode(String dataNodeXpath); - - /** - * Deletes multiple data nodes. - * - * @param dataNodeXpaths data node xpaths - */ - void deleteDataNodes(Collection dataNodeXpaths); -} 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 index 7359518dc9..32fc8a5dbb 100644 --- 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 @@ -37,13 +37,13 @@ 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.inventory.CmHandleState; -import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence; 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.impl.yangmodels.YangModelCmHandle; 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; 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 index 82dccc66da..f1fdbea7f6 100644 --- 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 @@ -38,8 +38,8 @@ 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.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.ncmp.api.models.YangResource; +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; 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 index f1032f818f..f10b4f920f 100644 --- 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 @@ -28,7 +28,7 @@ import java.util.List; import java.util.Map; import lombok.Builder; import lombok.Getter; -import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; +import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; @JsonInclude(JsonInclude.Include.NON_NULL) @Getter diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevelManager.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevelManager.java index 9d65a66d8d..d01acb8a3b 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevelManager.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevelManager.java @@ -26,9 +26,9 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.onap.cps.ncmp.api.impl.config.embeddedcache.TrustLevelCacheConfig; import org.onap.cps.ncmp.api.impl.events.avc.ncmptoclient.AvcEventPublisher; -import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence; import org.onap.cps.ncmp.api.impl.operations.RequiredDmiService; -import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; +import org.onap.cps.ncmp.impl.inventory.InventoryPersistence; +import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; 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/api/impl/trustlevel/dmiavailability/DmiPluginWatchDog.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/dmiavailability/DmiPluginWatchDog.java index 1022512a6c..c5098936c9 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/dmiavailability/DmiPluginWatchDog.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/dmiavailability/DmiPluginWatchDog.java @@ -26,9 +26,9 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.onap.cps.ncmp.api.impl.client.DmiRestClient; import org.onap.cps.ncmp.api.impl.config.embeddedcache.TrustLevelCacheConfig; -import org.onap.cps.ncmp.api.impl.inventory.CmHandleQueryService; import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevel; import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevelManager; +import org.onap.cps.ncmp.impl.inventory.CmHandleQueryService; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; 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 index 60f39fcea0..7ddde643aa 100644 --- 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 @@ -27,9 +27,9 @@ import java.util.Set; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; -import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence; -import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; +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; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/CmHandleQueryConditions.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/CmHandleQueryConditions.java deleted file mode 100644 index a59776036a..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/CmHandleQueryConditions.java +++ /dev/null @@ -1,43 +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.utils; - -import java.util.Arrays; -import java.util.Collection; -import java.util.stream.Collectors; -import lombok.Getter; - -@Getter -public enum CmHandleQueryConditions { - HAS_ALL_PROPERTIES("hasAllProperties"), - HAS_ALL_MODULES("hasAllModules"), - WITH_CPS_PATH("cmHandleWithCpsPath"), - WITH_TRUST_LEVEL("cmHandleWithTrustLevel"); - - public static final Collection ALL_CONDITION_NAMES = Arrays.stream(CmHandleQueryConditions.values()) - .map(CmHandleQueryConditions::getConditionName).collect(Collectors.toList()); - - private final String conditionName; - - CmHandleQueryConditions(final String conditionName) { - this.conditionName = conditionName; - } -} 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 26e94866a1..533e15b918 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 @@ -28,7 +28,7 @@ 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.api.impl.yangmodels.YangModelCmHandle; +import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; @NoArgsConstructor(access = AccessLevel.PRIVATE) public class DmiServiceNameOrganizer { diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/InventoryQueryConditions.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/InventoryQueryConditions.java deleted file mode 100644 index 9437cf0bac..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/InventoryQueryConditions.java +++ /dev/null @@ -1,42 +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.utils; - -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; -import lombok.AllArgsConstructor; -import lombok.Getter; - -@Getter -@AllArgsConstructor -public enum InventoryQueryConditions { - - HAS_ALL_PROPERTIES("hasAllProperties"), - HAS_ALL_ADDITIONAL_PROPERTIES("hasAllAdditionalProperties"), - CM_HANDLE_WITH_DMI_PLUGIN("cmHandleWithDmiPlugin"); - - public static final List ALL_CONDITION_NAMES = Arrays.stream(InventoryQueryConditions.values()) - .map(InventoryQueryConditions::getName).collect(Collectors.toList()); - - private final String name; - -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/RestQueryParametersValidator.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/RestQueryParametersValidator.java deleted file mode 100644 index 2ef97cab5c..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/RestQueryParametersValidator.java +++ /dev/null @@ -1,125 +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.utils; - -import com.google.common.base.Strings; -import java.util.Collection; -import java.util.Map; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.onap.cps.ncmp.api.models.CmHandleQueryServiceParameters; -import org.onap.cps.spi.exceptions.DataValidationException; - -@Slf4j -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public class RestQueryParametersValidator { - - /** - * Validate query parameters. - * - * @param cmHandleQueryServiceParameters name of data to be validated - * @param validConditionNames valid condition names - */ - public static void validateCmHandleQueryParameters( - final CmHandleQueryServiceParameters cmHandleQueryServiceParameters, - final Collection validConditionNames) { - cmHandleQueryServiceParameters.getCmHandleQueryParameters().forEach( - cmHandleQueryParameter -> { - if (validConditionNames.stream().noneMatch(validConditionName -> - validConditionName.equals(cmHandleQueryParameter.getConditionName()))) { - throw createDataValidationException( - String.format("Wrong 'conditionName': %s - please supply a valid name.", - cmHandleQueryParameter.getConditionName())); - } - if (cmHandleQueryParameter.getConditionParameters().isEmpty()) { - throw createDataValidationException( - "Empty 'conditionsParameters' - please supply a valid condition parameter."); - } - cmHandleQueryParameter.getConditionParameters().forEach( - RestQueryParametersValidator::validateConditionParameter - ); - } - ); - } - - private static void validateConditionParameter(final Map conditionParameter) { - if (conditionParameter.isEmpty()) { - throw createDataValidationException( - "Empty 'conditionsParameter' - please supply a valid condition parameter."); - } - if (conditionParameter.size() > 1) { - throw createDataValidationException("Too many names in one 'conditionsParameter' -" - + " please supply one name in one condition parameter."); - } - conditionParameter.forEach((key, value) -> { - if (Strings.isNullOrEmpty(key)) { - throw createDataValidationException( - "Missing 'conditionsParameterName' - please supply a valid name."); - } - }); - } - - /** - * Validate module name condition properties. - * @param conditionProperty name of data to be validated - */ - public static void validateModuleNameConditionProperties(final Map conditionProperty) { - if (conditionProperty.containsKey("moduleName") && !conditionProperty.get("moduleName").isEmpty()) { - return; - } - throw createDataValidationException("Wrong module condition property. - " - + "please supply a valid condition property."); - } - - /** - * Validate CPS path condition properties. - * @param conditionProperty name of data to be validated - */ - public static boolean validateCpsPathConditionProperties(final Map conditionProperty) { - if (conditionProperty.isEmpty()) { - return true; - } - if (conditionProperty.size() > 1) { - throw createDataValidationException("Only one condition property is allowed for the CPS path query."); - } - if (!conditionProperty.containsKey("cpsPath")) { - throw createDataValidationException( - "Wrong CPS path condition property. - expecting \"cpsPath\" as the condition property."); - } - final String cpsPath = conditionProperty.get("cpsPath"); - if (cpsPath.isBlank()) { - throw createDataValidationException( - "Wrong CPS path. - please supply a valid CPS path."); - } - if (cpsPath.contains("/additional-properties")) { - log.debug("{} - Private metadata cannot be queried. Nothing to be returned", - cpsPath); - return false; - } - return true; - } - - private static DataValidationException createDataValidationException(final String details) { - return new DataValidationException("Invalid Query Parameter.", details); - } - -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/YangDataConverter.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/YangDataConverter.java deleted file mode 100644 index 07b92892a9..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/YangDataConverter.java +++ /dev/null @@ -1,159 +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.utils; - -import java.util.Collection; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.onap.cps.ncmp.api.impl.inventory.CompositeState; -import org.onap.cps.ncmp.api.impl.inventory.CompositeStateBuilder; -import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; -import org.onap.cps.spi.model.DataNode; - -@NoArgsConstructor(access = AccessLevel.PRIVATE) -@Slf4j -public class YangDataConverter { - - private static final Pattern cmHandleIdInXpathPattern = Pattern.compile("\\[@id='(.*?)']"); - - /** - * This method convert yang model cm handle to ncmp service cm handle. - * @param yangModelCmHandle the yang model of the cm handle - * @return ncmp service cm handle - */ - public static NcmpServiceCmHandle convertYangModelCmHandleToNcmpServiceCmHandle( - final YangModelCmHandle yangModelCmHandle) { - final NcmpServiceCmHandle ncmpServiceCmHandle = new NcmpServiceCmHandle(); - final List dmiProperties = yangModelCmHandle.getDmiProperties(); - final List publicProperties = yangModelCmHandle.getPublicProperties(); - ncmpServiceCmHandle.setCmHandleId(yangModelCmHandle.getId()); - ncmpServiceCmHandle.setCompositeState(yangModelCmHandle.getCompositeState()); - ncmpServiceCmHandle.setModuleSetTag(yangModelCmHandle.getModuleSetTag()); - ncmpServiceCmHandle.setAlternateId(yangModelCmHandle.getAlternateId()); - ncmpServiceCmHandle.setDataProducerIdentifier(yangModelCmHandle.getDataProducerIdentifier()); - setDmiProperties(dmiProperties, ncmpServiceCmHandle); - setPublicProperties(publicProperties, ncmpServiceCmHandle); - return ncmpServiceCmHandle; - } - - /** - * This method convert yang model cm handle properties to simple map. - * @param properties the yang model cm handle properties - * @param propertiesMap the String, String map for the results - */ - public static void asPropertiesMap(final List properties, - final Map propertiesMap) { - for (final YangModelCmHandle.Property property : properties) { - propertiesMap.put(property.getName(), property.getValue()); - } - } - - /** - * This method convert cm handle data node to yang model cm handle. - * @param cmHandleDataNode the datanode of the cm handle - * @return yang model cm handle - */ - public static YangModelCmHandle convertCmHandleToYangModel(final DataNode cmHandleDataNode) { - final NcmpServiceCmHandle ncmpServiceCmHandle = new NcmpServiceCmHandle(); - final String cmHandleId = cmHandleDataNode.getLeaves().get("id").toString(); - ncmpServiceCmHandle.setCmHandleId(cmHandleId); - populateCmHandleDetails(cmHandleDataNode, ncmpServiceCmHandle); - return YangModelCmHandle.toYangModelCmHandle( - (String) cmHandleDataNode.getLeaves().get("dmi-service-name"), - (String) cmHandleDataNode.getLeaves().get("dmi-data-service-name"), - (String) cmHandleDataNode.getLeaves().get("dmi-model-service-name"), - ncmpServiceCmHandle, - (String) cmHandleDataNode.getLeaves().get("module-set-tag"), - (String) cmHandleDataNode.getLeaves().get("alternate-id"), - (String) cmHandleDataNode.getLeaves().get("data-producer-identifier") - ); - } - - /** - * This method convert cm handle data nodes to yang model cm handles. - * @param cmHandleDataNodes the datanode of the cm handle - * @return yang model cm handles - */ - public static Collection convertDataNodesToYangModelCmHandles( - final Collection cmHandleDataNodes) { - return cmHandleDataNodes.stream().map(YangDataConverter::convertCmHandleToYangModel) - .collect(Collectors.toList()); - } - - /** - * This method extract cm handle id from xpath of data node. - * @param xpath for data node of the cm handle - * @return cm handle Id - */ - public static String extractCmHandleIdFromXpath(final String xpath) { - final Matcher matcher = cmHandleIdInXpathPattern.matcher(xpath); - matcher.find(); - return matcher.group(1); - } - - - private static void populateCmHandleDetails(final DataNode cmHandleDataNode, - final NcmpServiceCmHandle ncmpServiceCmHandle) { - final Map dmiProperties = new LinkedHashMap<>(); - final Map publicProperties = new LinkedHashMap<>(); - final CompositeStateBuilder compositeStateBuilder = new CompositeStateBuilder(); - CompositeState compositeState = compositeStateBuilder.build(); - for (final DataNode childDataNode: cmHandleDataNode.getChildDataNodes()) { - if (childDataNode.getXpath().contains("/additional-properties[@name=")) { - addProperty(childDataNode, dmiProperties); - } else if (childDataNode.getXpath().contains("/public-properties[@name=")) { - addProperty(childDataNode, publicProperties); - } else if (childDataNode.getXpath().endsWith("/state")) { - compositeState = compositeStateBuilder.fromDataNode(childDataNode).build(); - } - } - ncmpServiceCmHandle.setDmiProperties(dmiProperties); - ncmpServiceCmHandle.setPublicProperties(publicProperties); - ncmpServiceCmHandle.setCompositeState(compositeState); - } - - private static void addProperty(final DataNode propertyDataNode, final Map propertiesAsMap) { - propertiesAsMap.put(String.valueOf(propertyDataNode.getLeaves().get("name")), - String.valueOf(propertyDataNode.getLeaves().get("value"))); - } - - private static void setDmiProperties(final List dmiProperties, - final NcmpServiceCmHandle ncmpServiceCmHandle) { - final Map dmiPropertiesMap = new LinkedHashMap<>(dmiProperties.size()); - asPropertiesMap(dmiProperties, dmiPropertiesMap); - ncmpServiceCmHandle.setDmiProperties(dmiPropertiesMap); - } - - private static void setPublicProperties(final List publicProperties, - final NcmpServiceCmHandle ncmpServiceCmHandle) { - final Map publicPropertiesMap = new LinkedHashMap<>(); - asPropertiesMap(publicProperties, publicPropertiesMap); - ncmpServiceCmHandle.setPublicProperties(publicPropertiesMap); - } -} 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 index 407fcf034e..bb0c9a3150 100644 --- 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 @@ -37,14 +37,14 @@ 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.inventory.CmHandleState; 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.impl.yangmodels.YangModelCmHandle; 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; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandle.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandle.java deleted file mode 100644 index 2ca2b2eb0d..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandle.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2021-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.yangmodels; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonInclude.Include; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import org.apache.commons.lang3.StringUtils; -import org.onap.cps.ncmp.api.impl.inventory.CompositeState; -import org.onap.cps.ncmp.api.impl.operations.RequiredDmiService; -import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; - -/** - * Cm Handle which follows the Yang resource dmi registry model when persisting data to DMI or the DB. - * Yang model CmHandle - */ -@Getter -@Setter -@NoArgsConstructor -@JsonInclude(Include.NON_NULL) -@EqualsAndHashCode(onlyExplicitlyIncluded = true) -public class YangModelCmHandle { - - @EqualsAndHashCode.Include - private String id; - - @JsonProperty("dmi-service-name") - private String dmiServiceName; - - @JsonProperty("dmi-data-service-name") - private String dmiDataServiceName; - - @JsonProperty("state") - private CompositeState compositeState; - - @JsonProperty("dmi-model-service-name") - private String dmiModelServiceName; - - @JsonProperty("module-set-tag") - private String moduleSetTag; - - @JsonProperty("alternate-id") - private String alternateId; - - @JsonProperty("data-producer-identifier") - private String dataProducerIdentifier; - - @JsonProperty("additional-properties") - private List dmiProperties; - - @JsonProperty("public-properties") - private List publicProperties; - - /** - * Creates a deep copy of Yang Model Cm Handle. - * - * @param original Yang Model Cm Handle - * @return instance of yangModelCmHandle - */ - public static YangModelCmHandle deepCopyOf(final YangModelCmHandle original) { - final YangModelCmHandle copy = new YangModelCmHandle(); - copy.id = original.getId(); - copy.dmiServiceName = original.getDmiServiceName(); - copy.dmiDataServiceName = original.getDmiDataServiceName(); - copy.dmiModelServiceName = original.getDmiModelServiceName(); - copy.compositeState = - original.getCompositeState() == null ? null : new CompositeState(original.getCompositeState()); - copy.dmiProperties = original.getDmiProperties() == null ? null : new ArrayList<>(original.getDmiProperties()); - copy.publicProperties = - original.getPublicProperties() == null ? null : new ArrayList<>(original.getPublicProperties()); - copy.moduleSetTag = original.getModuleSetTag(); - copy.alternateId = original.getAlternateId(); - copy.dataProducerIdentifier = original.getDataProducerIdentifier(); - return copy; - } - - /** - * Create a yangModelCmHandle. - * - * @param dmiServiceName dmi service name - * @param dmiDataServiceName dmi data service name - * @param dmiModelServiceName dmi model service name - * @param ncmpServiceCmHandle the cm handle - * @param moduleSetTag moduleSetTag - * @param alternateId alternateId - * @param dataProducerIdentifier dataProducerIdentifier - * @return instance of yangModelCmHandle - */ - public static YangModelCmHandle toYangModelCmHandle(final String dmiServiceName, - final String dmiDataServiceName, - final String dmiModelServiceName, - final NcmpServiceCmHandle ncmpServiceCmHandle, - final String moduleSetTag, - final String alternateId, - final String dataProducerIdentifier) { - final YangModelCmHandle yangModelCmHandle = new YangModelCmHandle(); - yangModelCmHandle.setId(ncmpServiceCmHandle.getCmHandleId()); - yangModelCmHandle.setDmiServiceName(dmiServiceName); - yangModelCmHandle.setDmiDataServiceName(dmiDataServiceName); - yangModelCmHandle.setDmiModelServiceName(dmiModelServiceName); - yangModelCmHandle.setModuleSetTag(moduleSetTag == null ? StringUtils.EMPTY : moduleSetTag); - yangModelCmHandle.setAlternateId(alternateId == null ? StringUtils.EMPTY : alternateId); - yangModelCmHandle.setDataProducerIdentifier( - dataProducerIdentifier == null ? StringUtils.EMPTY : dataProducerIdentifier); - yangModelCmHandle.setDmiProperties(asYangModelCmHandleProperties(ncmpServiceCmHandle.getDmiProperties())); - yangModelCmHandle.setPublicProperties(asYangModelCmHandleProperties( - ncmpServiceCmHandle.getPublicProperties())); - yangModelCmHandle.setCompositeState(ncmpServiceCmHandle.getCompositeState()); - return yangModelCmHandle; - } - - /** - * Resolve a dmi service name. - * - * @param requiredService indicates what typo of service is required - * @return dmi service name - */ - public String resolveDmiServiceName(final RequiredDmiService requiredService) { - if (StringUtils.isBlank(dmiServiceName)) { - if (RequiredDmiService.DATA.equals(requiredService)) { - return dmiDataServiceName; - } - return dmiModelServiceName; - } - return dmiServiceName; - } - - private static List asYangModelCmHandleProperties(final Map propertiesAsMap) { - final List yangModelCmHandleProperties = new ArrayList<>(propertiesAsMap.size()); - for (final Map.Entry entry : propertiesAsMap.entrySet()) { - yangModelCmHandleProperties.add(new YangModelCmHandle.Property(entry.getKey(), entry.getValue())); - } - return yangModelCmHandleProperties; - } - - @AllArgsConstructor - @Data - public static class Property { - - @JsonProperty() - private final String name; - - @JsonProperty() - private final String value; - } - -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/NetworkCmProxyInventoryFacade.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/NetworkCmProxyInventoryFacade.java new file mode 100644 index 0000000000..0ff59c1316 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/NetworkCmProxyInventoryFacade.java @@ -0,0 +1,208 @@ +/* + * ============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.inventory; + +import static org.onap.cps.ncmp.impl.inventory.CmHandleQueryParametersValidator.validateCmHandleQueryParameters; + +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.onap.cps.ncmp.api.inventory.models.CmHandleQueryApiParameters; +import org.onap.cps.ncmp.api.inventory.models.CmHandleQueryServiceParameters; +import org.onap.cps.ncmp.api.inventory.models.CompositeState; +import org.onap.cps.ncmp.api.inventory.models.DmiPluginRegistration; +import org.onap.cps.ncmp.api.inventory.models.DmiPluginRegistrationResponse; +import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle; +import org.onap.cps.ncmp.impl.inventory.CmHandleQueryService; +import org.onap.cps.ncmp.impl.inventory.CmHandleRegistrationService; +import org.onap.cps.ncmp.impl.inventory.InventoryPersistence; +import org.onap.cps.ncmp.impl.inventory.ParameterizedCmHandleQueryService; +import org.onap.cps.ncmp.impl.inventory.models.CmHandleQueryConditions; +import org.onap.cps.ncmp.impl.inventory.models.InventoryQueryConditions; +import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; +import org.onap.cps.ncmp.impl.utils.YangDataConverter; +import org.onap.cps.spi.model.ModuleDefinition; +import org.onap.cps.spi.model.ModuleReference; +import org.onap.cps.utils.JsonObjectMapper; +import org.springframework.stereotype.Service; + +@Slf4j +@Service +@RequiredArgsConstructor +public class NetworkCmProxyInventoryFacade { + + private final CmHandleRegistrationService cmHandleRegistrationService; + private final CmHandleQueryService cmHandleQueryService; + private final ParameterizedCmHandleQueryService parameterizedCmHandleQueryService; + private final InventoryPersistence inventoryPersistence; + private final JsonObjectMapper jsonObjectMapper; + + /** + * Registration of Created, Removed, Updated or Upgraded CM Handles. + * + * @param dmiPluginRegistration Dmi Plugin Registration details + * @return dmiPluginRegistrationResponse + */ + + public DmiPluginRegistrationResponse updateDmiRegistrationAndSyncModule( + final DmiPluginRegistration dmiPluginRegistration) { + return cmHandleRegistrationService.updateDmiRegistrationAndSyncModule(dmiPluginRegistration); + } + + /** + * Get all cm handle IDs by DMI plugin identifier. + * + * @param dmiPluginIdentifier DMI plugin identifier + * @return collection of cm handle IDs + */ + public Collection getAllCmHandleIdsByDmiPluginIdentifier(final String dmiPluginIdentifier) { + return cmHandleQueryService.getCmHandleIdsByDmiPluginIdentifier(dmiPluginIdentifier); + } + + /** + * Get all cm handle IDs by various properties. + * + * @param cmHandleQueryServiceParameters cm handle query parameters + * @return collection of cm handle IDs + */ + public Collection executeParameterizedCmHandleIdSearch( + final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) { + validateCmHandleQueryParameters(cmHandleQueryServiceParameters, InventoryQueryConditions.ALL_CONDITION_NAMES); + return parameterizedCmHandleQueryService.queryCmHandleIdsForInventory(cmHandleQueryServiceParameters); + } + + + /** + * Retrieve module references for the given cm handle. + * + * @param cmHandleId cm handle identifier + * @return a collection of modules names and revisions + */ + public Collection getYangResourcesModuleReferences(final String cmHandleId) { + return inventoryPersistence.getYangResourcesModuleReferences(cmHandleId); + } + + /** + * Retrieve module definitions for the given cm handle. + * + * @param cmHandleId cm handle identifier + * @return a collection of module definition (moduleName, revision and yang resource content) + */ + public Collection getModuleDefinitionsByCmHandleId(final String cmHandleId) { + return inventoryPersistence.getModuleDefinitionsByCmHandleId(cmHandleId); + } + + /** + * Get module definitions for the given parameters. + * + * @param cmHandleId cm-handle identifier + * @param moduleName module name + * @param moduleRevision the revision of the module + * @return list of module definitions (module name, revision, yang resource content) + */ + public Collection getModuleDefinitionsByCmHandleAndModule(final String cmHandleId, + final String moduleName, + final String moduleRevision) { + return inventoryPersistence.getModuleDefinitionsByCmHandleAndModule(cmHandleId, moduleName, moduleRevision); + } + + /** + * Retrieve cm handles with details for the given query parameters. + * + * @param cmHandleQueryApiParameters cm handle query parameters + * @return cm handles with details + */ + public Collection executeCmHandleSearch( + final CmHandleQueryApiParameters cmHandleQueryApiParameters) { + final CmHandleQueryServiceParameters cmHandleQueryServiceParameters = jsonObjectMapper.convertToValueType( + cmHandleQueryApiParameters, CmHandleQueryServiceParameters.class); + validateCmHandleQueryParameters(cmHandleQueryServiceParameters, CmHandleQueryConditions.ALL_CONDITION_NAMES); + return parameterizedCmHandleQueryService.queryCmHandles(cmHandleQueryServiceParameters); + } + + /** + * Retrieve cm handle ids for the given query parameters. + * + * @param cmHandleQueryApiParameters cm handle query parameters + * @return cm handle ids + */ + public Collection executeCmHandleIdSearch(final CmHandleQueryApiParameters cmHandleQueryApiParameters) { + final CmHandleQueryServiceParameters cmHandleQueryServiceParameters = jsonObjectMapper.convertToValueType( + cmHandleQueryApiParameters, CmHandleQueryServiceParameters.class); + validateCmHandleQueryParameters(cmHandleQueryServiceParameters, CmHandleQueryConditions.ALL_CONDITION_NAMES); + return parameterizedCmHandleQueryService.queryCmHandleIds(cmHandleQueryServiceParameters); + } + + /** + * Set the data sync enabled flag, along with the data sync state + * based on the data sync enabled boolean for the cm handle id provided. + * + * @param cmHandleId cm handle id + * @param dataSyncEnabledTargetValue data sync enabled flag + */ + public void setDataSyncEnabled(final String cmHandleId, final Boolean dataSyncEnabledTargetValue) { + cmHandleRegistrationService.setDataSyncEnabled(cmHandleId, dataSyncEnabledTargetValue); + } + + /** + * Retrieve cm handle details for a given cm handle. + * + * @param cmHandleId cm handle identifier + * @return cm handle details + */ + public NcmpServiceCmHandle getNcmpServiceCmHandle(final String cmHandleId) { + return YangDataConverter.convertYangModelCmHandleToNcmpServiceCmHandle( + inventoryPersistence.getYangModelCmHandle(cmHandleId)); + } + + /** + * Get cm handle public properties for a given cm handle id. + * + * @param cmHandleId cm handle identifier + * @return cm handle public properties + */ + public Map getCmHandlePublicProperties(final String cmHandleId) { + final YangModelCmHandle yangModelCmHandle = inventoryPersistence.getYangModelCmHandle(cmHandleId); + final List yangModelPublicProperties = yangModelCmHandle.getPublicProperties(); + final Map cmHandlePublicProperties = new HashMap<>(); + YangDataConverter.asPropertiesMap(yangModelPublicProperties, cmHandlePublicProperties); + return cmHandlePublicProperties; + } + + /** + * Get cm handle composite state for a given cm handle id. + * + * @param cmHandleId cm handle identifier + * @return cm handle state + */ + public CompositeState getCmHandleCompositeState(final String cmHandleId) { + return inventoryPersistence.getYangModelCmHandle(cmHandleId).getCompositeState(); + } + + +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CmHandleQueryApiParameters.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CmHandleQueryApiParameters.java new file mode 100644 index 0000000000..596fb94a36 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CmHandleQueryApiParameters.java @@ -0,0 +1,43 @@ +/* + * ============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.inventory.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +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(Include.NON_EMPTY) +@JsonIgnoreProperties(ignoreUnknown = true) +public class CmHandleQueryApiParameters { + @JsonProperty("cmHandleQueryParameters") + @Valid + private List cmHandleQueryParameters = Collections.emptyList(); +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CmHandleQueryServiceParameters.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CmHandleQueryServiceParameters.java new file mode 100644 index 0000000000..13915918e5 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CmHandleQueryServiceParameters.java @@ -0,0 +1,42 @@ +/* + * ============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.inventory.models; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +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; +import org.onap.cps.spi.model.ConditionProperties; + +@Setter +@Getter +@EqualsAndHashCode +@JsonInclude(Include.NON_EMPTY) +public class CmHandleQueryServiceParameters { + @JsonProperty("cmHandleQueryParameters") + @Valid + private List cmHandleQueryParameters = Collections.emptyList(); +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CmHandleRegistrationResponse.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CmHandleRegistrationResponse.java new file mode 100644 index 0000000000..7523f77af2 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CmHandleRegistrationResponse.java @@ -0,0 +1,147 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Bell Canada + * Modifications 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.inventory.models; + +import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNKNOWN_ERROR; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Builder; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.onap.cps.ncmp.api.NcmpResponseStatus; +import org.onap.cps.ncmp.impl.utils.YangDataConverter; + +@Data +@Builder +@Slf4j +public class CmHandleRegistrationResponse { + + private final String cmHandle; + private final Status status; + private NcmpResponseStatus ncmpResponseStatus; + private String errorText; + + /** + * Creates a failure response based on exception. + * + * @param cmHandleId cmHandleId + * @param exception exception + * @return CmHandleRegistrationResponse + */ + public static CmHandleRegistrationResponse createFailureResponse(final String cmHandleId, + final Exception exception) { + return CmHandleRegistrationResponse.builder() + .cmHandle(cmHandleId) + .status(Status.FAILURE) + .ncmpResponseStatus(UNKNOWN_ERROR) + .errorText(exception.getMessage()).build(); + } + + /** + * Creates a failure response based on registration error. + * + * @param cmHandleId cmHandleId + * @param ncmpResponseStatus registration error code and status + * @return CmHandleRegistrationResponse + */ + public static CmHandleRegistrationResponse createFailureResponse(final String cmHandleId, + final NcmpResponseStatus ncmpResponseStatus) { + return CmHandleRegistrationResponse.builder().cmHandle(cmHandleId) + .status(Status.FAILURE) + .ncmpResponseStatus(ncmpResponseStatus) + .errorText(ncmpResponseStatus.getMessage()) + .build(); + } + + /** + * Create a failure response of cm handle registration based on xpath and registration error. + * Conditions: + * - the xpath should be valid according to the cps path, otherwise xpath is not included in the response. + * + * @param failedXpaths the failed xpaths + * @param ncmpResponseStatus type of the registration error + * @return collection of cm handle registration response + */ + public static List createFailureResponsesFromXpaths( + final Collection failedXpaths, final NcmpResponseStatus ncmpResponseStatus) { + final List cmHandleRegistrationResponses = new ArrayList<>(failedXpaths.size()); + for (final String xpath : failedXpaths) { + try { + final String cmHandleId = YangDataConverter.extractCmHandleIdFromXpath(xpath); + cmHandleRegistrationResponses + .add(CmHandleRegistrationResponse.createFailureResponse(cmHandleId, ncmpResponseStatus)); + } catch (IllegalArgumentException | IllegalStateException e) { + log.warn("Unexpected xpath {}", xpath); + } + } + return cmHandleRegistrationResponses; + } + + /** + * Create a failure response of cm handle registration based on cm handle id and registration error. + * + * @param failedCmHandleIds the failed cm handle ids + * @param ncmpResponseStatus type of the registration error + * @return collection of cm handle registration response + */ + public static List createFailureResponses( + final Collection failedCmHandleIds, final NcmpResponseStatus ncmpResponseStatus) { + final List cmHandleRegistrationResponses = + new ArrayList<>(failedCmHandleIds.size()); + for (final String failedCmHandleId : failedCmHandleIds) { + cmHandleRegistrationResponses.add( + CmHandleRegistrationResponse.createFailureResponse(failedCmHandleId, ncmpResponseStatus)); + } + return cmHandleRegistrationResponses; + } + + /** + * Creates a failure response based on other exception. + * + * @param cmHandleIds list of failed cmHandleIds + * @param exception exception caught during the registration + * @return CmHandleRegistrationResponse + */ + public static List createFailureResponses(final Collection cmHandleIds, + final Exception exception) { + return cmHandleIds.stream() + .map(cmHandleId -> CmHandleRegistrationResponse.createFailureResponse(cmHandleId, exception)) + .toList(); + } + + public static CmHandleRegistrationResponse createSuccessResponse(final String cmHandle) { + return CmHandleRegistrationResponse.builder().cmHandle(cmHandle) + .status(Status.SUCCESS).build(); + } + + public static List createSuccessResponses(final Collection cmHandleIds) { + return cmHandleIds.stream().map(CmHandleRegistrationResponse::createSuccessResponse) + .collect(Collectors.toList()); + } + + public enum Status { + SUCCESS, FAILURE; + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CompositeState.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CompositeState.java new file mode 100644 index 0000000000..ca4fde2b62 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CompositeState.java @@ -0,0 +1,147 @@ +/* + * ============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.inventory.models; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.time.OffsetDateTime; +import java.time.format.DateTimeFormatter; +import lombok.Builder; +import lombok.Data; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.onap.cps.ncmp.impl.inventory.DataStoreSyncState; +import org.onap.cps.ncmp.impl.inventory.models.CmHandleState; +import org.onap.cps.ncmp.impl.inventory.models.LockReasonCategory; + +/** + * State Model to store state corresponding to the Yang resource dmi-registry model. + */ +@Getter +@Setter +@NoArgsConstructor +@JsonInclude(JsonInclude.Include.NON_NULL) +public class CompositeState { + + @JsonProperty("cm-handle-state") + private CmHandleState cmHandleState; + + @JsonProperty("lock-reason") + private LockReason lockReason; + + @JsonProperty("last-update-time") + private String lastUpdateTime; + + @JsonProperty("data-sync-enabled") + private Boolean dataSyncEnabled; + + @JsonProperty("datastores") + private DataStores dataStores; + + /** + * Date and Time in the format of yyyy-MM-dd'T'HH:mm:ss.SSSZ + */ + private static final DateTimeFormatter dateTimeFormatter = + DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); + + /** + * Composite State copy constructor. + * + * @param compositeState Composite State + */ + public CompositeState(final CompositeState compositeState) { + this.cmHandleState = compositeState.getCmHandleState(); + this.lockReason = compositeState.getLockReason(); + this.lastUpdateTime = compositeState.getLastUpdateTime(); + this.dataSyncEnabled = compositeState.getDataSyncEnabled(); + this.dataStores = compositeState.getDataStores(); + } + + + /** + * This will specify the latest lock reason for a specific cm handle. If a cm handle is in a state other than LOCKED + * it specifies the last lock reason. + * This can be used to track retry attempts as part of the lock details. + */ + @Data + @Builder + @JsonInclude(JsonInclude.Include.NON_NULL) + public static class LockReason { + + @JsonProperty("reason") + private LockReasonCategory lockReasonCategory; + + @JsonProperty("details") + private String details; + + } + + @Data + @Builder + @JsonInclude(JsonInclude.Include.NON_NULL) + public static class DataStores { + + @JsonProperty("operational") + private Operational operationalDataStore; + } + + @Data + @Builder + @JsonInclude(JsonInclude.Include.NON_NULL) + public static class Operational { + + @JsonProperty("sync-state") + private DataStoreSyncState dataStoreSyncState; + + @JsonProperty("last-sync-time") + private String lastSyncTime; + } + + @Data + @Builder + @JsonInclude(JsonInclude.Include.NON_NULL) + public static class Running { + + @JsonProperty("sync-state") + private String syncState; + + @JsonProperty("last-sync-time") + private String lastSyncTime; + } + + /** + * The date and time format used for the cm handle sync state. + * + * @return the date and time in the format of yyyy-MM-dd'T'HH:mm:ss.SSSZ + */ + public static String nowInSyncTimeFormat() { + return dateTimeFormatter.format(OffsetDateTime.now()); + } + + /** + * Sets the last updated date and time for the cm handle sync state. + */ + public void setLastUpdateTimeNow() { + lastUpdateTime = CompositeState.nowInSyncTimeFormat(); + } + +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CompositeStateBuilder.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CompositeStateBuilder.java new file mode 100644 index 0000000000..59d7aa2b44 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CompositeStateBuilder.java @@ -0,0 +1,157 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Bell Canada + * Modifications 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.inventory.models; + +import org.onap.cps.ncmp.api.inventory.models.CompositeState.DataStores; +import org.onap.cps.ncmp.api.inventory.models.CompositeState.LockReason; +import org.onap.cps.ncmp.api.inventory.models.CompositeState.Operational; +import org.onap.cps.ncmp.impl.inventory.DataStoreSyncState; +import org.onap.cps.ncmp.impl.inventory.models.CmHandleState; +import org.onap.cps.ncmp.impl.inventory.models.LockReasonCategory; +import org.onap.cps.spi.model.DataNode; + +public class CompositeStateBuilder { + + private CmHandleState cmHandleState; + private LockReason lockReason; + private DataStores datastores; + private String lastUpdatedTime; + private Boolean dataSyncEnabled; + + /** + * To create the {@link CompositeState}. + * + * @return {@link DataNode} + */ + public CompositeState build() { + final CompositeState compositeState = new CompositeState(); + compositeState.setCmHandleState(cmHandleState); + compositeState.setLockReason(lockReason); + compositeState.setDataStores(datastores); + compositeState.setLastUpdateTime(lastUpdatedTime); + compositeState.setDataSyncEnabled(dataSyncEnabled); + return compositeState; + } + + /** + * To use attributes for creating {@link CompositeState}. + * + * @param cmHandleState for the data node + * @return CompositeStateBuilder + */ + public CompositeStateBuilder withCmHandleState(final CmHandleState cmHandleState) { + this.cmHandleState = cmHandleState; + return this; + } + + /** + * To use attributes for creating {@link CompositeState}. + * + * @param reason for the locked state + * @param details for the locked state + * @return CompositeStateBuilder + */ + public CompositeStateBuilder withLockReason(final LockReasonCategory reason, final String details) { + this.lockReason = LockReason.builder().lockReasonCategory(reason).details(details).build(); + return this; + } + + /** + * To use attributes for creating {@link CompositeState}. + * + * @param time for the state change + * @return CompositeStateBuilder + */ + public CompositeStateBuilder withLastUpdatedTime(final String time) { + this.lastUpdatedTime = time; + return this; + } + + /** + * To use attributes for creating {@link CompositeState}. + * + * @return composite state builder + */ + public CompositeStateBuilder withLastUpdatedTimeNow() { + this.lastUpdatedTime = CompositeState.nowInSyncTimeFormat(); + return this; + } + + /** + * To use attributes for creating {@link CompositeState}. + * + * @param dataStoreSyncState for the locked state + * @param lastSyncTime for the locked state + * @return CompositeStateBuilder + */ + public CompositeStateBuilder withOperationalDataStores(final DataStoreSyncState dataStoreSyncState, + final String lastSyncTime) { + this.datastores = DataStores.builder().operationalDataStore( + Operational.builder().dataStoreSyncState(dataStoreSyncState).lastSyncTime(lastSyncTime).build()).build(); + return this; + } + + /** + * To use dataNode for creating {@link CompositeState}. + * + * @param dataNode for the dataNode + * @return CompositeState + */ + public CompositeStateBuilder fromDataNode(final DataNode dataNode) { + this.cmHandleState = CmHandleState.valueOf((String) dataNode.getLeaves() + .get("cm-handle-state")); + this.lastUpdatedTime = (String) dataNode.getLeaves().get("last-update-time"); + if (this.cmHandleState == CmHandleState.READY) { + this.dataSyncEnabled = (Boolean) dataNode.getLeaves().get("data-sync-enabled"); + } + for (final DataNode stateChildNode : dataNode.getChildDataNodes()) { + if (stateChildNode.getXpath().endsWith("/lock-reason")) { + this.lockReason = getLockReason(stateChildNode); + } + if (stateChildNode.getXpath().endsWith("/datastores")) { + for (final DataNode dataStoreNodes : stateChildNode.getChildDataNodes()) { + Operational operationalDataStore = null; + if (dataStoreNodes.getXpath().contains("/operational")) { + operationalDataStore = getOperationalDataStore(dataStoreNodes); + } + this.datastores = DataStores.builder().operationalDataStore(operationalDataStore).build(); + } + } + } + return this; + } + + private Operational getOperationalDataStore(final DataNode dataStoreNodes) { + return Operational.builder() + .dataStoreSyncState(DataStoreSyncState.valueOf((String) dataStoreNodes.getLeaves().get("sync-state"))) + .lastSyncTime((String) dataStoreNodes.getLeaves().get("last-sync-time")) + .build(); + } + + private LockReason getLockReason(final DataNode stateChildNode) { + final boolean isLockReasonExists = stateChildNode.getLeaves().containsKey("reason"); + return new LockReason(isLockReasonExists + ? LockReasonCategory.valueOf((String) stateChildNode.getLeaves().get("reason")) + : null, (String) stateChildNode.getLeaves().get("details")); + } + +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/ConditionApiProperties.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/ConditionApiProperties.java new file mode 100644 index 0000000000..61d9f4a250 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/ConditionApiProperties.java @@ -0,0 +1,44 @@ +/* + * ============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.inventory.models; + +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 java.util.Map; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@EqualsAndHashCode +@JsonInclude(JsonInclude.Include.NON_EMPTY) +public class ConditionApiProperties { + @JsonProperty("conditionName") + private String conditionName = ""; + + @JsonProperty("conditionParameters") + @Valid + private List> conditionParameters = Collections.emptyList(); +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/DmiPluginRegistration.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/DmiPluginRegistration.java new file mode 100644 index 0000000000..a5002e7909 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/DmiPluginRegistration.java @@ -0,0 +1,89 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021-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.inventory.models; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.google.common.base.Strings; +import java.util.Collections; +import java.util.List; +import lombok.Getter; +import lombok.Setter; +import org.onap.cps.ncmp.api.impl.exception.DmiRequestException; +import org.onap.cps.ncmp.api.impl.exception.NcmpException; + +/** + * Dmi Registry request object. + */ +@Getter +@Setter +@JsonInclude(Include.NON_NULL) +public class DmiPluginRegistration { + + private String dmiPlugin; + + private String dmiDataPlugin; + + private String dmiModelPlugin; + + private List createdCmHandles = Collections.emptyList(); + + private List updatedCmHandles = Collections.emptyList(); + + private List removedCmHandles = Collections.emptyList(); + + private UpgradedCmHandles upgradedCmHandles = new UpgradedCmHandles(); + + /** + * Validates plugin service names. + * @throws NcmpException if validation fails. + */ + public void validateDmiPluginRegistration() throws NcmpException { + final String combinedServiceName = dmiPlugin; + final String dataServiceName = dmiDataPlugin; + final String modelsServiceName = dmiModelPlugin; + + String errorMessage = null; + + if (isNullEmptyOrBlank(combinedServiceName)) { + if ((isNullEmptyOrBlank(dataServiceName) && isNullEmptyOrBlank(modelsServiceName))) { + errorMessage = "No DMI plugin service names"; + } else { + if (isNullEmptyOrBlank(dataServiceName) || isNullEmptyOrBlank(modelsServiceName)) { + errorMessage = "Cannot register just a Data or Model plugin service name"; + } + } + } else { + if (!isNullEmptyOrBlank(dataServiceName) || !isNullEmptyOrBlank(modelsServiceName)) { + errorMessage = "Cannot register combined plugin service name and other service names"; + } + } + + if (errorMessage != null) { + throw new DmiRequestException(errorMessage, "Please supply correct plugin information."); + } + } + + public static boolean isNullEmptyOrBlank(final String serviceName) { + return Strings.isNullOrEmpty(serviceName) || serviceName.isBlank(); + } + +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/DmiPluginRegistrationResponse.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/DmiPluginRegistrationResponse.java new file mode 100644 index 0000000000..736ca620d0 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/DmiPluginRegistrationResponse.java @@ -0,0 +1,36 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Bell Canada + * Modifications 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.inventory.models; + +import java.util.Collections; +import java.util.List; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +public class DmiPluginRegistrationResponse { + private List createdCmHandles = Collections.emptyList(); + private List updatedCmHandles = Collections.emptyList(); + private List removedCmHandles = Collections.emptyList(); + private List upgradedCmHandles = Collections.emptyList(); +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/NcmpServiceCmHandle.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/NcmpServiceCmHandle.java new file mode 100644 index 0000000000..69b33a16f5 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/NcmpServiceCmHandle.java @@ -0,0 +1,65 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021-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.inventory.models; + +import com.fasterxml.jackson.annotation.JsonSetter; +import com.fasterxml.jackson.annotation.Nulls; +import java.util.Collections; +import java.util.Map; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevel; +import org.springframework.validation.annotation.Validated; + +/** + * The NCMP Service model used for the java service API. + * NCMP Service CmHandle. + */ +@Validated +@Getter +@Setter +@NoArgsConstructor +public class NcmpServiceCmHandle { + + private String cmHandleId; + + @JsonSetter(nulls = Nulls.AS_EMPTY) + private Map dmiProperties = Collections.emptyMap(); + + @JsonSetter(nulls = Nulls.AS_EMPTY) + private Map publicProperties = Collections.emptyMap(); + + @JsonSetter(nulls = Nulls.AS_EMPTY) + private CompositeState compositeState; + + @JsonSetter(nulls = Nulls.AS_EMPTY) + private String moduleSetTag; + + @JsonSetter(nulls = Nulls.AS_EMPTY) + private TrustLevel registrationTrustLevel; + + @JsonSetter(nulls = Nulls.AS_EMPTY) + private String alternateId; + + @JsonSetter(nulls = Nulls.AS_EMPTY) + private String dataProducerIdentifier; +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/UpgradedCmHandles.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/UpgradedCmHandles.java new file mode 100644 index 0000000000..9f48ae968c --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/UpgradedCmHandles.java @@ -0,0 +1,36 @@ +/* + * ============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.inventory.models; + +import com.fasterxml.jackson.annotation.JsonInclude; +import java.util.Collections; +import java.util.List; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@JsonInclude(JsonInclude.Include.NON_EMPTY) +public class UpgradedCmHandles { + private List cmHandles = Collections.emptyList(); + private String moduleSetTag; +} + diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/YangResource.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/YangResource.java new file mode 100644 index 0000000000..1c0ca5d8cd --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/YangResource.java @@ -0,0 +1,34 @@ +/* + * ============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.inventory.models; + +import lombok.Data; + +@Data +public class YangResource { + + private String moduleName; + + private String revision; + + private String yangSource; + +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandleQueryApiParameters.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandleQueryApiParameters.java deleted file mode 100644 index dd8dcd60ac..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandleQueryApiParameters.java +++ /dev/null @@ -1,43 +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.models; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonInclude.Include; -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(Include.NON_EMPTY) -@JsonIgnoreProperties(ignoreUnknown = true) -public class CmHandleQueryApiParameters { - @JsonProperty("cmHandleQueryParameters") - @Valid - private List cmHandleQueryParameters = Collections.emptyList(); -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandleQueryServiceParameters.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandleQueryServiceParameters.java deleted file mode 100644 index 5eeafaca33..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandleQueryServiceParameters.java +++ /dev/null @@ -1,42 +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.models; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonInclude.Include; -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; -import org.onap.cps.spi.model.ConditionProperties; - -@Setter -@Getter -@EqualsAndHashCode -@JsonInclude(Include.NON_EMPTY) -public class CmHandleQueryServiceParameters { - @JsonProperty("cmHandleQueryParameters") - @Valid - private List cmHandleQueryParameters = Collections.emptyList(); -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandleRegistrationResponse.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandleRegistrationResponse.java deleted file mode 100644 index 52b8d6926a..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandleRegistrationResponse.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022 Bell Canada - * Modifications 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.models; - -import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNKNOWN_ERROR; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.stream.Collectors; -import lombok.Builder; -import lombok.Data; -import lombok.extern.slf4j.Slf4j; -import org.onap.cps.ncmp.api.NcmpResponseStatus; -import org.onap.cps.ncmp.api.impl.utils.YangDataConverter; - -@Data -@Builder -@Slf4j -public class CmHandleRegistrationResponse { - - private final String cmHandle; - private final Status status; - private NcmpResponseStatus ncmpResponseStatus; - private String errorText; - - /** - * Creates a failure response based on exception. - * - * @param cmHandleId cmHandleId - * @param exception exception - * @return CmHandleRegistrationResponse - */ - public static CmHandleRegistrationResponse createFailureResponse(final String cmHandleId, - final Exception exception) { - return CmHandleRegistrationResponse.builder() - .cmHandle(cmHandleId) - .status(Status.FAILURE) - .ncmpResponseStatus(UNKNOWN_ERROR) - .errorText(exception.getMessage()).build(); - } - - /** - * Creates a failure response based on registration error. - * - * @param cmHandleId cmHandleId - * @param ncmpResponseStatus registration error code and status - * @return CmHandleRegistrationResponse - */ - public static CmHandleRegistrationResponse createFailureResponse(final String cmHandleId, - final NcmpResponseStatus ncmpResponseStatus) { - return CmHandleRegistrationResponse.builder().cmHandle(cmHandleId) - .status(Status.FAILURE) - .ncmpResponseStatus(ncmpResponseStatus) - .errorText(ncmpResponseStatus.getMessage()) - .build(); - } - - /** - * Create a failure response of cm handle registration based on xpath and registration error. - * Conditions: - * - the xpath should be valid according to the cps path, otherwise xpath is not included in the response. - * - * @param failedXpaths the failed xpaths - * @param ncmpResponseStatus type of the registration error - * @return collection of cm handle registration response - */ - public static List createFailureResponsesFromXpaths( - final Collection failedXpaths, final NcmpResponseStatus ncmpResponseStatus) { - final List cmHandleRegistrationResponses = new ArrayList<>(failedXpaths.size()); - for (final String xpath : failedXpaths) { - try { - final String cmHandleId = YangDataConverter.extractCmHandleIdFromXpath(xpath); - cmHandleRegistrationResponses - .add(CmHandleRegistrationResponse.createFailureResponse(cmHandleId, ncmpResponseStatus)); - } catch (IllegalArgumentException | IllegalStateException e) { - log.warn("Unexpected xpath {}", xpath); - } - } - return cmHandleRegistrationResponses; - } - - /** - * Create a failure response of cm handle registration based on cm handle id and registration error. - * - * @param failedCmHandleIds the failed cm handle ids - * @param ncmpResponseStatus type of the registration error - * @return collection of cm handle registration response - */ - public static List createFailureResponses( - final Collection failedCmHandleIds, final NcmpResponseStatus ncmpResponseStatus) { - final List cmHandleRegistrationResponses = - new ArrayList<>(failedCmHandleIds.size()); - for (final String failedCmHandleId : failedCmHandleIds) { - cmHandleRegistrationResponses.add( - CmHandleRegistrationResponse.createFailureResponse(failedCmHandleId, ncmpResponseStatus)); - } - return cmHandleRegistrationResponses; - } - - /** - * Creates a failure response based on other exception. - * - * @param cmHandleIds list of failed cmHandleIds - * @param exception exception caught during the registration - * @return CmHandleRegistrationResponse - */ - public static List createFailureResponses(final Collection cmHandleIds, - final Exception exception) { - return cmHandleIds.stream() - .map(cmHandleId -> CmHandleRegistrationResponse.createFailureResponse(cmHandleId, exception)) - .toList(); - } - - public static CmHandleRegistrationResponse createSuccessResponse(final String cmHandle) { - return CmHandleRegistrationResponse.builder().cmHandle(cmHandle) - .status(Status.SUCCESS).build(); - } - - public static List createSuccessResponses(final Collection cmHandleIds) { - return cmHandleIds.stream().map(CmHandleRegistrationResponse::createSuccessResponse) - .collect(Collectors.toList()); - } - - public enum Status { - SUCCESS, FAILURE; - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/ConditionApiProperties.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/ConditionApiProperties.java deleted file mode 100644 index 5cb2ed376c..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/ConditionApiProperties.java +++ /dev/null @@ -1,44 +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.models; - -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 java.util.Map; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; - -@Getter -@Setter -@EqualsAndHashCode -@JsonInclude(JsonInclude.Include.NON_EMPTY) -public class ConditionApiProperties { - @JsonProperty("conditionName") - private String conditionName = ""; - - @JsonProperty("conditionParameters") - @Valid - private List> conditionParameters = Collections.emptyList(); -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DmiPluginRegistration.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DmiPluginRegistration.java deleted file mode 100644 index 7d6a8e1407..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DmiPluginRegistration.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2021-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; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonInclude.Include; -import com.google.common.base.Strings; -import java.util.Collections; -import java.util.List; -import lombok.Getter; -import lombok.Setter; -import org.onap.cps.ncmp.api.impl.exception.DmiRequestException; -import org.onap.cps.ncmp.api.impl.exception.NcmpException; - -/** - * Dmi Registry request object. - */ -@Getter -@Setter -@JsonInclude(Include.NON_NULL) -public class DmiPluginRegistration { - - private String dmiPlugin; - - private String dmiDataPlugin; - - private String dmiModelPlugin; - - private List createdCmHandles = Collections.emptyList(); - - private List updatedCmHandles = Collections.emptyList(); - - private List removedCmHandles = Collections.emptyList(); - - private UpgradedCmHandles upgradedCmHandles = new UpgradedCmHandles(); - - /** - * Validates plugin service names. - * @throws NcmpException if validation fails. - */ - public void validateDmiPluginRegistration() throws NcmpException { - final String combinedServiceName = dmiPlugin; - final String dataServiceName = dmiDataPlugin; - final String modelsServiceName = dmiModelPlugin; - - String errorMessage = null; - - if (isNullEmptyOrBlank(combinedServiceName)) { - if ((isNullEmptyOrBlank(dataServiceName) && isNullEmptyOrBlank(modelsServiceName))) { - errorMessage = "No DMI plugin service names"; - } else { - if (isNullEmptyOrBlank(dataServiceName) || isNullEmptyOrBlank(modelsServiceName)) { - errorMessage = "Cannot register just a Data or Model plugin service name"; - } - } - } else { - if (!isNullEmptyOrBlank(dataServiceName) || !isNullEmptyOrBlank(modelsServiceName)) { - errorMessage = "Cannot register combined plugin service name and other service names"; - } - } - - if (errorMessage != null) { - throw new DmiRequestException(errorMessage, "Please supply correct plugin information."); - } - } - - public static boolean isNullEmptyOrBlank(final String serviceName) { - return Strings.isNullOrEmpty(serviceName) || serviceName.isBlank(); - } - -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DmiPluginRegistrationResponse.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DmiPluginRegistrationResponse.java deleted file mode 100644 index ee034176e3..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DmiPluginRegistrationResponse.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022 Bell Canada - * Modifications 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 java.util.Collections; -import java.util.List; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@NoArgsConstructor -public class DmiPluginRegistrationResponse { - private List createdCmHandles = Collections.emptyList(); - private List updatedCmHandles = Collections.emptyList(); - private List removedCmHandles = Collections.emptyList(); - private List upgradedCmHandles = Collections.emptyList(); -} \ No newline at end of file diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/NcmpServiceCmHandle.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/NcmpServiceCmHandle.java deleted file mode 100644 index 676eebc4d6..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/NcmpServiceCmHandle.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2021-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; - -import com.fasterxml.jackson.annotation.JsonSetter; -import com.fasterxml.jackson.annotation.Nulls; -import java.util.Collections; -import java.util.Map; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import org.onap.cps.ncmp.api.impl.inventory.CompositeState; -import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevel; -import org.springframework.validation.annotation.Validated; - -/** - * The NCMP Service model used for the java service API. - * NCMP Service CmHandle. - */ -@Validated -@Getter -@Setter -@NoArgsConstructor -public class NcmpServiceCmHandle { - - private String cmHandleId; - - @JsonSetter(nulls = Nulls.AS_EMPTY) - private Map dmiProperties = Collections.emptyMap(); - - @JsonSetter(nulls = Nulls.AS_EMPTY) - private Map publicProperties = Collections.emptyMap(); - - @JsonSetter(nulls = Nulls.AS_EMPTY) - private CompositeState compositeState; - - @JsonSetter(nulls = Nulls.AS_EMPTY) - private String moduleSetTag; - - @JsonSetter(nulls = Nulls.AS_EMPTY) - private TrustLevel registrationTrustLevel; - - @JsonSetter(nulls = Nulls.AS_EMPTY) - private String alternateId; - - @JsonSetter(nulls = Nulls.AS_EMPTY) - private String dataProducerIdentifier; -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/UpgradedCmHandles.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/UpgradedCmHandles.java deleted file mode 100644 index 61cd99ac8f..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/UpgradedCmHandles.java +++ /dev/null @@ -1,36 +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.JsonInclude; -import java.util.Collections; -import java.util.List; -import lombok.Getter; -import lombok.Setter; - -@Getter -@Setter -@JsonInclude(JsonInclude.Include.NON_EMPTY) -public class UpgradedCmHandles { - private List cmHandles = Collections.emptyList(); - private String moduleSetTag; -} - diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/YangResource.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/YangResource.java deleted file mode 100644 index 7975777aa5..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/YangResource.java +++ /dev/null @@ -1,34 +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.models; - -import lombok.Data; - -@Data -public class YangResource { - - private String moduleName; - - private String revision; - - private String yangSource; - -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/WriteRequestExaminer.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/WriteRequestExaminer.java index 1c3e476c8b..0e51f0c447 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/WriteRequestExaminer.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/WriteRequestExaminer.java @@ -31,9 +31,9 @@ import org.onap.cps.ncmp.api.datajobs.models.DataJobWriteRequest; import org.onap.cps.ncmp.api.datajobs.models.DmiWriteOperation; import org.onap.cps.ncmp.api.datajobs.models.ProducerKey; import org.onap.cps.ncmp.api.datajobs.models.WriteOperation; -import org.onap.cps.ncmp.api.impl.utils.YangDataConverter; -import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.ncmp.utils.AlternateIdMatcher; +import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; +import org.onap.cps.ncmp.impl.utils.AlternateIdMatcher; +import org.onap.cps.ncmp.impl.utils.YangDataConverter; import org.onap.cps.spi.model.DataNode; import org.springframework.stereotype.Service; @@ -106,4 +106,4 @@ public class WriteRequestExaminer { return cmHandleDmiProperties; } -} \ No newline at end of file +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryParametersValidator.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryParametersValidator.java new file mode 100644 index 0000000000..08954024b7 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryParametersValidator.java @@ -0,0 +1,125 @@ +/* + * ============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.inventory; + +import com.google.common.base.Strings; +import java.util.Collection; +import java.util.Map; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.onap.cps.ncmp.api.inventory.models.CmHandleQueryServiceParameters; +import org.onap.cps.spi.exceptions.DataValidationException; + +@Slf4j +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class CmHandleQueryParametersValidator { + + /** + * Validate query parameters. + * + * @param cmHandleQueryServiceParameters name of data to be validated + * @param validConditionNames valid condition names + */ + public static void validateCmHandleQueryParameters( + final CmHandleQueryServiceParameters cmHandleQueryServiceParameters, + final Collection validConditionNames) { + cmHandleQueryServiceParameters.getCmHandleQueryParameters().forEach( + cmHandleQueryParameter -> { + if (validConditionNames.stream().noneMatch(validConditionName -> + validConditionName.equals(cmHandleQueryParameter.getConditionName()))) { + throw createDataValidationException( + String.format("Wrong 'conditionName': %s - please supply a valid name.", + cmHandleQueryParameter.getConditionName())); + } + if (cmHandleQueryParameter.getConditionParameters().isEmpty()) { + throw createDataValidationException( + "Empty 'conditionsParameters' - please supply a valid condition parameter."); + } + cmHandleQueryParameter.getConditionParameters().forEach( + CmHandleQueryParametersValidator::validateConditionParameter + ); + } + ); + } + + private static void validateConditionParameter(final Map conditionParameter) { + if (conditionParameter.isEmpty()) { + throw createDataValidationException( + "Empty 'conditionsParameter' - please supply a valid condition parameter."); + } + if (conditionParameter.size() > 1) { + throw createDataValidationException("Too many names in one 'conditionsParameter' -" + + " please supply one name in one condition parameter."); + } + conditionParameter.forEach((key, value) -> { + if (Strings.isNullOrEmpty(key)) { + throw createDataValidationException( + "Missing 'conditionsParameterName' - please supply a valid name."); + } + }); + } + + /** + * Validate module name condition properties. + * @param conditionProperty name of data to be validated + */ + public static void validateModuleNameConditionProperties(final Map conditionProperty) { + if (conditionProperty.containsKey("moduleName") && !conditionProperty.get("moduleName").isEmpty()) { + return; + } + throw createDataValidationException("Wrong module condition property. - " + + "please supply a valid condition property."); + } + + /** + * Validate CPS path condition properties. + * @param conditionProperty name of data to be validated + */ + public static boolean validateCpsPathConditionProperties(final Map conditionProperty) { + if (conditionProperty.isEmpty()) { + return true; + } + if (conditionProperty.size() > 1) { + throw createDataValidationException("Only one condition property is allowed for the CPS path query."); + } + if (!conditionProperty.containsKey("cpsPath")) { + throw createDataValidationException( + "Wrong CPS path condition property. - expecting \"cpsPath\" as the condition property."); + } + final String cpsPath = conditionProperty.get("cpsPath"); + if (cpsPath.isBlank()) { + throw createDataValidationException( + "Wrong CPS path. - please supply a valid CPS path."); + } + if (cpsPath.contains("/additional-properties")) { + log.debug("{} - Private metadata cannot be queried. Nothing to be returned", + cpsPath); + return false; + } + return true; + } + + private static DataValidationException createDataValidationException(final String details) { + return new DataValidationException("Invalid Query Parameter.", details); + } + +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryService.java new file mode 100644 index 0000000000..795d7c9c4c --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryService.java @@ -0,0 +1,106 @@ +/* + * ============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.inventory; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import org.onap.cps.ncmp.impl.inventory.models.CmHandleState; +import org.onap.cps.spi.FetchDescendantsOption; +import org.onap.cps.spi.model.DataNode; + +public interface CmHandleQueryService { + + /** + * Query Cm Handles based on additional (private) properties. + * + * @param additionalPropertyQueryPairs private properties for query + * @return Ids of Cm Handles which have these private properties + */ + Collection queryCmHandleAdditionalProperties(Map additionalPropertyQueryPairs); + + /** + * Query Cm Handles based on public properties. + * + * @param publicPropertyQueryPairs public properties for query + * @return CmHandles which have these public properties + */ + Collection queryCmHandlePublicProperties(Map publicPropertyQueryPairs); + + /** + * Query Cm Handles based on Trust Level. + * + * @param trustLevelPropertyQueryPairs trust level properties for query + * @return Ids of Cm Handles which have desired trust level + */ + Collection queryCmHandlesByTrustLevel(Map trustLevelPropertyQueryPairs); + + /** + * Method which returns cm handles by the cm handles state. + * + * @param cmHandleState cm handle state + * @return a list of data nodes representing the cm handles. + */ + List queryCmHandlesByState(CmHandleState cmHandleState); + + /** + * Method to return data nodes with ancestor representing the cm handles. + * + * @param cpsPath cps path for which the cmHandle is requested + * @return a list of data nodes representing the cm handles. + */ + List queryCmHandleAncestorsByCpsPath(String cpsPath, + FetchDescendantsOption fetchDescendantsOption); + + /** + * Method to return data nodes representing the cm handles. + * + * @param cpsPath cps path for which the cmHandle is requested + * @return a list of data nodes representing the cm handles. + */ + List queryNcmpRegistryByCpsPath(String cpsPath, FetchDescendantsOption fetchDescendantsOption); + + /** + * Method to check the state of a cm handle with given id. + * + * @param cmHandleId cm handle id + * @param requiredCmHandleState the required state of the cm handle + * @return a boolean, true if the state is equal to the required state + */ + boolean cmHandleHasState(String cmHandleId, CmHandleState requiredCmHandleState); + + /** + * Method which returns cm handles by the operational sync state of cm handle. + * + * @param dataStoreSyncState sync state + * @return a list of data nodes representing the cm handles. + */ + List queryCmHandlesByOperationalSyncState(DataStoreSyncState dataStoreSyncState); + + /** + * Get all cm handles ids by DMI plugin identifier. + * + * @param dmiPluginIdentifier DMI plugin identifier + * @return collection of cm handle ids + */ + Collection getCmHandleIdsByDmiPluginIdentifier(String dmiPluginIdentifier); + +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImpl.java new file mode 100644 index 0000000000..4c2f93a95e --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImpl.java @@ -0,0 +1,194 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022-2024 Nordix Foundation + * 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.inventory; + +import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DATASPACE_NAME; +import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR; +import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT; +import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS; +import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import lombok.RequiredArgsConstructor; +import org.onap.cps.ncmp.api.impl.config.embeddedcache.TrustLevelCacheConfig; +import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevel; +import org.onap.cps.ncmp.impl.inventory.models.CmHandleState; +import org.onap.cps.ncmp.impl.inventory.models.ModelledDmiServiceLeaves; +import org.onap.cps.ncmp.impl.inventory.models.PropertyType; +import org.onap.cps.spi.CpsDataPersistenceService; +import org.onap.cps.spi.FetchDescendantsOption; +import org.onap.cps.spi.model.DataNode; +import org.onap.cps.spi.utils.CpsValidator; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Component; + +@RequiredArgsConstructor +@Component +public class CmHandleQueryServiceImpl implements CmHandleQueryService { + + private static final String DESCENDANT_PATH = "//"; + private static final String ANCESTOR_CM_HANDLES = "/ancestor::cm-handles"; + private final CpsDataPersistenceService cpsDataPersistenceService; + + @Qualifier(TrustLevelCacheConfig.TRUST_LEVEL_PER_DMI_PLUGIN) + private final Map trustLevelPerDmiPlugin; + + @Qualifier(TrustLevelCacheConfig.TRUST_LEVEL_PER_CM_HANDLE) + private final Map trustLevelPerCmHandle; + + private final CpsValidator cpsValidator; + + @Override + public Collection queryCmHandleAdditionalProperties(final Map privatePropertyQueryPairs) { + return queryCmHandleAnyProperties(privatePropertyQueryPairs, PropertyType.ADDITIONAL); + } + + @Override + public Collection queryCmHandlePublicProperties(final Map publicPropertyQueryPairs) { + return queryCmHandleAnyProperties(publicPropertyQueryPairs, PropertyType.PUBLIC); + } + + @Override + public Collection queryCmHandlesByTrustLevel(final Map trustLevelPropertyQueryPairs) { + final String trustLevelProperty = trustLevelPropertyQueryPairs.values().iterator().next(); + final TrustLevel targetTrustLevel = TrustLevel.valueOf(trustLevelProperty); + + return getCmHandleIdsByTrustLevel(targetTrustLevel); + } + + @Override + public List queryCmHandlesByState(final CmHandleState cmHandleState) { + return queryCmHandleAncestorsByCpsPath("//state[@cm-handle-state=\"" + cmHandleState + "\"]", + INCLUDE_ALL_DESCENDANTS); + } + + @Override + public List queryNcmpRegistryByCpsPath(final String cpsPath, + final FetchDescendantsOption fetchDescendantsOption) { + return cpsDataPersistenceService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, + cpsPath, fetchDescendantsOption); + } + + @Override + public List queryCmHandleAncestorsByCpsPath(final String cpsPath, + final FetchDescendantsOption fetchDescendantsOption) { + return queryNcmpRegistryByCpsPath(cpsPath + ANCESTOR_CM_HANDLES, fetchDescendantsOption); + } + + @Override + public boolean cmHandleHasState(final String cmHandleId, final CmHandleState requiredCmHandleState) { + final DataNode stateDataNode = getCmHandleState(cmHandleId); + final String cmHandleStateAsString = (String) stateDataNode.getLeaves().get("cm-handle-state"); + return CmHandleState.valueOf(cmHandleStateAsString).equals(requiredCmHandleState); + } + + @Override + public List queryCmHandlesByOperationalSyncState(final DataStoreSyncState dataStoreSyncState) { + return queryCmHandleAncestorsByCpsPath("//state/datastores" + "/operational[@sync-state=\"" + + dataStoreSyncState + "\"]", FetchDescendantsOption.OMIT_DESCENDANTS); + } + + @Override + public Collection getCmHandleIdsByDmiPluginIdentifier(final String dmiPluginIdentifier) { + final Collection cmHandleIds = new HashSet<>(); + for (final ModelledDmiServiceLeaves modelledDmiServiceLeaf : ModelledDmiServiceLeaves.values()) { + for (final DataNode cmHandleAsDataNode: getCmHandlesByDmiPluginIdentifierAndDmiProperty( + dmiPluginIdentifier, + modelledDmiServiceLeaf.getLeafName())) { + cmHandleIds.add(cmHandleAsDataNode.getLeaves().get("id").toString()); + } + } + return cmHandleIds; + } + + private Collection getCmHandleIdsByTrustLevel(final TrustLevel targetTrustLevel) { + final Collection selectedCmHandleIds = new HashSet<>(); + + for (final Map.Entry mapEntry : trustLevelPerDmiPlugin.entrySet()) { + final String dmiPluginIdentifier = mapEntry.getKey(); + final TrustLevel dmiTrustLevel = mapEntry.getValue(); + final Collection candidateCmHandleIds = getCmHandleIdsByDmiPluginIdentifier(dmiPluginIdentifier); + for (final String candidateCmHandleId : candidateCmHandleIds) { + final TrustLevel candidateCmHandleTrustLevel = trustLevelPerCmHandle.get(candidateCmHandleId); + final TrustLevel effectiveTrustlevel = + candidateCmHandleTrustLevel.getEffectiveTrustLevel(dmiTrustLevel); + if (targetTrustLevel.equals(effectiveTrustlevel)) { + selectedCmHandleIds.add(candidateCmHandleId); + } + } + } + + return selectedCmHandleIds; + } + + private Collection collectCmHandleIdsFromDataNodes(final Collection dataNodes) { + return dataNodes.stream().map(dataNode -> (String) dataNode.getLeaves().get("id")).collect(Collectors.toSet()); + } + + private Collection queryCmHandleAnyProperties( + final Map propertyQueryPairs, + final PropertyType propertyType) { + if (propertyQueryPairs.isEmpty()) { + return Collections.emptySet(); + } + Collection cmHandleIds = null; + for (final Map.Entry publicPropertyQueryPair : propertyQueryPairs.entrySet()) { + final String cpsPath = DESCENDANT_PATH + propertyType.getYangContainerName() + "[@name=\"" + + publicPropertyQueryPair.getKey() + + "\" and @value=\"" + publicPropertyQueryPair.getValue() + "\"]"; + + final Collection dataNodes = queryCmHandleAncestorsByCpsPath(cpsPath, + OMIT_DESCENDANTS); + if (cmHandleIds == null) { + cmHandleIds = collectCmHandleIdsFromDataNodes(dataNodes); + } else { + final Collection cmHandleIdsToRetain = collectCmHandleIdsFromDataNodes(dataNodes); + cmHandleIds.retainAll(cmHandleIdsToRetain); + } + if (cmHandleIds.isEmpty()) { + break; + } + } + return cmHandleIds; + } + + private List getCmHandlesByDmiPluginIdentifierAndDmiProperty(final String dmiPluginIdentifier, + final String dmiProperty) { + return cpsDataPersistenceService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, + NCMP_DMI_REGISTRY_PARENT + "/cm-handles[@" + dmiProperty + "='" + dmiPluginIdentifier + "']", + OMIT_DESCENDANTS); + } + + private DataNode getCmHandleState(final String cmHandleId) { + cpsValidator.validateNameCharacters(cmHandleId); + final String xpath = NCMP_DMI_REGISTRY_PARENT + "/cm-handles[@id='" + cmHandleId + "']/state"; + return cpsDataPersistenceService.getDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, + xpath, OMIT_DESCENDANTS).iterator().next(); + } +} + + 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 new file mode 100644 index 0000000000..f10ccd4aed --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationService.java @@ -0,0 +1,401 @@ +/* + * ============LICENSE_START======================================================= + * 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.inventory; + +import static org.onap.cps.ncmp.api.NcmpResponseStatus.ALTERNATE_ID_ALREADY_ASSOCIATED; +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 static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLE_ALREADY_EXIST; +import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLE_INVALID_ID; +import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT; +import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME; +import static org.onap.cps.ncmp.impl.inventory.models.LockReasonCategory.MODULE_UPGRADE; + +import com.google.common.collect.Lists; +import com.hazelcast.map.IMap; +import java.time.OffsetDateTime; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +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.config.embeddedcache.TrustLevelCacheConfig; +import org.onap.cps.ncmp.api.impl.events.lcm.LcmEventsCmHandleStateHandler; +import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevel; +import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevelManager; +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; +import org.onap.cps.ncmp.api.inventory.models.DmiPluginRegistration; +import org.onap.cps.ncmp.api.inventory.models.DmiPluginRegistrationResponse; +import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle; +import org.onap.cps.ncmp.impl.inventory.models.CmHandleState; +import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; +import org.onap.cps.ncmp.impl.inventory.sync.ModuleOperationsUtils; +import org.onap.cps.spi.exceptions.AlreadyDefinedException; +import org.onap.cps.spi.exceptions.CpsException; +import org.onap.cps.spi.exceptions.DataNodeNotFoundException; +import org.onap.cps.spi.exceptions.DataValidationException; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Service; + +@Slf4j +@Service +@RequiredArgsConstructor +public class CmHandleRegistrationService { + + private static final int DELETE_BATCH_SIZE = 100; + + private final CmHandleRegistrationServicePropertyHandler cmHandleRegistrationServicePropertyHandler; + private final InventoryPersistence inventoryPersistence; + private final CpsDataService cpsDataService; + private final LcmEventsCmHandleStateHandler lcmEventsCmHandleStateHandler; + private final IMap moduleSyncStartedOnCmHandles; + + @Qualifier(TrustLevelCacheConfig.TRUST_LEVEL_PER_DMI_PLUGIN) + private final Map trustLevelPerDmiPlugin; + private final TrustLevelManager trustLevelManager; + + private final AlternateIdChecker alternateIdChecker; + + /** + * Registration of Created, Removed, Updated or Upgraded CM Handles. + * + * @param dmiPluginRegistration Dmi Plugin Registration details + * @return dmiPluginRegistrationResponse + */ + public DmiPluginRegistrationResponse updateDmiRegistrationAndSyncModule( + final DmiPluginRegistration dmiPluginRegistration) { + + dmiPluginRegistration.validateDmiPluginRegistration(); + final DmiPluginRegistrationResponse dmiPluginRegistrationResponse = new DmiPluginRegistrationResponse(); + + setTrustLevelPerDmiPlugin(dmiPluginRegistration); + + processRemovedCmHandles(dmiPluginRegistration, dmiPluginRegistrationResponse); + + processCreatedCmHandles(dmiPluginRegistration, dmiPluginRegistrationResponse); + + processUpdatedCmHandles(dmiPluginRegistration, dmiPluginRegistrationResponse); + + processUpgradedCmHandles(dmiPluginRegistration, dmiPluginRegistrationResponse); + + return dmiPluginRegistrationResponse; + } + + /** + * Set the data sync enabled flag, along with the data sync state + * based on the data sync enabled boolean for the cm handle id provided. + * + * @param cmHandleId cm handle id + * @param dataSyncEnabledTargetValue data sync enabled flag + */ + public void setDataSyncEnabled(final String cmHandleId, final Boolean dataSyncEnabledTargetValue) { + final CompositeState compositeState = inventoryPersistence.getCmHandleState(cmHandleId); + if (dataSyncEnabledTargetValue.equals(compositeState.getDataSyncEnabled())) { + log.info("Data-Sync Enabled flag is already: {} ", dataSyncEnabledTargetValue); + return; + } + if (CmHandleState.READY.equals(compositeState.getCmHandleState())) { + final DataStoreSyncState dataStoreSyncState = compositeState.getDataStores() + .getOperationalDataStore().getDataStoreSyncState(); + if (Boolean.FALSE.equals(dataSyncEnabledTargetValue) + && DataStoreSyncState.SYNCHRONIZED.equals(dataStoreSyncState)) { + // TODO : This is hard-coded for onap dmi that need to be addressed + cpsDataService.deleteDataNode(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId, + "/netconf-state", OffsetDateTime.now()); + } + CompositeStateUtils.setDataSyncEnabledFlagWithDataSyncState(dataSyncEnabledTargetValue, compositeState); + inventoryPersistence.saveCmHandleState(cmHandleId, compositeState); + } else { + throw new CpsException("State mismatch exception.", "Cm-Handle not in READY state. Cm handle state is: " + + compositeState.getCmHandleState()); + } + } + + protected void processRemovedCmHandles(final DmiPluginRegistration dmiPluginRegistration, + final DmiPluginRegistrationResponse dmiPluginRegistrationResponse) { + final List tobeRemovedCmHandleIds = dmiPluginRegistration.getRemovedCmHandles(); + final List cmHandleRegistrationResponses = + new ArrayList<>(tobeRemovedCmHandleIds.size()); + final Collection yangModelCmHandles = + inventoryPersistence.getYangModelCmHandles(tobeRemovedCmHandleIds); + updateCmHandleStateBatch(yangModelCmHandles, CmHandleState.DELETING); + + final Set notDeletedCmHandles = new HashSet<>(); + for (final List tobeRemovedCmHandleBatch : Lists.partition(tobeRemovedCmHandleIds, DELETE_BATCH_SIZE)) { + try { + batchDeleteCmHandlesFromDbAndModuleSyncMap(tobeRemovedCmHandleBatch); + tobeRemovedCmHandleBatch.forEach(cmHandleId -> + cmHandleRegistrationResponses.add(CmHandleRegistrationResponse.createSuccessResponse(cmHandleId))); + + } catch (final RuntimeException batchException) { + log.error("Unable to de-register cm-handle batch, retrying on each cm handle"); + for (final String cmHandleId : tobeRemovedCmHandleBatch) { + final CmHandleRegistrationResponse cmHandleRegistrationResponse = + deleteCmHandleAndGetCmHandleRegistrationResponse(cmHandleId); + cmHandleRegistrationResponses.add(cmHandleRegistrationResponse); + if (cmHandleRegistrationResponse.getStatus() != CmHandleRegistrationResponse.Status.SUCCESS) { + notDeletedCmHandles.add(cmHandleId); + } + } + } + } + yangModelCmHandles.removeIf(yangModelCmHandle -> notDeletedCmHandles.contains(yangModelCmHandle.getId())); + updateCmHandleStateBatch(yangModelCmHandles, CmHandleState.DELETED); + dmiPluginRegistrationResponse.setRemovedCmHandles(cmHandleRegistrationResponses); + } + + protected void processCreatedCmHandles(final DmiPluginRegistration dmiPluginRegistration, + final DmiPluginRegistrationResponse dmiPluginRegistrationResponse) { + final List ncmpServiceCmHandles = dmiPluginRegistration.getCreatedCmHandles(); + final List failedCmHandleRegistrationResponses = new ArrayList<>(); + + try { + final Collection rejectedCmHandleIds + = checkAlternateIds(ncmpServiceCmHandles, failedCmHandleRegistrationResponses); + + final Collection succeededCmHandleIds = persistCmHandlesWithState(dmiPluginRegistration, + dmiPluginRegistrationResponse, ncmpServiceCmHandles, rejectedCmHandleIds); + + processTrustLevels(ncmpServiceCmHandles, succeededCmHandleIds); + + } catch (final AlreadyDefinedException alreadyDefinedException) { + failedCmHandleRegistrationResponses.addAll(CmHandleRegistrationResponse.createFailureResponsesFromXpaths( + alreadyDefinedException.getAlreadyDefinedObjectNames(), CM_HANDLE_ALREADY_EXIST)); + } catch (final Exception exception) { + final Collection cmHandleIds = + ncmpServiceCmHandles.stream().map(NcmpServiceCmHandle::getCmHandleId).collect(Collectors.toList()); + failedCmHandleRegistrationResponses.addAll(CmHandleRegistrationResponse + .createFailureResponses(cmHandleIds, exception)); + } + final List mergedCmHandleRegistrationResponses + = new ArrayList<>(failedCmHandleRegistrationResponses); + mergedCmHandleRegistrationResponses.addAll(dmiPluginRegistrationResponse.getCreatedCmHandles()); + + dmiPluginRegistrationResponse.setCreatedCmHandles(mergedCmHandleRegistrationResponses); + } + + protected void processUpdatedCmHandles(final DmiPluginRegistration dmiPluginRegistration, + final DmiPluginRegistrationResponse dmiPluginRegistrationResponse) { + dmiPluginRegistrationResponse.setUpdatedCmHandles(cmHandleRegistrationServicePropertyHandler + .updateCmHandleProperties(dmiPluginRegistration.getUpdatedCmHandles())); + } + + protected void processUpgradedCmHandles( + final DmiPluginRegistration dmiPluginRegistration, + final DmiPluginRegistrationResponse dmiPluginRegistrationResponse) { + + final List cmHandleIds = dmiPluginRegistration.getUpgradedCmHandles().getCmHandles(); + final String upgradedModuleSetTag = dmiPluginRegistration.getUpgradedCmHandles().getModuleSetTag(); + final Map acceptedCmHandleStatePerCmHandle + = new HashMap<>(cmHandleIds.size()); + final List cmHandleUpgradeResponses = new ArrayList<>(cmHandleIds.size()); + + for (final String cmHandleId : cmHandleIds) { + try { + final YangModelCmHandle yangModelCmHandle = inventoryPersistence.getYangModelCmHandle(cmHandleId); + if (yangModelCmHandle.getCompositeState().getCmHandleState() == CmHandleState.READY) { + if (moduleUpgradeCanBeSkipped(yangModelCmHandle, upgradedModuleSetTag)) { + cmHandleUpgradeResponses.add(CmHandleRegistrationResponse.createSuccessResponse(cmHandleId)); + } else { + updateYangModelCmHandleForUpgrade(yangModelCmHandle, upgradedModuleSetTag); + acceptedCmHandleStatePerCmHandle.put(yangModelCmHandle, CmHandleState.LOCKED); + } + } else { + cmHandleUpgradeResponses.add( + CmHandleRegistrationResponse.createFailureResponse(cmHandleId, CM_HANDLES_NOT_READY)); + } + } catch (final DataNodeNotFoundException dataNodeNotFoundException) { + log.error("Unable to find data node for cm handle id : {} , caused by : {}", + cmHandleId, dataNodeNotFoundException.getMessage()); + cmHandleUpgradeResponses.add( + CmHandleRegistrationResponse.createFailureResponse(cmHandleId, CM_HANDLES_NOT_FOUND)); + } catch (final DataValidationException dataValidationException) { + log.error("Unable to upgrade cm handle id: {}, caused by : {}", + cmHandleId, dataValidationException.getMessage()); + cmHandleUpgradeResponses.add( + CmHandleRegistrationResponse.createFailureResponse(cmHandleId, CM_HANDLE_INVALID_ID)); + } + } + cmHandleUpgradeResponses.addAll(upgradeCmHandles(acceptedCmHandleStatePerCmHandle)); + dmiPluginRegistrationResponse.setUpgradedCmHandles(cmHandleUpgradeResponses); + } + + private void processTrustLevels(final Collection cmHandlesToBeCreated, + final Collection succeededCmHandleIds) { + final Map initialTrustLevelPerCmHandleId = new HashMap<>(cmHandlesToBeCreated.size()); + for (final NcmpServiceCmHandle ncmpServiceCmHandle: cmHandlesToBeCreated) { + if (succeededCmHandleIds.contains(ncmpServiceCmHandle.getCmHandleId())) { + initialTrustLevelPerCmHandleId.put(ncmpServiceCmHandle.getCmHandleId(), + ncmpServiceCmHandle.getRegistrationTrustLevel()); + } + } + trustLevelManager.handleInitialRegistrationOfTrustLevels(initialTrustLevelPerCmHandleId); + } + + private static boolean moduleUpgradeCanBeSkipped(final YangModelCmHandle yangModelCmHandle, + final String upgradedModuleSetTag) { + if (StringUtils.isBlank(upgradedModuleSetTag)) { + return false; + } + return yangModelCmHandle.getModuleSetTag().equals(upgradedModuleSetTag); + } + + private static void updateYangModelCmHandleForUpgrade(final YangModelCmHandle yangModelCmHandle, + final String upgradedModuleSetTag) { + final String lockReasonWithModuleSetTag = String.format(ModuleOperationsUtils.MODULE_SET_TAG_MESSAGE_FORMAT, + upgradedModuleSetTag); + yangModelCmHandle.setCompositeState(new CompositeStateBuilder().withCmHandleState(CmHandleState.READY) + .withLockReason(MODULE_UPGRADE, lockReasonWithModuleSetTag).build()); + } + + private CmHandleRegistrationResponse deleteCmHandleAndGetCmHandleRegistrationResponse(final String cmHandleId) { + try { + deleteCmHandleFromDbAndModuleSyncMap(cmHandleId); + return CmHandleRegistrationResponse.createSuccessResponse(cmHandleId); + } catch (final DataNodeNotFoundException dataNodeNotFoundException) { + log.error("Unable to find dataNode for cmHandleId : {} , caused by : {}", + cmHandleId, dataNodeNotFoundException.getMessage()); + return CmHandleRegistrationResponse.createFailureResponse(cmHandleId, CM_HANDLES_NOT_FOUND); + } catch (final DataValidationException dataValidationException) { + log.error("Unable to de-register cm-handle id: {}, caused by: {}", + cmHandleId, dataValidationException.getMessage()); + return CmHandleRegistrationResponse.createFailureResponse(cmHandleId, CM_HANDLE_INVALID_ID); + } catch (final Exception exception) { + log.error("Unable to de-register cm-handle id : {} , caused by : {}", cmHandleId, exception.getMessage()); + return CmHandleRegistrationResponse.createFailureResponse(cmHandleId, exception); + } + } + + private void updateCmHandleStateBatch(final Collection yangModelCmHandles, + final CmHandleState cmHandleState) { + final Map cmHandleStatePerCmHandle = new HashMap<>(yangModelCmHandles.size()); + yangModelCmHandles.forEach(yangModelCmHandle -> cmHandleStatePerCmHandle.put(yangModelCmHandle, cmHandleState)); + lcmEventsCmHandleStateHandler.updateCmHandleStateBatch(cmHandleStatePerCmHandle); + } + + private void deleteCmHandleFromDbAndModuleSyncMap(final String cmHandleId) { + inventoryPersistence.deleteSchemaSetWithCascade(cmHandleId); + inventoryPersistence.deleteDataNode(NCMP_DMI_REGISTRY_PARENT + "/cm-handles[@id='" + cmHandleId + "']"); + removeDeletedCmHandleFromModuleSyncMap(cmHandleId); + } + + private void batchDeleteCmHandlesFromDbAndModuleSyncMap(final Collection cmHandleIds) { + inventoryPersistence.deleteSchemaSetsWithCascade(cmHandleIds); + inventoryPersistence.deleteDataNodes(mapCmHandleIdsToXpaths(cmHandleIds)); + cmHandleIds.forEach(this::removeDeletedCmHandleFromModuleSyncMap); + } + + private Collection mapCmHandleIdsToXpaths(final Collection cmHandles) { + return cmHandles.stream() + .map(cmHandleId -> NCMP_DMI_REGISTRY_PARENT + "/cm-handles[@id='" + cmHandleId + "']") + .collect(Collectors.toSet()); + } + + // CPS-1239 Robustness cleaning of in progress cache + private void removeDeletedCmHandleFromModuleSyncMap(final String cmHandleId) { + if (moduleSyncStartedOnCmHandles.remove(cmHandleId) != null) { + log.debug("{} removed from in progress map", cmHandleId); + } + } + + private List upgradeCmHandles(final Map + cmHandleStatePerCmHandle) { + final List cmHandleIds = getCmHandleIds(cmHandleStatePerCmHandle); + log.info("Moving cm handles : {} into locked (for upgrade) state.", cmHandleIds); + try { + lcmEventsCmHandleStateHandler.updateCmHandleStateBatch(cmHandleStatePerCmHandle); + return CmHandleRegistrationResponse.createSuccessResponses(cmHandleIds); + } catch (final Exception e) { + log.error("Unable to update cmHandleIds : {} , caused by : {}", cmHandleIds, e.getMessage()); + return CmHandleRegistrationResponse.createFailureResponses(cmHandleIds, e); + } + } + + private static List getCmHandleIds(final Map cmHandleStatePerCmHandle) { + return cmHandleStatePerCmHandle.keySet().stream().map(YangModelCmHandle::getId).toList(); + } + + private void setTrustLevelPerDmiPlugin(final DmiPluginRegistration dmiPluginRegistration) { + if (DmiPluginRegistration.isNullEmptyOrBlank(dmiPluginRegistration.getDmiDataPlugin())) { + trustLevelPerDmiPlugin.put(dmiPluginRegistration.getDmiPlugin(), TrustLevel.COMPLETE); + } else { + trustLevelPerDmiPlugin.put(dmiPluginRegistration.getDmiDataPlugin(), TrustLevel.COMPLETE); + } + } + + private Collection checkAlternateIds( + final List cmHandlesToBeCreated, + final List cmHandleRegistrationResponses) { + final Collection rejectedCmHandleIds = alternateIdChecker + .getIdsOfCmHandlesWithRejectedAlternateId(cmHandlesToBeCreated, AlternateIdChecker.Operation.CREATE); + cmHandleRegistrationResponses.addAll(CmHandleRegistrationResponse.createFailureResponses( + rejectedCmHandleIds, ALTERNATE_ID_ALREADY_ASSOCIATED)); + return rejectedCmHandleIds; + } + + private List persistCmHandlesWithState(final DmiPluginRegistration dmiPluginRegistration, + final DmiPluginRegistrationResponse dmiPluginRegistrationResponse, + final List cmHandlesToBeCreated, + final Collection rejectedCmHandleIds) { + final List succeededCmHandleIds = new ArrayList<>(cmHandlesToBeCreated.size()); + final List yangModelCmHandlesToRegister = new ArrayList<>(cmHandlesToBeCreated.size()); + final List cmHandleRegistrationResponses = + new ArrayList<>(cmHandlesToBeCreated.size()); + for (final NcmpServiceCmHandle ncmpServiceCmHandle: cmHandlesToBeCreated) { + if (!rejectedCmHandleIds.contains(ncmpServiceCmHandle.getCmHandleId())) { + yangModelCmHandlesToRegister.add(getYangModelCmHandle(dmiPluginRegistration, ncmpServiceCmHandle)); + cmHandleRegistrationResponses.add( + CmHandleRegistrationResponse.createSuccessResponse(ncmpServiceCmHandle.getCmHandleId())); + succeededCmHandleIds.add(ncmpServiceCmHandle.getCmHandleId()); + } + } + lcmEventsCmHandleStateHandler.initiateStateAdvised(yangModelCmHandlesToRegister); + dmiPluginRegistrationResponse.setCreatedCmHandles(cmHandleRegistrationResponses); + return succeededCmHandleIds; + } + + private YangModelCmHandle getYangModelCmHandle(final DmiPluginRegistration dmiPluginRegistration, + final NcmpServiceCmHandle ncmpServiceCmHandle) { + return YangModelCmHandle.toYangModelCmHandle( + dmiPluginRegistration.getDmiPlugin(), + dmiPluginRegistration.getDmiDataPlugin(), + dmiPluginRegistration.getDmiModelPlugin(), + ncmpServiceCmHandle, + ncmpServiceCmHandle.getModuleSetTag(), + ncmpServiceCmHandle.getAlternateId(), + ncmpServiceCmHandle.getDataProducerIdentifier()); + } + + +} 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 new file mode 100644 index 0000000000..164d917257 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServicePropertyHandler.java @@ -0,0 +1,245 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022-2024 Nordix Foundation + * Modifications Copyright (C) 2022 Bell Canada + * Modifications Copyright (C) 2024 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.inventory; + +import static org.onap.cps.ncmp.api.NcmpResponseStatus.ALTERNATE_ID_ALREADY_ASSOCIATED; +import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLES_NOT_FOUND; +import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLE_INVALID_ID; +import static org.onap.cps.ncmp.impl.inventory.CmHandleRegistrationServicePropertyHandler.PropertyType.DMI_PROPERTY; +import static org.onap.cps.ncmp.impl.inventory.CmHandleRegistrationServicePropertyHandler.PropertyType.PUBLIC_PROPERTY; +import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DATASPACE_NAME; +import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR; +import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT; + +import com.google.common.collect.ImmutableMap; +import java.time.OffsetDateTime; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +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; +import org.onap.cps.ncmp.impl.utils.YangDataConverter; +import org.onap.cps.spi.exceptions.DataNodeNotFoundException; +import org.onap.cps.spi.exceptions.DataValidationException; +import org.onap.cps.spi.model.DataNode; +import org.onap.cps.spi.model.DataNodeBuilder; +import org.onap.cps.utils.ContentType; +import org.onap.cps.utils.JsonObjectMapper; +import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; + +@Slf4j +@Service +@RequiredArgsConstructor +//Accepting the security hotspot as the string checked is generated from inside code and not user input. +@SuppressWarnings("squid:S5852") +public class CmHandleRegistrationServicePropertyHandler { + + private final InventoryPersistence inventoryPersistence; + private final CpsDataService cpsDataService; + private final JsonObjectMapper jsonObjectMapper; + private final AlternateIdChecker alternateIdChecker; + + /** + * Iterates over incoming updatedNcmpServiceCmHandles and update the dataNodes based on the updated attributes. + * The attributes which are not passed will remain as is. + * + * @param updatedNcmpServiceCmHandles collection of CmHandles + */ + public List updateCmHandleProperties( + final Collection updatedNcmpServiceCmHandles) { + final Collection rejectedCmHandleIds = alternateIdChecker + .getIdsOfCmHandlesWithRejectedAlternateId(updatedNcmpServiceCmHandles, AlternateIdChecker.Operation.UPDATE); + final List failureResponses = + CmHandleRegistrationResponse.createFailureResponses(rejectedCmHandleIds, ALTERNATE_ID_ALREADY_ASSOCIATED); + final List cmHandleRegistrationResponses = new ArrayList<>(failureResponses); + for (final NcmpServiceCmHandle updatedNcmpServiceCmHandle : updatedNcmpServiceCmHandles) { + final String cmHandleId = updatedNcmpServiceCmHandle.getCmHandleId(); + if (!rejectedCmHandleIds.contains(cmHandleId)) { + try { + final DataNode existingCmHandleDataNode = inventoryPersistence + .getCmHandleDataNodeByCmHandleId(cmHandleId).iterator().next(); + processUpdates(existingCmHandleDataNode, updatedNcmpServiceCmHandle); + cmHandleRegistrationResponses.add(CmHandleRegistrationResponse.createSuccessResponse(cmHandleId)); + } catch (final DataNodeNotFoundException e) { + log.error("Unable to find dataNode for cmHandleId : {} , caused by : {}", cmHandleId, + e.getMessage()); + cmHandleRegistrationResponses.add( + CmHandleRegistrationResponse.createFailureResponse(cmHandleId, CM_HANDLES_NOT_FOUND)); + } catch (final DataValidationException e) { + log.error("Unable to update cm handle : {}, caused by : {}", cmHandleId, e.getMessage()); + cmHandleRegistrationResponses.add( + CmHandleRegistrationResponse.createFailureResponse(cmHandleId, CM_HANDLE_INVALID_ID)); + } catch (final Exception exception) { + log.error("Unable to update cmHandle : {} , caused by : {}", cmHandleId, exception.getMessage()); + cmHandleRegistrationResponses.add( + CmHandleRegistrationResponse.createFailureResponse(cmHandleId, exception)); + } + } + } + return cmHandleRegistrationResponses; + } + + private void processUpdates(final DataNode existingCmHandleDataNode, + final NcmpServiceCmHandle updatedNcmpServiceCmHandle) { + setAndUpdateCmHandleField( + updatedNcmpServiceCmHandle.getCmHandleId(), "alternate-id", updatedNcmpServiceCmHandle.getAlternateId()); + updateDataProducerIdentifier(existingCmHandleDataNode, updatedNcmpServiceCmHandle); + if (!updatedNcmpServiceCmHandle.getPublicProperties().isEmpty()) { + updateProperties(existingCmHandleDataNode, PUBLIC_PROPERTY, + updatedNcmpServiceCmHandle.getPublicProperties()); + } + if (!updatedNcmpServiceCmHandle.getDmiProperties().isEmpty()) { + updateProperties(existingCmHandleDataNode, DMI_PROPERTY, updatedNcmpServiceCmHandle.getDmiProperties()); + } + } + + private void updateDataProducerIdentifier(final DataNode cmHandleDataNode, + final NcmpServiceCmHandle ncmpServiceCmHandle) { + final String newDataProducerIdentifier = ncmpServiceCmHandle.getDataProducerIdentifier(); + if (StringUtils.hasText(newDataProducerIdentifier)) { + final YangModelCmHandle yangModelCmHandle = + YangDataConverter.convertCmHandleToYangModel(cmHandleDataNode); + final String existingDataProducerIdentifier = yangModelCmHandle.getDataProducerIdentifier(); + if (StringUtils.hasText(existingDataProducerIdentifier)) { + if (!existingDataProducerIdentifier.equals(newDataProducerIdentifier)) { + log.warn("Unable to update dataProducerIdentifier for cmHandle {}. " + + "Value for dataProducerIdentifier has been set previously.", + ncmpServiceCmHandle.getCmHandleId()); + } else { + log.debug("dataProducerIdentifier for cmHandle {} is already set to {}.", + ncmpServiceCmHandle.getCmHandleId(), newDataProducerIdentifier); + } + } else { + setAndUpdateCmHandleField( + yangModelCmHandle.getId(), "data-producer-identifier", newDataProducerIdentifier); + } + } + } + + private void updateProperties(final DataNode existingCmHandleDataNode, final PropertyType propertyType, + final Map updatedProperties) { + final Collection replacementPropertyDataNodes = + getReplacementDataNodes(existingCmHandleDataNode, propertyType, updatedProperties); + replacementPropertyDataNodes.addAll( + getUnchangedPropertyDataNodes(existingCmHandleDataNode, propertyType, updatedProperties)); + if (replacementPropertyDataNodes.isEmpty()) { + removeAllProperties(existingCmHandleDataNode, propertyType); + } else { + inventoryPersistence.replaceListContent(existingCmHandleDataNode.getXpath(), replacementPropertyDataNodes); + } + } + + private void removeAllProperties(final DataNode existingCmHandleDataNode, final PropertyType propertyType) { + existingCmHandleDataNode.getChildDataNodes().forEach(dataNode -> { + final Matcher matcher = propertyType.propertyXpathPattern.matcher(dataNode.getXpath()); + if (matcher.find()) { + log.info("Deleting dataNode with xpath : [{}]", dataNode.getXpath()); + inventoryPersistence.deleteDataNode(dataNode.getXpath()); + } + }); + } + + private Collection getUnchangedPropertyDataNodes(final DataNode existingCmHandleDataNode, + final PropertyType propertyType, + final Map updatedProperties) { + final Collection unchangedPropertyDataNodes = new HashSet<>(); + for (final DataNode existingPropertyDataNode : existingCmHandleDataNode.getChildDataNodes()) { + final Matcher matcher = propertyType.propertyXpathPattern.matcher(existingPropertyDataNode.getXpath()); + if (matcher.find()) { + final String keyName = matcher.group(2); + if (!updatedProperties.containsKey(keyName)) { + unchangedPropertyDataNodes.add(existingPropertyDataNode); + } + } + } + return unchangedPropertyDataNodes; + } + + private Collection getReplacementDataNodes(final DataNode existingCmHandleDataNode, + final PropertyType propertyType, + final Map updatedProperties) { + final Collection replacementPropertyDataNodes = new HashSet<>(); + updatedProperties.forEach((updatedAttributeKey, updatedAttributeValue) -> { + final String propertyXpath = getAttributeXpath(existingCmHandleDataNode, propertyType, updatedAttributeKey); + if (updatedAttributeValue != null) { + log.info("Creating a new DataNode with xpath {} , key : {} and value : {}", propertyXpath, + updatedAttributeKey, updatedAttributeValue); + replacementPropertyDataNodes.add( + buildDataNode(propertyXpath, updatedAttributeKey, updatedAttributeValue)); + } + }); + return replacementPropertyDataNodes; + } + + private String getAttributeXpath(final DataNode cmHandle, final PropertyType propertyType, + final String attributeKey) { + return cmHandle.getXpath() + "/" + propertyType.xpathPrefix + String.format("[@name='%s']", attributeKey); + } + + private DataNode buildDataNode(final String xpath, final String attributeKey, final String attributeValue) { + final Map updatedLeaves = new LinkedHashMap<>(1); + updatedLeaves.put("name", attributeKey); + updatedLeaves.put("value", attributeValue); + log.debug("Building a new node with xpath {} with leaves (name : {} , value : {})", xpath, attributeKey, + attributeValue); + return new DataNodeBuilder().withXpath(xpath).withLeaves(ImmutableMap.copyOf(updatedLeaves)).build(); + } + + private void setAndUpdateCmHandleField(final String cmHandleIdToUpdate, final String fieldName, + final String newFieldValue) { + final Map> dmiRegistryData = new HashMap<>(1); + final Map cmHandleData = new HashMap<>(2); + cmHandleData.put("id", cmHandleIdToUpdate); + cmHandleData.put(fieldName, newFieldValue); + dmiRegistryData.put("cm-handles", cmHandleData); + cpsDataService.updateNodeLeaves(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, NCMP_DMI_REGISTRY_PARENT, + jsonObjectMapper.asJsonString(dmiRegistryData), OffsetDateTime.now(), ContentType.JSON); + log.debug("Updating {} for cmHandle {} with value : {})", fieldName, cmHandleIdToUpdate, newFieldValue); + } + + enum PropertyType { + DMI_PROPERTY("additional-properties"), PUBLIC_PROPERTY("public-properties"); + + private static final String LIST_INDEX_PATTERN = "\\[@(\\w+)[^\\/]'([^']+)']"; + + final String xpathPrefix; + final Pattern propertyXpathPattern; + + PropertyType(final String xpathPrefix) { + this.xpathPrefix = xpathPrefix; + this.propertyXpathPattern = Pattern.compile(xpathPrefix + LIST_INDEX_PATTERN); + } + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CompositeStateUtils.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CompositeStateUtils.java new file mode 100644 index 0000000000..685d204633 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CompositeStateUtils.java @@ -0,0 +1,98 @@ +/* + * ============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.inventory; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.onap.cps.ncmp.api.inventory.models.CompositeState; +import org.onap.cps.ncmp.impl.inventory.models.CmHandleState; + +/** + * It will have all the utility method responsible for handling the composite state. + */ +@Slf4j +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class CompositeStateUtils { + + /** + * Sets the cmHandleState to the provided state and updates the timestamp. + */ + public static void setCompositeState(final CmHandleState cmHandleState, + final CompositeState compositeState) { + compositeState.setCmHandleState(cmHandleState); + compositeState.setLastUpdateTimeNow(); + } + + /** + * Set the Operational datastore sync state based on the global flag. + */ + public static void setInitialDataStoreSyncState(final CompositeState compositeState) { + compositeState.setDataSyncEnabled(false); + final CompositeState.Operational operational = + getInitialDataStoreSyncState(compositeState.getDataSyncEnabled()); + final CompositeState.DataStores dataStores = + CompositeState.DataStores.builder().operationalDataStore(operational).build(); + compositeState.setDataStores(dataStores); + } + + /** + * Set the data sync enabled flag, along with the data store sync state based on this flag. + * + * @param dataSyncEnabled data sync enabled flag + * @param compositeState cm handle composite state + */ + public static void setDataSyncEnabledFlagWithDataSyncState(final boolean dataSyncEnabled, + final CompositeState compositeState) { + compositeState.setDataSyncEnabled(dataSyncEnabled); + compositeState.setLastUpdateTimeNow(); + final CompositeState.Operational operational = getInitialDataStoreSyncState(dataSyncEnabled); + final CompositeState.DataStores dataStores = + CompositeState.DataStores.builder().operationalDataStore(operational).build(); + compositeState.setDataStores(dataStores); + } + + /** + * Get initial data sync state based on data sync enabled boolean flag. + * + * @param dataSyncEnabled data sync enabled boolean flag + * @return the data store sync state + */ + private static CompositeState.Operational getInitialDataStoreSyncState(final boolean dataSyncEnabled) { + final DataStoreSyncState dataStoreSyncState = + dataSyncEnabled ? DataStoreSyncState.UNSYNCHRONIZED : DataStoreSyncState.NONE_REQUESTED; + return CompositeState.Operational.builder().dataStoreSyncState(dataStoreSyncState).build(); + } + + /** + * Sets the cmHandleState to ADVISED and retain the lock details. Used in retry scenarios. + */ + public static void setCompositeStateForRetry(final CompositeState compositeState) { + compositeState.setCmHandleState(CmHandleState.ADVISED); + compositeState.setLastUpdateTimeNow(); + final String oldLockReasonDetails = compositeState.getLockReason().getDetails(); + final CompositeState.LockReason lockReason = + CompositeState.LockReason.builder() + .lockReasonCategory(compositeState.getLockReason().getLockReasonCategory()) + .details(oldLockReasonDetails).build(); + compositeState.setLockReason(lockReason); + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/DataStoreSyncState.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/DataStoreSyncState.java new file mode 100644 index 0000000000..a260ce9cbe --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/DataStoreSyncState.java @@ -0,0 +1,25 @@ +/* + * ============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.inventory; + +public enum DataStoreSyncState { + SYNCHRONIZED, UNSYNCHRONIZED, NONE_REQUESTED +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistence.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistence.java new file mode 100644 index 0000000000..cb4b04e4a0 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistence.java @@ -0,0 +1,147 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022-2024 Nordix Foundation + * 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.inventory; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import org.onap.cps.ncmp.api.inventory.models.CompositeState; +import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; +import org.onap.cps.spi.model.DataNode; +import org.onap.cps.spi.model.ModuleDefinition; +import org.onap.cps.spi.model.ModuleReference; + +public interface InventoryPersistence extends NcmpPersistence { + + /** + * Get the Cm Handle Composite State from the data node. + * + * @param cmHandleId cm handle id + * @return the cm handle composite state + */ + CompositeState getCmHandleState(String cmHandleId); + + /** + * Save the cm handles state. + * + * @param cmHandleId cm handle id + * @param compositeState composite state + */ + void saveCmHandleState(String cmHandleId, CompositeState compositeState); + + /** + * Save all cm handles states in batch. + * + * @param cmHandleStatePerCmHandleId contains cm handle id and updated state + */ + void saveCmHandleStateBatch(Map cmHandleStatePerCmHandleId); + + /** + * This method retrieves DMI service name, DMI properties and the state for a given cm handle. + * + * @param cmHandleId the id of the cm handle + * @return yang model cm handle + */ + YangModelCmHandle getYangModelCmHandle(String cmHandleId); + + /** + * This method retrieves DMI service name, DMI properties and the state for a given cm handle. + * + * @param cmHandleIds a list of the ids of the cm handles + * @return collection of yang model cm handles + */ + Collection getYangModelCmHandles(Collection cmHandleIds); + + /** + * Method to return module definitions by cmHandleId. + * + * @param cmHandleId cm handle ID + * @return a collection of module definitions (moduleName, revision and yang resource content) + */ + Collection getModuleDefinitionsByCmHandleId(String cmHandleId); + + /** + * Method to return module definitions for the given parameters. + * + * @param cmHandleId cm-handle identifier + * @param moduleName module name + * @param moduleRevision the revision of the module + * @return list of module definitions (module name, revision, yang resource content) + */ + Collection getModuleDefinitionsByCmHandleAndModule(String cmHandleId, + String moduleName, + String moduleRevision); + + /** + * Method to return module references by cmHandleId. + * + * @param cmHandleId cm handle ID + * @return a collection of module references (moduleName and revision) + */ + Collection getYangResourcesModuleReferences(String cmHandleId); + + /** + * Method to save cmHandle. + * + * @param yangModelCmHandle cmHandle represented as Yang Model + */ + void saveCmHandle(YangModelCmHandle yangModelCmHandle); + + /** + * Method to save batch of cm handles. + * + * @param yangModelCmHandles cm handle represented as Yang Models + */ + void saveCmHandleBatch(List yangModelCmHandles); + + /** + * Get data node with the given cm handle id. + * + * @param cmHandleId cmHandle ID + * @return data node + */ + Collection getCmHandleDataNodeByCmHandleId(String cmHandleId); + + /** + * Get data node with the given alternate id. + * + * @param alternateId alternate ID + * @return data node + */ + DataNode getCmHandleDataNodeByAlternateId(String alternateId); + + /** + * Get collection of data nodes of given cm handles. + * + * @param cmHandleIds collection of cmHandle IDs + * @return collection of data nodes + */ + Collection getCmHandleDataNodes(Collection cmHandleIds); + + /** + * get CM handles that has given module names. + * + * @param moduleNamesForQuery module names + * @return Collection of CM handle Ids + */ + Collection getCmHandleIdsWithGivenModules(Collection moduleNamesForQuery); +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImpl.java new file mode 100644 index 0000000000..40aefed2aa --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImpl.java @@ -0,0 +1,212 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022-2024 Nordix Foundation + * Modifications Copyright (C) 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.inventory; + +import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS; + +import com.google.common.collect.Lists; +import java.time.OffsetDateTime; +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.extern.slf4j.Slf4j; +import org.onap.cps.api.CpsAnchorService; +import org.onap.cps.api.CpsDataService; +import org.onap.cps.api.CpsModuleService; +import org.onap.cps.ncmp.api.inventory.models.CompositeState; +import org.onap.cps.ncmp.api.inventory.models.CompositeStateBuilder; +import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; +import org.onap.cps.ncmp.impl.utils.YangDataConverter; +import org.onap.cps.spi.FetchDescendantsOption; +import org.onap.cps.spi.exceptions.DataNodeNotFoundException; +import org.onap.cps.spi.exceptions.DataValidationException; +import org.onap.cps.spi.model.DataNode; +import org.onap.cps.spi.model.ModuleDefinition; +import org.onap.cps.spi.model.ModuleReference; +import org.onap.cps.spi.utils.CpsValidator; +import org.onap.cps.utils.JsonObjectMapper; +import org.springframework.stereotype.Component; + +@Slf4j +@Component +public class InventoryPersistenceImpl extends NcmpPersistenceImpl implements InventoryPersistence { + + private static final int CMHANDLE_BATCH_SIZE = 100; + + private final CpsModuleService cpsModuleService; + private final CpsAnchorService cpsAnchorService; + private final CpsValidator cpsValidator; + private final CmHandleQueryService cmHandleQueryService; + + /** + * initialize an inventory persistence object. + * + * @param jsonObjectMapper json mapper object + * @param cpsDataService cps data service instance + * @param cpsModuleService cps module service instance + * @param cpsValidator cps validation service instance + * @param cpsAnchorService cps anchor service instance + */ + public InventoryPersistenceImpl(final JsonObjectMapper jsonObjectMapper, final CpsDataService cpsDataService, + final CpsModuleService cpsModuleService, final CpsValidator cpsValidator, + final CpsAnchorService cpsAnchorService, + final CmHandleQueryService cmHandleQueryService) { + super(jsonObjectMapper, cpsDataService, cpsModuleService, cpsValidator); + this.cpsModuleService = cpsModuleService; + this.cpsAnchorService = cpsAnchorService; + this.cpsValidator = cpsValidator; + this.cmHandleQueryService = cmHandleQueryService; + } + + + @Override + public CompositeState getCmHandleState(final String cmHandleId) { + final DataNode stateAsDataNode = cpsDataService.getDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, + getXPathForCmHandleById(cmHandleId) + "/state", FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) + .iterator().next(); + cpsValidator.validateNameCharacters(cmHandleId); + return new CompositeStateBuilder().fromDataNode(stateAsDataNode).build(); + } + + @Override + public void saveCmHandleState(final String cmHandleId, final CompositeState compositeState) { + final String cmHandleJsonData = createStateJsonData(jsonObjectMapper.asJsonString(compositeState)); + cpsDataService.updateDataNodeAndDescendants(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, + getXPathForCmHandleById(cmHandleId), cmHandleJsonData, OffsetDateTime.now()); + } + + @Override + public void saveCmHandleStateBatch(final Map cmHandleStatePerCmHandleId) { + final Map cmHandlesJsonDataMap = new HashMap<>(); + cmHandleStatePerCmHandleId.forEach((cmHandleId, compositeState) -> cmHandlesJsonDataMap.put( + getXPathForCmHandleById(cmHandleId), + createStateJsonData(jsonObjectMapper.asJsonString(compositeState)))); + cpsDataService.updateDataNodesAndDescendants(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, + cmHandlesJsonDataMap, OffsetDateTime.now()); + } + + @Override + public YangModelCmHandle getYangModelCmHandle(final String cmHandleId) { + cpsValidator.validateNameCharacters(cmHandleId); + final DataNode dataNode = getCmHandleDataNodeByCmHandleId(cmHandleId).iterator().next(); + return YangDataConverter.convertCmHandleToYangModel(dataNode); + } + + @Override + public Collection getYangModelCmHandles(final Collection cmHandleIds) { + final Collection validCmHandleIds = new ArrayList<>(cmHandleIds.size()); + cmHandleIds.forEach(cmHandleId -> { + try { + cpsValidator.validateNameCharacters(cmHandleId); + validCmHandleIds.add(cmHandleId); + } catch (final DataValidationException dataValidationException) { + log.error("DataValidationException in CmHandleId {} to be ignored", + dataValidationException.getMessage()); + } + }); + return YangDataConverter.convertDataNodesToYangModelCmHandles(getCmHandleDataNodes(validCmHandleIds)); + } + + @Override + public Collection getModuleDefinitionsByCmHandleId(final String cmHandleId) { + return cpsModuleService.getModuleDefinitionsByAnchorName(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId); + } + + @Override + public Collection getModuleDefinitionsByCmHandleAndModule(final String cmHandleId, + final String moduleName, + final String moduleRevision) { + cpsValidator.validateNameCharacters(cmHandleId, moduleName); + return cpsModuleService.getModuleDefinitionsByAnchorAndModule(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, + cmHandleId, moduleName, moduleRevision); + } + + @Override + public Collection getYangResourcesModuleReferences(final String cmHandleId) { + cpsValidator.validateNameCharacters(cmHandleId); + return cpsModuleService.getYangResourcesModuleReferences(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId); + } + + @Override + public void saveCmHandle(final YangModelCmHandle yangModelCmHandle) { + saveCmHandleBatch(Collections.singletonList(yangModelCmHandle)); + } + + @Override + public void saveCmHandleBatch(final List yangModelCmHandles) { + for (final List yangModelCmHandleBatch : + Lists.partition(yangModelCmHandles, CMHANDLE_BATCH_SIZE)) { + final String cmHandlesJsonData = createCmHandlesJsonData(yangModelCmHandleBatch); + cpsDataService.saveListElements(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, + NCMP_DMI_REGISTRY_PARENT, cmHandlesJsonData, NO_TIMESTAMP); + } + } + + @Override + public Collection getCmHandleDataNodeByCmHandleId(final String cmHandleId) { + return this.getDataNode(getXPathForCmHandleById(cmHandleId)); + } + + @Override + public DataNode getCmHandleDataNodeByAlternateId(final String alternateId) { + final String cpsPathForCmHandleByAlternateId = getCpsPathForCmHandleByAlternateId(alternateId); + final Collection dataNodes = cmHandleQueryService + .queryNcmpRegistryByCpsPath(cpsPathForCmHandleByAlternateId, OMIT_DESCENDANTS); + if (dataNodes.isEmpty()) { + throw new DataNodeNotFoundException(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, + cpsPathForCmHandleByAlternateId); + } + return dataNodes.iterator().next(); + } + + @Override + public Collection getCmHandleDataNodes(final Collection cmHandleIds) { + final Collection xpaths = new ArrayList<>(cmHandleIds.size()); + cmHandleIds.forEach(cmHandleId -> xpaths.add(getXPathForCmHandleById(cmHandleId))); + return this.getDataNodes(xpaths); + } + + @Override + public Collection getCmHandleIdsWithGivenModules(final Collection moduleNamesForQuery) { + return cpsAnchorService.queryAnchorNames(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, moduleNamesForQuery); + } + + private static String getXPathForCmHandleById(final String cmHandleId) { + return NCMP_DMI_REGISTRY_PARENT + "/cm-handles[@id='" + cmHandleId + "']"; + } + + private static String getCpsPathForCmHandleByAlternateId(final String alternateId) { + return NCMP_DMI_REGISTRY_PARENT + "/cm-handles[@alternate-id='" + alternateId + "']"; + } + + private static String createStateJsonData(final String state) { + return "{\"state\":" + state + "}"; + } + + private String createCmHandlesJsonData(final List yangModelCmHandles) { + return "{\"cm-handles\":" + jsonObjectMapper.asJsonString(yangModelCmHandles) + "}"; + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/NcmpPersistence.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/NcmpPersistence.java new file mode 100644 index 0000000000..5271485e3b --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/NcmpPersistence.java @@ -0,0 +1,116 @@ +/* + * ============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.inventory; + +import java.time.OffsetDateTime; +import java.util.Collection; +import org.onap.cps.spi.FetchDescendantsOption; +import org.onap.cps.spi.model.DataNode; + +/** + * DmiRegistryConstants class to be strictly used for DMI Related constants only. + */ +public interface NcmpPersistence { + + String NCMP_DATASPACE_NAME = "NCMP-Admin"; + String NCMP_DMI_REGISTRY_ANCHOR = "ncmp-dmi-registry"; + String NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME = "NFP-Operational"; + String NCMP_DMI_REGISTRY_PARENT = "/dmi-registry"; + OffsetDateTime NO_TIMESTAMP = null; + + /** + * Method to delete a list or a list element. + * + * @param listElementXpath list element xPath + */ + void deleteListOrListElement(String listElementXpath); + + /** + * Method to delete a schema set. + * + * @param schemaSetName schema set name + */ + void deleteSchemaSetWithCascade(String schemaSetName); + + /** + * Method to delete multiple schema sets. + * + * @param schemaSetNames schema set names + */ + void deleteSchemaSetsWithCascade(Collection schemaSetNames); + + /** + * Get data node via xpath. + * + * @param xpath xpath + * @return data node + */ + Collection getDataNode(String xpath); + + /** + * Get data node via xpath. + * + * @param xpath xpath + * @param fetchDescendantsOption fetch descendants option + * @return data node + */ + Collection getDataNode(String xpath, FetchDescendantsOption fetchDescendantsOption); + + /** + * Get collection of data nodes via xpaths. + * + * @param xpaths collection of xpaths + * @return collection of data nodes + */ + Collection getDataNodes(Collection xpaths); + + /** + * Get collection of data nodes via xpaths. + * + * @param xpaths collection of xpaths + * @param fetchDescendantsOption fetch descendants option + * @return collection of data nodes + */ + Collection getDataNodes(Collection xpaths, + FetchDescendantsOption fetchDescendantsOption); + + /** + * Replaces list content by removing all existing elements and inserting the given new elements as data nodes. + * + * @param parentNodeXpath parent node xpath + * @param dataNodes datanodes representing the updated data + */ + void replaceListContent(String parentNodeXpath, Collection dataNodes); + + /** + * Deletes data node. + * + * @param dataNodeXpath data node xpath + */ + void deleteDataNode(String dataNodeXpath); + + /** + * Deletes multiple data nodes. + * + * @param dataNodeXpaths data node xpaths + */ + void deleteDataNodes(Collection dataNodeXpaths); +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/NcmpPersistenceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/NcmpPersistenceImpl.java new file mode 100644 index 0000000000..e44b6ba342 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/NcmpPersistenceImpl.java @@ -0,0 +1,119 @@ +/* + * ============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.inventory; + +import static org.onap.cps.spi.CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED; +import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS; + +import io.micrometer.core.annotation.Timed; +import java.util.Collection; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.onap.cps.api.CpsDataService; +import org.onap.cps.api.CpsModuleService; +import org.onap.cps.spi.FetchDescendantsOption; +import org.onap.cps.spi.exceptions.SchemaSetNotFoundException; +import org.onap.cps.spi.model.DataNode; +import org.onap.cps.spi.utils.CpsValidator; +import org.onap.cps.utils.JsonObjectMapper; +import org.springframework.stereotype.Component; + +@Slf4j +@RequiredArgsConstructor +@Component +public class NcmpPersistenceImpl implements NcmpPersistence { + + protected final JsonObjectMapper jsonObjectMapper; + protected final CpsDataService cpsDataService; + private final CpsModuleService cpsModuleService; + private final CpsValidator cpsValidator; + + @Override + public void deleteListOrListElement(final String listElementXpath) { + cpsDataService.deleteListOrListElement(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, listElementXpath, + NO_TIMESTAMP); + } + + @Override + @Timed(value = "cps.ncmp.inventory.persistence.schemaset.delete", + description = "Time taken to delete a schemaset") + public void deleteSchemaSetWithCascade(final String schemaSetName) { + try { + cpsValidator.validateNameCharacters(schemaSetName); + cpsModuleService.deleteSchemaSet(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, schemaSetName, + CASCADE_DELETE_ALLOWED); + } catch (final SchemaSetNotFoundException schemaSetNotFoundException) { + log.warn("Schema set {} does not exist or already deleted", schemaSetName); + } + } + + @Override + @Timed(value = "cps.ncmp.inventory.persistence.schemaset.delete.batch", + description = "Time taken to delete multiple schemaset") + public void deleteSchemaSetsWithCascade(final Collection schemaSetNames) { + cpsValidator.validateNameCharacters(schemaSetNames); + cpsModuleService.deleteSchemaSetsWithCascade(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, schemaSetNames); + } + + @Override + @Timed(value = "cps.ncmp.inventory.persistence.datanode.get", + description = "Time taken to get a data node (from ncmp dmi registry)") + public Collection getDataNode(final String xpath) { + return getDataNode(xpath, INCLUDE_ALL_DESCENDANTS); + } + + @Override + @Timed(value = "cps.ncmp.inventory.persistence.datanode.get", + description = "Time taken to get a data node (from ncmp dmi registry)") + public Collection getDataNode(final String xpath, final FetchDescendantsOption fetchDescendantsOption) { + return cpsDataService.getDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, xpath, + fetchDescendantsOption); + } + + @Override + public Collection getDataNodes(final Collection xpaths) { + return getDataNodes(xpaths, INCLUDE_ALL_DESCENDANTS); + } + + @Override + public Collection getDataNodes(final Collection xpaths, + final FetchDescendantsOption fetchDescendantsOption) { + return cpsDataService.getDataNodesForMultipleXpaths(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, xpaths, + fetchDescendantsOption); + } + + @Override + public void replaceListContent(final String parentNodeXpath, final Collection dataNodes) { + cpsDataService.replaceListContent(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, parentNodeXpath, dataNodes, + NO_TIMESTAMP); + } + + @Override + public void deleteDataNode(final String dataNodeXpath) { + cpsDataService.deleteDataNode(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, dataNodeXpath, NO_TIMESTAMP); + } + + @Override + public void deleteDataNodes(final Collection dataNodeXpaths) { + cpsDataService.deleteDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, dataNodeXpaths, NO_TIMESTAMP); + } + +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryService.java new file mode 100644 index 0000000000..e5848c0dfa --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryService.java @@ -0,0 +1,72 @@ +/* + * ============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.inventory; + +import java.util.Collection; +import org.onap.cps.ncmp.api.inventory.models.CmHandleQueryServiceParameters; +import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle; + +public interface ParameterizedCmHandleQueryService { + /** + * Query and return cm handle ids that match the given query parameters. + * Supported query types: + * public properties + * modules + * cps-path + * + * @param cmHandleQueryServiceParameters the cm handle query parameters + * @return collection of cm handle ids + */ + Collection queryCmHandleIds(CmHandleQueryServiceParameters cmHandleQueryServiceParameters); + + /** + * Query and return cm handle ids that match the given query parameters. + * Supported query types: + * public properties + * private (additional) properties + * dmi-names + * The inventory interface also allows conditions on private (additional) properties and dmi names + * + * @param cmHandleQueryServiceParameters the cm handle query parameters + * @return collection of cm handle ids + */ + Collection queryCmHandleIdsForInventory(CmHandleQueryServiceParameters cmHandleQueryServiceParameters); + + /** + * Query and return cm handle objects that match the given query parameters. + * Supported query types: + * public properties + * modules + * cps-path + * + * @param cmHandleQueryServiceParameters the cm handle query parameters + * @return collection of cm handles + */ + Collection queryCmHandles(CmHandleQueryServiceParameters cmHandleQueryServiceParameters); + + /** + * Get all cm handle objects. + * Note: it is similar to all the queries above but simply no conditions and hence not 'parameterized' + * + * @return collection of cm handles + */ + Collection getAllCmHandles(); +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryServiceImpl.java new file mode 100644 index 0000000000..51e403fd66 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryServiceImpl.java @@ -0,0 +1,283 @@ +/* + * ============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.inventory; + +import static org.onap.cps.ncmp.impl.inventory.CmHandleQueryParametersValidator.validateCpsPathConditionProperties; +import static org.onap.cps.ncmp.impl.inventory.CmHandleQueryParametersValidator.validateModuleNameConditionProperties; +import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT; +import static org.onap.cps.ncmp.impl.inventory.models.CmHandleQueryConditions.HAS_ALL_MODULES; +import static org.onap.cps.ncmp.impl.inventory.models.CmHandleQueryConditions.HAS_ALL_PROPERTIES; +import static org.onap.cps.ncmp.impl.inventory.models.CmHandleQueryConditions.WITH_CPS_PATH; +import static org.onap.cps.ncmp.impl.inventory.models.CmHandleQueryConditions.WITH_TRUST_LEVEL; +import static org.onap.cps.ncmp.impl.utils.YangDataConverter.convertYangModelCmHandleToNcmpServiceCmHandle; +import static org.onap.cps.spi.FetchDescendantsOption.DIRECT_CHILDREN_ONLY; +import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS; + +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.function.Function; +import java.util.stream.Collectors; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.onap.cps.cpspath.parser.PathParsingException; +import org.onap.cps.ncmp.api.inventory.models.CmHandleQueryServiceParameters; +import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle; +import org.onap.cps.ncmp.impl.inventory.models.InventoryQueryConditions; +import org.onap.cps.ncmp.impl.inventory.models.PropertyType; +import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; +import org.onap.cps.ncmp.impl.utils.YangDataConverter; +import org.onap.cps.spi.exceptions.DataValidationException; +import org.onap.cps.spi.model.ConditionProperties; +import org.onap.cps.spi.model.DataNode; +import org.springframework.stereotype.Service; + +@Service +@Slf4j +@RequiredArgsConstructor +public class ParameterizedCmHandleQueryServiceImpl implements ParameterizedCmHandleQueryService { + + private static final Collection NO_QUERY_TO_EXECUTE = null; + private final CmHandleQueryService cmHandleQueryService; + private final InventoryPersistence inventoryPersistence; + + @Override + public Collection queryCmHandleIds( + final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) { + return executeQueries(cmHandleQueryServiceParameters, + this::executeCpsPathQuery, + this::queryCmHandlesByPublicProperties, + this::executeModuleNameQuery, + this::queryCmHandlesByTrustLevel); + } + + @Override + public Collection queryCmHandleIdsForInventory( + final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) { + return executeQueries(cmHandleQueryServiceParameters, + this::queryCmHandlesByPublicProperties, + this::queryCmHandlesByPrivateProperties, + this::queryCmHandlesByDmiPlugin); + } + + @Override + public Collection queryCmHandles( + final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) { + + if (cmHandleQueryServiceParameters.getCmHandleQueryParameters().isEmpty()) { + return getAllCmHandles(); + } + + final Collection cmHandleIds = queryCmHandleIds(cmHandleQueryServiceParameters); + + return getNcmpServiceCmHandles(cmHandleIds); + } + + @Override + public Collection getAllCmHandles() { + final DataNode dataNode = inventoryPersistence.getDataNode(NCMP_DMI_REGISTRY_PARENT).iterator().next(); + return dataNode.getChildDataNodes().stream().map(this::createNcmpServiceCmHandle).collect(Collectors.toSet()); + } + + private Collection queryCmHandlesByDmiPlugin( + final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) { + final Map dmiPropertyQueryPairs = + getPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters(), + InventoryQueryConditions.CM_HANDLE_WITH_DMI_PLUGIN.getName()); + if (dmiPropertyQueryPairs.isEmpty()) { + return NO_QUERY_TO_EXECUTE; + } + + final String dmiPluginIdentifierValue = dmiPropertyQueryPairs + .get(PropertyType.DMI_PLUGIN.getYangContainerName()); + + return cmHandleQueryService.getCmHandleIdsByDmiPluginIdentifier(dmiPluginIdentifierValue); + } + + private Collection queryCmHandlesByPrivateProperties( + final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) { + + final Map privatePropertyQueryPairs = + getPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters(), + InventoryQueryConditions.HAS_ALL_ADDITIONAL_PROPERTIES.getName()); + + if (privatePropertyQueryPairs.isEmpty()) { + return NO_QUERY_TO_EXECUTE; + } + return cmHandleQueryService.queryCmHandleAdditionalProperties(privatePropertyQueryPairs); + } + + private Collection queryCmHandlesByPublicProperties( + final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) { + + final Map publicPropertyQueryPairs = + getPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters(), + HAS_ALL_PROPERTIES.getConditionName()); + + if (publicPropertyQueryPairs.isEmpty()) { + return NO_QUERY_TO_EXECUTE; + } + return cmHandleQueryService.queryCmHandlePublicProperties(publicPropertyQueryPairs); + } + + private Collection queryCmHandlesByTrustLevel(final CmHandleQueryServiceParameters + cmHandleQueryServiceParameters) { + + final Map trustLevelPropertyQueryPairs = + getPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters(), + WITH_TRUST_LEVEL.getConditionName()); + + if (trustLevelPropertyQueryPairs.isEmpty()) { + return NO_QUERY_TO_EXECUTE; + } + return cmHandleQueryService.queryCmHandlesByTrustLevel(trustLevelPropertyQueryPairs); + } + + private Collection executeModuleNameQuery( + final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) { + final Collection moduleNamesForQuery = + getModuleNamesForQuery(cmHandleQueryServiceParameters.getCmHandleQueryParameters()); + if (moduleNamesForQuery.isEmpty()) { + return NO_QUERY_TO_EXECUTE; + } + return inventoryPersistence.getCmHandleIdsWithGivenModules(moduleNamesForQuery); + } + + private Collection executeCpsPathQuery( + final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) { + final Map cpsPathCondition + = getCpsPathCondition(cmHandleQueryServiceParameters.getCmHandleQueryParameters()); + if (!validateCpsPathConditionProperties(cpsPathCondition)) { + return Collections.emptySet(); + } + final Collection cpsPathQueryResult; + if (cpsPathCondition.isEmpty()) { + return NO_QUERY_TO_EXECUTE; + } + try { + cpsPathQueryResult = collectCmHandleIdsFromDataNodes( + cmHandleQueryService.queryCmHandleAncestorsByCpsPath( + cpsPathCondition.get("cpsPath"), OMIT_DESCENDANTS)); + } catch (final PathParsingException pathParsingException) { + throw new DataValidationException(pathParsingException.getMessage(), pathParsingException.getDetails(), + pathParsingException); + } + return cpsPathQueryResult; + } + + private Collection getModuleNamesForQuery(final List conditionProperties) { + final List result = new ArrayList<>(); + getConditions(conditionProperties, HAS_ALL_MODULES.getConditionName()).forEach( + conditionProperty -> { + validateModuleNameConditionProperties(conditionProperty); + result.add(conditionProperty.get("moduleName")); + }); + return result; + } + + private Map getCpsPathCondition(final List conditionProperties) { + final Map result = new HashMap<>(); + getConditions(conditionProperties, WITH_CPS_PATH.getConditionName()).forEach(result::putAll); + return result; + } + + private Map getPropertyPairs(final List conditionProperties, + final String queryProperty) { + final Map result = new HashMap<>(); + getConditions(conditionProperties, queryProperty).forEach(result::putAll); + return result; + } + + private List> getConditions(final List conditionProperties, + final String name) { + for (final ConditionProperties conditionProperty : conditionProperties) { + if (conditionProperty.getConditionName().equals(name)) { + return conditionProperty.getConditionParameters(); + } + } + return Collections.emptyList(); + } + + private Collection getAllCmHandleIds() { + final DataNode dataNode = inventoryPersistence.getDataNode(NCMP_DMI_REGISTRY_PARENT, DIRECT_CHILDREN_ONLY) + .iterator().next(); + return collectCmHandleIdsFromDataNodes(dataNode.getChildDataNodes()); + } + + private Collection getNcmpServiceCmHandles(final Collection cmHandleIds) { + final Collection yangModelcmHandles + = inventoryPersistence.getYangModelCmHandles(cmHandleIds); + + final Collection ncmpServiceCmHandles = new ArrayList<>(yangModelcmHandles.size()); + + yangModelcmHandles.forEach(yangModelcmHandle -> + ncmpServiceCmHandles.add(YangDataConverter.convertYangModelCmHandleToNcmpServiceCmHandle(yangModelcmHandle)) + ); + return ncmpServiceCmHandles; + } + + private NcmpServiceCmHandle createNcmpServiceCmHandle(final DataNode dataNode) { + return convertYangModelCmHandleToNcmpServiceCmHandle(YangDataConverter.convertCmHandleToYangModel(dataNode)); + } + + private Collection executeQueries(final CmHandleQueryServiceParameters cmHandleQueryServiceParameters, + final Function>... + queryFunctions) { + if (cmHandleQueryServiceParameters.getCmHandleQueryParameters().isEmpty()) { + return getAllCmHandleIds(); + } + Collection combinedQueryResult = NO_QUERY_TO_EXECUTE; + for (final Function> queryFunction : queryFunctions) { + final Collection queryResult = queryFunction.apply(cmHandleQueryServiceParameters); + if (noEntriesFoundCanStopQuerying(queryResult)) { + return Collections.emptySet(); + } + combinedQueryResult = combineCmHandleQueryResults(combinedQueryResult, queryResult); + } + return combinedQueryResult; + } + + private boolean noEntriesFoundCanStopQuerying(final Collection queryResult) { + return queryResult != NO_QUERY_TO_EXECUTE && queryResult.isEmpty(); + } + + private Collection combineCmHandleQueryResults(final Collection firstQuery, + final Collection secondQuery) { + if (firstQuery == NO_QUERY_TO_EXECUTE && secondQuery == NO_QUERY_TO_EXECUTE) { + return NO_QUERY_TO_EXECUTE; + } else if (firstQuery == NO_QUERY_TO_EXECUTE) { + return secondQuery; + } else if (secondQuery == NO_QUERY_TO_EXECUTE) { + return firstQuery; + } else { + firstQuery.retainAll(secondQuery); + return firstQuery; + } + } + + private Collection collectCmHandleIdsFromDataNodes(final Collection dataNodes) { + return dataNodes.stream().map(dataNode -> (String) dataNode.getLeaves().get("id")).collect(Collectors.toSet()); + } + +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/CmHandleQueryConditions.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/CmHandleQueryConditions.java new file mode 100644 index 0000000000..6be5c8ba16 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/CmHandleQueryConditions.java @@ -0,0 +1,43 @@ +/* + * ============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.inventory.models; + +import java.util.Arrays; +import java.util.Collection; +import java.util.stream.Collectors; +import lombok.Getter; + +@Getter +public enum CmHandleQueryConditions { + HAS_ALL_PROPERTIES("hasAllProperties"), + HAS_ALL_MODULES("hasAllModules"), + WITH_CPS_PATH("cmHandleWithCpsPath"), + WITH_TRUST_LEVEL("cmHandleWithTrustLevel"); + + public static final Collection ALL_CONDITION_NAMES = Arrays.stream(CmHandleQueryConditions.values()) + .map(CmHandleQueryConditions::getConditionName).collect(Collectors.toList()); + + private final String conditionName; + + CmHandleQueryConditions(final String conditionName) { + this.conditionName = conditionName; + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/CmHandleState.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/CmHandleState.java new file mode 100644 index 0000000000..9a4b3e2a83 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/CmHandleState.java @@ -0,0 +1,25 @@ +/* + * ============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.inventory.models; + +public enum CmHandleState { + ADVISED, READY, LOCKED, DELETING, DELETED +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/InventoryQueryConditions.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/InventoryQueryConditions.java new file mode 100644 index 0000000000..fce285b415 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/InventoryQueryConditions.java @@ -0,0 +1,42 @@ +/* + * ============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.inventory.models; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum InventoryQueryConditions { + + HAS_ALL_PROPERTIES("hasAllProperties"), + HAS_ALL_ADDITIONAL_PROPERTIES("hasAllAdditionalProperties"), + CM_HANDLE_WITH_DMI_PLUGIN("cmHandleWithDmiPlugin"); + + public static final List ALL_CONDITION_NAMES = Arrays.stream(InventoryQueryConditions.values()) + .map(InventoryQueryConditions::getName).collect(Collectors.toList()); + + private final String name; + +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/LockReasonCategory.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/LockReasonCategory.java new file mode 100644 index 0000000000..1003aeca2d --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/LockReasonCategory.java @@ -0,0 +1,28 @@ +/* + * ============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.inventory.models; + +public enum LockReasonCategory { + MODULE_SYNC_FAILED, + MODULE_UPGRADE, + MODULE_UPGRADE_FAILED, + LOCKED_MISBEHAVING +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/ModelledDmiServiceLeaves.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/ModelledDmiServiceLeaves.java new file mode 100644 index 0000000000..e9c4957d0c --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/ModelledDmiServiceLeaves.java @@ -0,0 +1,38 @@ +/* + * ============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.inventory.models; + +public enum ModelledDmiServiceLeaves { + DMI_SERVICE_NAME("dmi-service-name"), + DMI_DATA_SERVICE_NAME("dmi-data-service-name"), + DMI_MODEL_SERVICE_NAME("dmi-model-service-name"); + + private String leafName; + + ModelledDmiServiceLeaves(final String dmiPluginIdentifierKey) { + this.leafName = dmiPluginIdentifierKey; + } + + public String getLeafName() { + return leafName; + } + +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/PropertyType.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/PropertyType.java new file mode 100644 index 0000000000..cc8b094b4c --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/PropertyType.java @@ -0,0 +1,34 @@ +/* + * ============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.inventory.models; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum PropertyType { + ADDITIONAL("additional-properties"), + PUBLIC("public-properties"), + DMI_PLUGIN("dmiPluginName"); + + private final String yangContainerName; +} 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 new file mode 100644 index 0000000000..d96c9c7206 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/YangModelCmHandle.java @@ -0,0 +1,175 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021-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.models; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +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; + +/** + * Cm Handle which follows the Yang resource dmi registry model when persisting data to DMI or the DB. + * Yang model CmHandle + */ +@Getter +@Setter +@NoArgsConstructor +@JsonInclude(Include.NON_NULL) +@EqualsAndHashCode(onlyExplicitlyIncluded = true) +public class YangModelCmHandle { + + @EqualsAndHashCode.Include + private String id; + + @JsonProperty("dmi-service-name") + private String dmiServiceName; + + @JsonProperty("dmi-data-service-name") + private String dmiDataServiceName; + + @JsonProperty("state") + private CompositeState compositeState; + + @JsonProperty("dmi-model-service-name") + private String dmiModelServiceName; + + @JsonProperty("module-set-tag") + private String moduleSetTag; + + @JsonProperty("alternate-id") + private String alternateId; + + @JsonProperty("data-producer-identifier") + private String dataProducerIdentifier; + + @JsonProperty("additional-properties") + private List dmiProperties; + + @JsonProperty("public-properties") + private List publicProperties; + + /** + * Creates a deep copy of Yang Model Cm Handle. + * + * @param original Yang Model Cm Handle + * @return instance of yangModelCmHandle + */ + public static YangModelCmHandle deepCopyOf(final YangModelCmHandle original) { + final YangModelCmHandle copy = new YangModelCmHandle(); + copy.id = original.getId(); + copy.dmiServiceName = original.getDmiServiceName(); + copy.dmiDataServiceName = original.getDmiDataServiceName(); + copy.dmiModelServiceName = original.getDmiModelServiceName(); + copy.compositeState = + original.getCompositeState() == null ? null : new CompositeState(original.getCompositeState()); + copy.dmiProperties = original.getDmiProperties() == null ? null : new ArrayList<>(original.getDmiProperties()); + copy.publicProperties = + original.getPublicProperties() == null ? null : new ArrayList<>(original.getPublicProperties()); + copy.moduleSetTag = original.getModuleSetTag(); + copy.alternateId = original.getAlternateId(); + copy.dataProducerIdentifier = original.getDataProducerIdentifier(); + return copy; + } + + /** + * Create a yangModelCmHandle. + * + * @param dmiServiceName dmi service name + * @param dmiDataServiceName dmi data service name + * @param dmiModelServiceName dmi model service name + * @param ncmpServiceCmHandle the cm handle + * @param moduleSetTag moduleSetTag + * @param alternateId alternateId + * @param dataProducerIdentifier dataProducerIdentifier + * @return instance of yangModelCmHandle + */ + public static YangModelCmHandle toYangModelCmHandle(final String dmiServiceName, + final String dmiDataServiceName, + final String dmiModelServiceName, + final NcmpServiceCmHandle ncmpServiceCmHandle, + final String moduleSetTag, + final String alternateId, + final String dataProducerIdentifier) { + final YangModelCmHandle yangModelCmHandle = new YangModelCmHandle(); + yangModelCmHandle.setId(ncmpServiceCmHandle.getCmHandleId()); + yangModelCmHandle.setDmiServiceName(dmiServiceName); + yangModelCmHandle.setDmiDataServiceName(dmiDataServiceName); + yangModelCmHandle.setDmiModelServiceName(dmiModelServiceName); + yangModelCmHandle.setModuleSetTag(moduleSetTag == null ? StringUtils.EMPTY : moduleSetTag); + yangModelCmHandle.setAlternateId(alternateId == null ? StringUtils.EMPTY : alternateId); + yangModelCmHandle.setDataProducerIdentifier( + dataProducerIdentifier == null ? StringUtils.EMPTY : dataProducerIdentifier); + yangModelCmHandle.setDmiProperties(asYangModelCmHandleProperties(ncmpServiceCmHandle.getDmiProperties())); + yangModelCmHandle.setPublicProperties(asYangModelCmHandleProperties( + ncmpServiceCmHandle.getPublicProperties())); + yangModelCmHandle.setCompositeState(ncmpServiceCmHandle.getCompositeState()); + return yangModelCmHandle; + } + + /** + * Resolve a dmi service name. + * + * @param requiredService indicates what typo of service is required + * @return dmi service name + */ + public String resolveDmiServiceName(final RequiredDmiService requiredService) { + if (StringUtils.isBlank(dmiServiceName)) { + if (RequiredDmiService.DATA.equals(requiredService)) { + return dmiDataServiceName; + } + return dmiModelServiceName; + } + return dmiServiceName; + } + + private static List asYangModelCmHandleProperties(final Map propertiesAsMap) { + final List yangModelCmHandleProperties = new ArrayList<>(propertiesAsMap.size()); + for (final Map.Entry entry : propertiesAsMap.entrySet()) { + yangModelCmHandleProperties.add(new YangModelCmHandle.Property(entry.getKey(), entry.getValue())); + } + return yangModelCmHandleProperties; + } + + @AllArgsConstructor + @Data + public static class Property { + + @JsonProperty() + private final String name; + + @JsonProperty() + private final String value; + } + +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/AsyncTaskExecutor.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/AsyncTaskExecutor.java new file mode 100644 index 0000000000..b8bb64f537 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/AsyncTaskExecutor.java @@ -0,0 +1,77 @@ +/* + * ============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.inventory.sync; + +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +import jakarta.annotation.PostConstruct; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeoutException; +import java.util.function.Supplier; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +@Slf4j +@Service +public class AsyncTaskExecutor { + + @Value("${ncmp.modules-sync-watchdog.async-executor.parallelism-level:10}") + @Getter + private int asyncTaskParallelismLevel; + private ExecutorService executorService; + private static final int DEFAULT_PARALLELISM_LEVEL = 10; + + /** + * Set up executor service with thread-pool size as per configuration parameter. + * If modules-sync-watchdog.async-executor.parallelism-level not set a default of 10 threads will be applied. + */ + @PostConstruct + public void setupThreadPool() { + executorService = Executors.newWorkStealingPool( + asyncTaskParallelismLevel == 0 ? DEFAULT_PARALLELISM_LEVEL : asyncTaskParallelismLevel); + } + + /** + * Execute supplied task asynchronously. + * + * @param taskSupplier functional method is get() task need to executed asynchronously + * @param timeOutInMillis the task timeout value in milliseconds + */ + public void executeTask(final Supplier taskSupplier, final long timeOutInMillis) { + CompletableFuture.supplyAsync(taskSupplier::get, executorService) + .orTimeout(timeOutInMillis, MILLISECONDS) + .whenCompleteAsync(this::handleTaskCompletion); + } + + private void handleTaskCompletion(final Object response, final Throwable throwable) { + if (throwable != null) { + if (throwable instanceof TimeoutException) { + log.warn("Async task didn't completed within the required time."); + } else { + log.debug("Watchdog async batch failed. caused by : {}", throwable.getMessage()); + } + } + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DataSyncWatchdog.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DataSyncWatchdog.java new file mode 100644 index 0000000000..45f6367841 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DataSyncWatchdog.java @@ -0,0 +1,101 @@ +/* + * ============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.inventory.sync; + +import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME; + +import com.hazelcast.map.IMap; +import java.time.OffsetDateTime; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.onap.cps.api.CpsDataService; +import org.onap.cps.ncmp.api.inventory.models.CompositeState; +import org.onap.cps.ncmp.impl.inventory.DataStoreSyncState; +import org.onap.cps.ncmp.impl.inventory.InventoryPersistence; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; + +@Slf4j +@RequiredArgsConstructor +@Service +public class DataSyncWatchdog { + + private static final boolean DATA_SYNC_IN_PROGRESS = false; + private static final boolean DATA_SYNC_DONE = true; + + private final InventoryPersistence inventoryPersistence; + + private final CpsDataService cpsDataService; + + private final ModuleOperationsUtils moduleOperationsUtils; + + private final IMap dataSyncSemaphores; + + /** + * Execute Cm Handle poll which queries the cm handle state in 'READY' and Operational Datastore Sync State in + * 'UNSYNCHRONIZED'. + */ + @Scheduled(fixedDelayString = "${ncmp.timers.cm-handle-data-sync.sleep-time-ms:30000}") + public void executeUnSynchronizedReadyCmHandlePoll() { + moduleOperationsUtils.getUnsynchronizedReadyCmHandles().forEach(unSynchronizedReadyCmHandle -> { + final String cmHandleId = unSynchronizedReadyCmHandle.getId(); + if (hasPushedIntoSemaphoreMap(cmHandleId)) { + log.debug("Executing data sync on {}", cmHandleId); + final CompositeState compositeState = inventoryPersistence + .getCmHandleState(cmHandleId); + final String resourceData = moduleOperationsUtils.getResourceData(cmHandleId); + if (resourceData == null) { + log.debug("Error retrieving resource data for Cm-Handle: {}", cmHandleId); + } else { + cpsDataService.saveData(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId, + resourceData, OffsetDateTime.now()); + setSyncStateToSynchronized().accept(compositeState); + inventoryPersistence.saveCmHandleState(cmHandleId, compositeState); + updateDataSyncSemaphoreMap(cmHandleId); + } + } else { + log.debug("{} already processed by another instance", cmHandleId); + } + }); + log.debug("No Cm-Handles currently found in READY State and Operational Sync State is UNSYNCHRONIZED"); + } + + private Consumer setSyncStateToSynchronized() { + return compositeState -> { + compositeState.setLastUpdateTimeNow(); + compositeState.getDataStores() + .setOperationalDataStore(CompositeState.Operational.builder() + .dataStoreSyncState(DataStoreSyncState.SYNCHRONIZED) + .lastSyncTime(CompositeState.nowInSyncTimeFormat()).build()); + }; + } + + private void updateDataSyncSemaphoreMap(final String cmHandleId) { + dataSyncSemaphores.replace(cmHandleId, DATA_SYNC_DONE); + } + + private boolean hasPushedIntoSemaphoreMap(final String cmHandleId) { + return dataSyncSemaphores.putIfAbsent(cmHandleId, DATA_SYNC_IN_PROGRESS, + SynchronizationCacheConfig.DATA_SYNC_SEMAPHORE_TTL_SECS, TimeUnit.SECONDS) == null; + } +} 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 new file mode 100644 index 0000000000..15e4653c92 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleOperationsUtils.java @@ -0,0 +1,262 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022-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.fasterxml.jackson.databind.JsonNode; +import java.time.Duration; +import java.time.OffsetDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.UUID; +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.inventory.CmHandleQueryService; +import org.onap.cps.ncmp.impl.inventory.DataStoreSyncState; +import org.onap.cps.ncmp.impl.inventory.models.CmHandleState; +import org.onap.cps.ncmp.impl.inventory.models.LockReasonCategory; +import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; +import org.onap.cps.ncmp.impl.utils.YangDataConverter; +import org.onap.cps.spi.FetchDescendantsOption; +import org.onap.cps.spi.model.DataNode; +import org.onap.cps.utils.JsonObjectMapper; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; + +@Slf4j +@Service +@RequiredArgsConstructor +public class ModuleOperationsUtils { + + private final CmHandleQueryService cmHandleQueryService; + private final DmiDataOperations dmiDataOperations; + private final JsonObjectMapper jsonObjectMapper; + private static final String RETRY_ATTEMPT_KEY = "attempt"; + private static final String MODULE_SET_TAG_KEY = "moduleSetTag"; + public static final String MODULE_SET_TAG_MESSAGE_FORMAT = "Upgrade to ModuleSetTag: %s"; + private static final String LOCK_REASON_DETAILS_MSG_FORMAT = + MODULE_SET_TAG_MESSAGE_FORMAT + " Attempt #%d failed: %s"; + private static final Pattern retryAttemptPattern = Pattern.compile("Attempt #(\\d+) failed:.+"); + private static final Pattern moduleSetTagPattern = Pattern.compile("Upgrade to ModuleSetTag: (\\S+)"); + private static final String CPS_PATH_CM_HANDLES_MODEL_SYNC_FAILED_OR_UPGRADE = """ + //lock-reason[@reason="MODULE_SYNC_FAILED" + or @reason="MODULE_UPGRADE" + or @reason="MODULE_UPGRADE_FAILED"]"""; + + /** + * Query data nodes for cm handles with an "ADVISED" cm handle state. + * + * @return cm handles (data nodes) in ADVISED state (empty list if none found) + */ + public List getAdvisedCmHandles() { + final List advisedCmHandlesAsDataNodes = + cmHandleQueryService.queryCmHandlesByState(CmHandleState.ADVISED); + log.debug("Total number of fetched advised cm handle(s) is (are) {}", advisedCmHandlesAsDataNodes.size()); + return advisedCmHandlesAsDataNodes; + } + + /** + * First query data nodes for cm handles with CM Handle Operational Sync State in "UNSYNCHRONIZED" and + * randomly select a CM Handle and query the data nodes for CM Handle State in "READY". + * + * @return a randomized yang model cm handle list with State in READY and Operation Sync State in "UNSYNCHRONIZED", + * return empty list if not found + */ + public List getUnsynchronizedReadyCmHandles() { + final List unsynchronizedCmHandles = cmHandleQueryService + .queryCmHandlesByOperationalSyncState(DataStoreSyncState.UNSYNCHRONIZED); + + final List yangModelCmHandles = new ArrayList<>(); + for (final DataNode unsynchronizedCmHandle : unsynchronizedCmHandles) { + final String cmHandleId = unsynchronizedCmHandle.getLeaves().get("id").toString(); + if (cmHandleQueryService.cmHandleHasState(cmHandleId, CmHandleState.READY)) { + yangModelCmHandles.addAll(convertCmHandlesDataNodesToYangModelCmHandles( + Collections.singletonList(unsynchronizedCmHandle))); + } + } + Collections.shuffle(yangModelCmHandles); + return yangModelCmHandles; + } + + /** + * Query data nodes for cm handles with an "LOCKED" cm handle state with reason. + * + * @return a random LOCKED yang model cm handle, return null if not found + */ + public List getCmHandlesThatFailedModelSyncOrUpgrade() { + final List lockedCmHandlesAsDataNodeList + = cmHandleQueryService.queryCmHandleAncestorsByCpsPath(CPS_PATH_CM_HANDLES_MODEL_SYNC_FAILED_OR_UPGRADE, + FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS); + return convertCmHandlesDataNodesToYangModelCmHandles(lockedCmHandlesAsDataNodeList); + } + + /** + * Update Composite State attempts counter and set new lock reason and details. + * + * @param lockReasonCategory lock reason category + * @param errorMessage error message + */ + public void updateLockReasonDetailsAndAttempts(final CompositeState compositeState, + final LockReasonCategory lockReasonCategory, + final String errorMessage) { + int attempt = 1; + final Map compositeStateDetails + = getLockedCompositeStateDetails(compositeState.getLockReason()); + if (!compositeStateDetails.isEmpty() && compositeStateDetails.containsKey(RETRY_ATTEMPT_KEY)) { + attempt = 1 + Integer.parseInt(compositeStateDetails.get(RETRY_ATTEMPT_KEY)); + } + final String moduleSetTag = compositeStateDetails.getOrDefault(MODULE_SET_TAG_KEY, ""); + compositeState.setLockReason(CompositeState.LockReason.builder() + .details(String.format(LOCK_REASON_DETAILS_MSG_FORMAT, moduleSetTag, attempt, errorMessage)) + .lockReasonCategory(lockReasonCategory) + .build()); + } + + /** + * Extract lock reason details as key-value pair. + * + * @param compositeStateLockReason lock reason having all the details + * @return a map of lock reason details + */ + public static Map getLockedCompositeStateDetails(final CompositeState.LockReason + compositeStateLockReason) { + if (compositeStateLockReason != null) { + final Map compositeStateDetails = new HashMap<>(2); + final String lockedCompositeStateReasonDetails = compositeStateLockReason.getDetails(); + final Matcher retryAttemptMatcher = retryAttemptPattern.matcher(lockedCompositeStateReasonDetails); + if (retryAttemptMatcher.find()) { + final int attemptsRegexGroupId = 1; + compositeStateDetails.put(RETRY_ATTEMPT_KEY, retryAttemptMatcher.group(attemptsRegexGroupId)); + } + final Matcher moduleSetTagMatcher = moduleSetTagPattern.matcher(lockedCompositeStateReasonDetails); + if (moduleSetTagMatcher.find()) { + final int moduleSetTagRegexGroupId = 1; + compositeStateDetails.put(MODULE_SET_TAG_KEY, moduleSetTagMatcher.group(moduleSetTagRegexGroupId)); + } + return compositeStateDetails; + } + return Collections.emptyMap(); + } + + + /** + * Check if a module sync retry is needed. + * + * @param compositeState the composite state currently in the locked state + * @return if the retry mechanism should be attempted + */ + public boolean needsModuleSyncRetryOrUpgrade(final CompositeState compositeState) { + final OffsetDateTime time = OffsetDateTime.parse(compositeState.getLastUpdateTime(), + DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ")); + final CompositeState.LockReason lockReason = compositeState.getLockReason(); + + final boolean moduleUpgrade = LockReasonCategory.MODULE_UPGRADE == lockReason.getLockReasonCategory(); + if (moduleUpgrade) { + log.info("Locked for module upgrade"); + return true; + } + + final boolean failedDuringModuleSync = LockReasonCategory.MODULE_SYNC_FAILED + == lockReason.getLockReasonCategory(); + final boolean failedDuringModuleUpgrade = LockReasonCategory.MODULE_UPGRADE_FAILED + == lockReason.getLockReasonCategory(); + + if (failedDuringModuleSync || failedDuringModuleUpgrade) { + log.info("Locked for module {} (last attempt failed).", failedDuringModuleSync ? "sync" : "upgrade"); + return isRetryDue(lockReason, time); + } + log.info("Locked for other reason"); + return false; + } + + /** + * Get the Resource Data from Node through DMI Passthrough service. + * + * @param cmHandleId cm handle id + * @return optional string containing the resource data + */ + public String getResourceData(final String cmHandleId) { + final ResponseEntity resourceDataResponseEntity = dmiDataOperations.getAllResourceDataFromDmi( + cmHandleId, UUID.randomUUID().toString()); + if (resourceDataResponseEntity.getStatusCode().is2xxSuccessful()) { + return getFirstResource(resourceDataResponseEntity.getBody()); + } + return null; + } + + /** + * Checks if cm handle state module is in upgrade or upgrade failed. + * + * @param compositeState current lock reason of cm handle + * @return true or false based on lock reason category + */ + public static boolean inUpgradeOrUpgradeFailed(final CompositeState compositeState) { + return compositeState.getLockReason() != null + && (LockReasonCategory.MODULE_UPGRADE.equals(compositeState.getLockReason().getLockReasonCategory()) + || LockReasonCategory.MODULE_UPGRADE_FAILED.equals(compositeState.getLockReason() + .getLockReasonCategory())); + } + + public static String getUpgradedModuleSetTagFromLockReason(final CompositeState.LockReason lockReason) { + return getLockedCompositeStateDetails(lockReason).getOrDefault(MODULE_SET_TAG_KEY, ""); + } + + private String getFirstResource(final Object responseBody) { + final String jsonObjectAsString = jsonObjectMapper.asJsonString(responseBody); + final JsonNode overallJsonNode = jsonObjectMapper.convertToJsonNode(jsonObjectAsString); + final Iterator> overallJsonTreeMap = overallJsonNode.fields(); + final Map.Entry firstElement = overallJsonTreeMap.next(); + return jsonObjectMapper.asJsonString(Map.of(firstElement.getKey(), firstElement.getValue())); + } + + private List convertCmHandlesDataNodesToYangModelCmHandles( + final List cmHandlesAsDataNodeList) { + return cmHandlesAsDataNodeList.stream().map(YangDataConverter::convertCmHandleToYangModel).toList(); + } + + private boolean isRetryDue(final CompositeState.LockReason compositeStateLockReason, final OffsetDateTime time) { + final int timeInMinutesUntilNextAttempt; + final Map compositeStateDetails = getLockedCompositeStateDetails(compositeStateLockReason); + if (compositeStateDetails.isEmpty()) { + timeInMinutesUntilNextAttempt = 1; + log.info("First Attempt: no current attempts found."); + } else { + timeInMinutesUntilNextAttempt = (int) Math.pow(2, Integer.parseInt(compositeStateDetails + .get(RETRY_ATTEMPT_KEY))); + } + final int timeSinceLastAttempt = (int) Duration.between(time, OffsetDateTime.now()).toMinutes(); + if (timeInMinutesUntilNextAttempt >= timeSinceLastAttempt) { + log.info("Time until next attempt is {} minutes: ", timeInMinutesUntilNextAttempt - timeSinceLastAttempt); + return false; + } + log.info("Retry due now"); + return true; + } +} 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 new file mode 100644 index 0000000000..2c8639a4dd --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncService.java @@ -0,0 +1,153 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022-2024 Nordix Foundation + * Modifications Copyright (C) 2024 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.inventory.sync; + +import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DATASPACE_NAME; +import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR; +import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT; +import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME; + +import java.time.OffsetDateTime; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import lombok.AllArgsConstructor; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +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; +import org.onap.cps.ncmp.impl.utils.YangDataConverter; +import org.onap.cps.spi.CascadeDeleteAllowed; +import org.onap.cps.spi.FetchDescendantsOption; +import org.onap.cps.spi.exceptions.SchemaSetNotFoundException; +import org.onap.cps.spi.model.DataNode; +import org.onap.cps.spi.model.ModuleReference; +import org.onap.cps.utils.ContentType; +import org.onap.cps.utils.JsonObjectMapper; +import org.springframework.stereotype.Service; + +@Slf4j +@Service +@RequiredArgsConstructor +public class ModuleSyncService { + + private final DmiModelOperations dmiModelOperations; + private final CpsModuleService cpsModuleService; + private final CmHandleQueryService cmHandleQueryService; + private final CpsDataService cpsDataService; + private final CpsAnchorService cpsAnchorService; + private final JsonObjectMapper jsonObjectMapper; + private static final Map NO_NEW_MODULES = Collections.emptyMap(); + + @AllArgsConstructor + private static final class ModuleDelta { + Collection allModuleReferences; + Map newModuleNameToContentMap; + } + + /** + * This method creates a cm handle and initiates modules sync. + * + * @param yangModelCmHandle the yang model of cm handle. + */ + public void syncAndCreateSchemaSetAndAnchor(final YangModelCmHandle yangModelCmHandle) { + final ModuleDelta moduleDelta = getModuleDelta(yangModelCmHandle, yangModelCmHandle.getModuleSetTag()); + final String cmHandleId = yangModelCmHandle.getId(); + cpsModuleService.createSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId, + moduleDelta.newModuleNameToContentMap, moduleDelta.allModuleReferences); + cpsAnchorService.createAnchor(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId, cmHandleId); + } + + /** + * This method upgrades a cm handle and initiates modules sync. + * + * @param yangModelCmHandle the yang model of cm handle. + */ + public void syncAndUpgradeSchemaSet(final YangModelCmHandle yangModelCmHandle) { + final String upgradedModuleSetTag = ModuleOperationsUtils.getUpgradedModuleSetTagFromLockReason( + yangModelCmHandle.getCompositeState().getLockReason()); + final ModuleDelta moduleDelta = getModuleDelta(yangModelCmHandle, upgradedModuleSetTag); + cpsModuleService.upgradeSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, + yangModelCmHandle.getId(), moduleDelta.newModuleNameToContentMap, moduleDelta.allModuleReferences); + setCmHandleModuleSetTag(yangModelCmHandle, upgradedModuleSetTag); + } + + /** + * Deletes the SchemaSet for schema set id if the SchemaSet Exists. + * + * @param schemaSetId the schema set id to be deleted + */ + public void deleteSchemaSetIfExists(final String schemaSetId) { + try { + cpsModuleService.deleteSchemaSet(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, schemaSetId, + CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED); + log.debug("SchemaSet for {} has been deleted. Ready to be recreated.", schemaSetId); + } catch (final SchemaSetNotFoundException e) { + log.debug("No SchemaSet for {}. Assuming CmHandle has not been previously Module Synced.", schemaSetId); + } + } + + private ModuleDelta getModuleDelta(final YangModelCmHandle yangModelCmHandle, final String targetModuleSetTag) { + final Collection allModuleReferences; + final Map newYangResources; + + final YangModelCmHandle cmHandleWithSameModuleSetTag = getAnyReadyCmHandleByModuleSetTag(targetModuleSetTag); + if (cmHandleWithSameModuleSetTag == null) { + allModuleReferences = dmiModelOperations.getModuleReferences(yangModelCmHandle); + newYangResources = dmiModelOperations.getNewYangResourcesFromDmi(yangModelCmHandle, + cpsModuleService.identifyNewModuleReferences(allModuleReferences)); + } else { + log.info("Found other cm handle having same module set tag: {}", targetModuleSetTag); + allModuleReferences = cpsModuleService.getYangResourcesModuleReferences( + NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleWithSameModuleSetTag.getId()); + newYangResources = NO_NEW_MODULES; + } + return new ModuleDelta(allModuleReferences, newYangResources); + } + + private YangModelCmHandle getAnyReadyCmHandleByModuleSetTag(final String moduleSetTag) { + if (StringUtils.isBlank(moduleSetTag)) { + return null; + } + final String escapedModuleSetTag = moduleSetTag.replace("'", "''"); + final List dataNodes = cmHandleQueryService.queryNcmpRegistryByCpsPath( + NCMP_DMI_REGISTRY_PARENT + "/cm-handles[@module-set-tag='" + escapedModuleSetTag + "']", + FetchDescendantsOption.DIRECT_CHILDREN_ONLY); + return dataNodes.stream().map(YangDataConverter::convertCmHandleToYangModel) + .filter(cmHandle -> cmHandle.getCompositeState().getCmHandleState() == CmHandleState.READY) + .findFirst().orElse(null); + } + + private void setCmHandleModuleSetTag(final YangModelCmHandle yangModelCmHandle, final String newModuleSetTag) { + final String jsonForUpdate = jsonObjectMapper.asJsonString(Map.of( + "cm-handles", Map.of("id", yangModelCmHandle.getId(), "module-set-tag", newModuleSetTag))); + cpsDataService.updateNodeLeaves(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, NCMP_DMI_REGISTRY_PARENT, + jsonForUpdate, OffsetDateTime.now(), ContentType.JSON); + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncTasks.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncTasks.java new file mode 100644 index 0000000000..80c290cb54 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncTasks.java @@ -0,0 +1,131 @@ +/* + * ============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.inventory.sync; + +import com.hazelcast.map.IMap; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.atomic.AtomicInteger; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.onap.cps.ncmp.api.impl.events.lcm.LcmEventsCmHandleStateHandler; +import org.onap.cps.ncmp.api.inventory.models.CompositeState; +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.LockReasonCategory; +import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; +import org.onap.cps.ncmp.impl.utils.YangDataConverter; +import org.onap.cps.spi.model.DataNode; +import org.springframework.stereotype.Component; + +@RequiredArgsConstructor +@Component +@Slf4j +public class ModuleSyncTasks { + private final InventoryPersistence inventoryPersistence; + private final ModuleOperationsUtils moduleOperationsUtils; + private final ModuleSyncService moduleSyncService; + private final LcmEventsCmHandleStateHandler lcmEventsCmHandleStateHandler; + private final IMap moduleSyncStartedOnCmHandles; + + /** + * Perform module sync on a batch of cm handles. + * + * @param cmHandlesAsDataNodes a batch of Data nodes representing cm handles to perform module sync on + * @param batchCounter the number of batches currently being processed, will be decreased when + * task is finished or fails + * @return completed future to handle post-processing + */ + public CompletableFuture performModuleSync(final Collection cmHandlesAsDataNodes, + final AtomicInteger batchCounter) { + try { + final Map cmHandelStatePerCmHandle + = new HashMap<>(cmHandlesAsDataNodes.size()); + for (final DataNode cmHandleAsDataNode : cmHandlesAsDataNodes) { + final String cmHandleId = String.valueOf(cmHandleAsDataNode.getLeaves().get("id")); + final YangModelCmHandle yangModelCmHandle = + YangDataConverter.convertCmHandleToYangModel(cmHandleAsDataNode); + final CompositeState compositeState = inventoryPersistence.getCmHandleState(cmHandleId); + final boolean inUpgrade = ModuleOperationsUtils.inUpgradeOrUpgradeFailed(compositeState); + try { + if (inUpgrade) { + moduleSyncService.syncAndUpgradeSchemaSet(yangModelCmHandle); + } else { + moduleSyncService.deleteSchemaSetIfExists(cmHandleId); + moduleSyncService.syncAndCreateSchemaSetAndAnchor(yangModelCmHandle); + } + yangModelCmHandle.getCompositeState().setLockReason(null); + cmHandelStatePerCmHandle.put(yangModelCmHandle, CmHandleState.READY); + } catch (final Exception e) { + log.warn("Processing of {} module failed due to reason {}.", cmHandleId, e.getMessage()); + final LockReasonCategory lockReasonCategory = inUpgrade ? LockReasonCategory.MODULE_UPGRADE_FAILED + : LockReasonCategory.MODULE_SYNC_FAILED; + moduleOperationsUtils.updateLockReasonDetailsAndAttempts(compositeState, + lockReasonCategory, e.getMessage()); + setCmHandleStateLocked(yangModelCmHandle, compositeState.getLockReason()); + cmHandelStatePerCmHandle.put(yangModelCmHandle, CmHandleState.LOCKED); + } + log.info("{} is now in {} state", cmHandleId, cmHandelStatePerCmHandle.get(yangModelCmHandle).name()); + } + lcmEventsCmHandleStateHandler.updateCmHandleStateBatch(cmHandelStatePerCmHandle); + } finally { + batchCounter.getAndDecrement(); + log.info("Processing module sync batch finished. {} batch(es) active.", batchCounter.get()); + } + return CompletableFuture.completedFuture(null); + } + + /** + * Reset state to "ADVISED" for any previously failed cm handles. + * + * @param failedCmHandles previously failed (locked) cm handles + */ + public void resetFailedCmHandles(final List failedCmHandles) { + final Map cmHandleStatePerCmHandle = new HashMap<>(failedCmHandles.size()); + for (final YangModelCmHandle failedCmHandle : failedCmHandles) { + final CompositeState compositeState = failedCmHandle.getCompositeState(); + final boolean isReadyForRetry = moduleOperationsUtils.needsModuleSyncRetryOrUpgrade(compositeState); + log.info("Retry for cmHandleId : {} is {}", failedCmHandle.getId(), isReadyForRetry); + if (isReadyForRetry) { + final String resetCmHandleId = failedCmHandle.getId(); + log.debug("Reset cm handle {} state to ADVISED to be re-attempted by module-sync watchdog", + resetCmHandleId); + cmHandleStatePerCmHandle.put(failedCmHandle, CmHandleState.ADVISED); + removeResetCmHandleFromModuleSyncMap(resetCmHandleId); + } + } + lcmEventsCmHandleStateHandler.updateCmHandleStateBatch(cmHandleStatePerCmHandle); + } + + private void setCmHandleStateLocked(final YangModelCmHandle advisedCmHandle, + final CompositeState.LockReason lockReason) { + advisedCmHandle.getCompositeState().setLockReason(lockReason); + } + + private void removeResetCmHandleFromModuleSyncMap(final String resetCmHandleId) { + if (moduleSyncStartedOnCmHandles.remove(resetCmHandleId) != null) { + log.info("{} removed from in progress map", resetCmHandleId); + } + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncWatchdog.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncWatchdog.java new file mode 100644 index 0000000000..b4dde18da0 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncWatchdog.java @@ -0,0 +1,138 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022-2023 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.hazelcast.map.IMap; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; +import org.onap.cps.spi.model.DataNode; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; + +@Slf4j +@RequiredArgsConstructor +@Service +public class ModuleSyncWatchdog { + + private final ModuleOperationsUtils moduleOperationsUtils; + private final BlockingQueue moduleSyncWorkQueue; + private final IMap moduleSyncStartedOnCmHandles; + private final ModuleSyncTasks moduleSyncTasks; + private final AsyncTaskExecutor asyncTaskExecutor; + private static final int MODULE_SYNC_BATCH_SIZE = 100; + private static final long PREVENT_CPU_BURN_WAIT_TIME_MILLIS = 10; + private static final String VALUE_FOR_HAZELCAST_IN_PROGRESS_MAP = "Started"; + private static final long ASYNC_TASK_TIMEOUT_IN_MILLISECONDS = TimeUnit.MINUTES.toMillis(5); + @Getter + private AtomicInteger batchCounter = new AtomicInteger(1); + + /** + * Check DB for any cm handles in 'ADVISED' state. + * Queue and create batches to process them asynchronously. + * This method will only finish when there are no more 'ADVISED' cm handles in the DB. + * This method wil be triggered on a configurable interval + */ + @Scheduled(fixedDelayString = "${ncmp.timers.advised-modules-sync.sleep-time-ms:5000}") + public void moduleSyncAdvisedCmHandles() { + log.info("Processing module sync watchdog waking up."); + populateWorkQueueIfNeeded(); + while (!moduleSyncWorkQueue.isEmpty()) { + if (batchCounter.get() <= asyncTaskExecutor.getAsyncTaskParallelismLevel()) { + final Collection nextBatch = prepareNextBatch(); + log.info("Processing module sync batch of {}. {} batch(es) active.", + nextBatch.size(), batchCounter.get()); + if (!nextBatch.isEmpty()) { + asyncTaskExecutor.executeTask(() -> + moduleSyncTasks.performModuleSync(nextBatch, batchCounter), + ASYNC_TASK_TIMEOUT_IN_MILLISECONDS); + batchCounter.getAndIncrement(); + } + } else { + preventBusyWait(); + } + } + } + + /** + * Find any failed (locked) cm handles and change state back to 'ADVISED'. + */ + @Scheduled(fixedDelayString = "${ncmp.timers.locked-modules-sync.sleep-time-ms:300000}") + public void resetPreviouslyFailedCmHandles() { + log.info("Processing module sync retry-watchdog waking up."); + final List failedCmHandles + = moduleOperationsUtils.getCmHandlesThatFailedModelSyncOrUpgrade(); + log.info("Retrying {} cmHandles", failedCmHandles.size()); + moduleSyncTasks.resetFailedCmHandles(failedCmHandles); + } + + private void preventBusyWait() { + try { + log.info("Busy waiting now"); + TimeUnit.MILLISECONDS.sleep(PREVENT_CPU_BURN_WAIT_TIME_MILLIS); + } catch (final InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + + private void populateWorkQueueIfNeeded() { + if (moduleSyncWorkQueue.isEmpty()) { + final List advisedCmHandles = moduleOperationsUtils.getAdvisedCmHandles(); + log.info("Processing module sync fetched {} advised cm handles from DB", advisedCmHandles.size()); + for (final DataNode advisedCmHandle : advisedCmHandles) { + if (!moduleSyncWorkQueue.offer(advisedCmHandle)) { + log.warn("Unable to add cm handle {} to the work queue", advisedCmHandle.getLeaves().get("id")); + } + } + log.info("Work Queue Size : {}", moduleSyncWorkQueue.size()); + } + } + + private Collection prepareNextBatch() { + final Collection nextBatchCandidates = new HashSet<>(MODULE_SYNC_BATCH_SIZE); + final Collection nextBatch = new HashSet<>(MODULE_SYNC_BATCH_SIZE); + moduleSyncWorkQueue.drainTo(nextBatchCandidates, MODULE_SYNC_BATCH_SIZE); + log.info("nextBatchCandidates size : {}", nextBatchCandidates.size()); + for (final DataNode batchCandidate : nextBatchCandidates) { + final String cmHandleId = String.valueOf(batchCandidate.getLeaves().get("id")); + final boolean alreadyAddedToInProgressMap = VALUE_FOR_HAZELCAST_IN_PROGRESS_MAP.equals( + moduleSyncStartedOnCmHandles.putIfAbsent(cmHandleId, VALUE_FOR_HAZELCAST_IN_PROGRESS_MAP, + SynchronizationCacheConfig.MODULE_SYNC_STARTED_TTL_SECS, TimeUnit.SECONDS)); + if (alreadyAddedToInProgressMap) { + log.info("module sync for {} already in progress by other instance", cmHandleId); + } else { + log.info("Adding cmHandle : {} to current batch", cmHandleId); + nextBatch.add(batchCandidate); + } + } + log.debug("nextBatch size : {}", nextBatch.size()); + return nextBatch; + } + +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/SynchronizationCacheConfig.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/SynchronizationCacheConfig.java new file mode 100644 index 0000000000..76b33cc8d9 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/SynchronizationCacheConfig.java @@ -0,0 +1,77 @@ +/* + * ============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.inventory.sync; + +import com.hazelcast.config.MapConfig; +import com.hazelcast.config.QueueConfig; +import com.hazelcast.map.IMap; +import java.util.concurrent.BlockingQueue; +import lombok.extern.slf4j.Slf4j; +import org.onap.cps.cache.HazelcastCacheConfig; +import org.onap.cps.spi.model.DataNode; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * Core infrastructure of the hazelcast distributed caches for Module Sync and Data Sync use cases. + */ +@Slf4j +@Configuration +public class SynchronizationCacheConfig extends HazelcastCacheConfig { + + public static final int MODULE_SYNC_STARTED_TTL_SECS = 600; + public static final int DATA_SYNC_SEMAPHORE_TTL_SECS = 1800; + + private static final QueueConfig commonQueueConfig = createQueueConfig("defaultQueueConfig"); + private static final MapConfig moduleSyncStartedConfig = createMapConfig("moduleSyncStartedConfig"); + private static final MapConfig dataSyncSemaphoresConfig = createMapConfig("dataSyncSemaphoresConfig"); + + /** + * Module Sync Distributed Queue Instance. + * + * @return queue of cm handles (data nodes) that need module sync + */ + @Bean + public BlockingQueue moduleSyncWorkQueue() { + return createHazelcastInstance("moduleSyncWorkQueue", commonQueueConfig).getQueue("moduleSyncWorkQueue"); + } + + /** + * Module Sync started (and maybe finished) on cm handles (ids). + * + * @return Map of cm handles (ids) and objects (not used really) for which module sync has started or been completed + */ + @Bean + public IMap moduleSyncStartedOnCmHandles() { + return createHazelcastInstance("moduleSyncStartedOnCmHandles", moduleSyncStartedConfig).getMap( + "moduleSyncStartedOnCmHandles"); + } + + /** + * Data Sync Distributed Map Instance. + * + * @return configured map of data sync semaphores + */ + @Bean + public IMap dataSyncSemaphores() { + return createHazelcastInstance("dataSyncSemaphores", dataSyncSemaphoresConfig).getMap("dataSyncSemaphores"); + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/WatchdogSchedulingConfigurer.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/WatchdogSchedulingConfigurer.java new file mode 100644 index 0000000000..203c5a1a20 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/WatchdogSchedulingConfigurer.java @@ -0,0 +1,56 @@ +/* + * ============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.inventory.sync; + +import java.util.concurrent.ThreadPoolExecutor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +@Configuration +@EnableScheduling +public class WatchdogSchedulingConfigurer implements SchedulingConfigurer { + + @Override + public void configureTasks(final ScheduledTaskRegistrar scheduledTaskRegistrar) { + scheduledTaskRegistrar.setTaskScheduler(taskScheduler()); + } + + /** + * Implementation of Spring's {@link TaskScheduler} interface, wrapping + * a native {@link org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler} for watchdogs. + */ + @Bean + public TaskScheduler taskScheduler() { + final ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler(); + taskScheduler.setPoolSize(10); + taskScheduler.setThreadNamePrefix("watchdog-th-"); + taskScheduler.setAwaitTerminationSeconds(60); + taskScheduler.setWaitForTasksToCompleteOnShutdown(true); + taskScheduler.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy()); + taskScheduler.initialize(); + return taskScheduler; + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/AlternateIdMatcher.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/AlternateIdMatcher.java new file mode 100644 index 0000000000..832e576d55 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/AlternateIdMatcher.java @@ -0,0 +1,63 @@ +/* + * ============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.utils; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.onap.cps.ncmp.exceptions.NoAlternateIdMatchFoundException; +import org.onap.cps.ncmp.impl.inventory.InventoryPersistence; +import org.onap.cps.spi.exceptions.DataNodeNotFoundException; +import org.onap.cps.spi.model.DataNode; +import org.springframework.stereotype.Service; + +@Slf4j +@Service +@RequiredArgsConstructor +public class AlternateIdMatcher { + + private final InventoryPersistence inventoryPersistence; + + /** + * Get data node that matches longest alternate id by removing elements (as defined by the separator string) + * from right to left. + * + * @param alternateId alternate ID + * @param separator a string that separates each element from the next. + * @return data node + */ + public DataNode getCmHandleDataNodeByLongestMatchingAlternateId(final String alternateId, final String separator) { + String bestMatch = alternateId; + while (StringUtils.isNotEmpty(bestMatch)) { + try { + return inventoryPersistence.getCmHandleDataNodeByAlternateId(bestMatch); + } catch (final DataNodeNotFoundException ignored) { + bestMatch = getParentPath(bestMatch, separator); + } + } + throw new NoAlternateIdMatchFoundException(alternateId); + } + + private String getParentPath(final String path, final String separator) { + final int lastSeparatorIndex = path.lastIndexOf(separator); + return lastSeparatorIndex < 0 ? "" : path.substring(0, lastSeparatorIndex); + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/YangDataConverter.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/YangDataConverter.java new file mode 100644 index 0000000000..bde13684af --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/YangDataConverter.java @@ -0,0 +1,159 @@ +/* + * ============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.utils; + +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.onap.cps.ncmp.api.inventory.models.CompositeState; +import org.onap.cps.ncmp.api.inventory.models.CompositeStateBuilder; +import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle; +import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; +import org.onap.cps.spi.model.DataNode; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +@Slf4j +public class YangDataConverter { + + private static final Pattern cmHandleIdInXpathPattern = Pattern.compile("\\[@id='(.*?)']"); + + /** + * This method convert yang model cm handle to ncmp service cm handle. + * @param yangModelCmHandle the yang model of the cm handle + * @return ncmp service cm handle + */ + public static NcmpServiceCmHandle convertYangModelCmHandleToNcmpServiceCmHandle( + final YangModelCmHandle yangModelCmHandle) { + final NcmpServiceCmHandle ncmpServiceCmHandle = new NcmpServiceCmHandle(); + final List dmiProperties = yangModelCmHandle.getDmiProperties(); + final List publicProperties = yangModelCmHandle.getPublicProperties(); + ncmpServiceCmHandle.setCmHandleId(yangModelCmHandle.getId()); + ncmpServiceCmHandle.setCompositeState(yangModelCmHandle.getCompositeState()); + ncmpServiceCmHandle.setModuleSetTag(yangModelCmHandle.getModuleSetTag()); + ncmpServiceCmHandle.setAlternateId(yangModelCmHandle.getAlternateId()); + ncmpServiceCmHandle.setDataProducerIdentifier(yangModelCmHandle.getDataProducerIdentifier()); + setDmiProperties(dmiProperties, ncmpServiceCmHandle); + setPublicProperties(publicProperties, ncmpServiceCmHandle); + return ncmpServiceCmHandle; + } + + /** + * This method convert yang model cm handle properties to simple map. + * @param properties the yang model cm handle properties + * @param propertiesMap the String, String map for the results + */ + public static void asPropertiesMap(final List properties, + final Map propertiesMap) { + for (final YangModelCmHandle.Property property : properties) { + propertiesMap.put(property.getName(), property.getValue()); + } + } + + /** + * This method convert cm handle data node to yang model cm handle. + * @param cmHandleDataNode the datanode of the cm handle + * @return yang model cm handle + */ + public static YangModelCmHandle convertCmHandleToYangModel(final DataNode cmHandleDataNode) { + final NcmpServiceCmHandle ncmpServiceCmHandle = new NcmpServiceCmHandle(); + final String cmHandleId = cmHandleDataNode.getLeaves().get("id").toString(); + ncmpServiceCmHandle.setCmHandleId(cmHandleId); + populateCmHandleDetails(cmHandleDataNode, ncmpServiceCmHandle); + return YangModelCmHandle.toYangModelCmHandle( + (String) cmHandleDataNode.getLeaves().get("dmi-service-name"), + (String) cmHandleDataNode.getLeaves().get("dmi-data-service-name"), + (String) cmHandleDataNode.getLeaves().get("dmi-model-service-name"), + ncmpServiceCmHandle, + (String) cmHandleDataNode.getLeaves().get("module-set-tag"), + (String) cmHandleDataNode.getLeaves().get("alternate-id"), + (String) cmHandleDataNode.getLeaves().get("data-producer-identifier") + ); + } + + /** + * This method convert cm handle data nodes to yang model cm handles. + * @param cmHandleDataNodes the datanode of the cm handle + * @return yang model cm handles + */ + public static Collection convertDataNodesToYangModelCmHandles( + final Collection cmHandleDataNodes) { + return cmHandleDataNodes.stream().map(YangDataConverter::convertCmHandleToYangModel) + .collect(Collectors.toList()); + } + + /** + * This method extract cm handle id from xpath of data node. + * @param xpath for data node of the cm handle + * @return cm handle Id + */ + public static String extractCmHandleIdFromXpath(final String xpath) { + final Matcher matcher = cmHandleIdInXpathPattern.matcher(xpath); + matcher.find(); + return matcher.group(1); + } + + + private static void populateCmHandleDetails(final DataNode cmHandleDataNode, + final NcmpServiceCmHandle ncmpServiceCmHandle) { + final Map dmiProperties = new LinkedHashMap<>(); + final Map publicProperties = new LinkedHashMap<>(); + final CompositeStateBuilder compositeStateBuilder = new CompositeStateBuilder(); + CompositeState compositeState = compositeStateBuilder.build(); + for (final DataNode childDataNode: cmHandleDataNode.getChildDataNodes()) { + if (childDataNode.getXpath().contains("/additional-properties[@name=")) { + addProperty(childDataNode, dmiProperties); + } else if (childDataNode.getXpath().contains("/public-properties[@name=")) { + addProperty(childDataNode, publicProperties); + } else if (childDataNode.getXpath().endsWith("/state")) { + compositeState = compositeStateBuilder.fromDataNode(childDataNode).build(); + } + } + ncmpServiceCmHandle.setDmiProperties(dmiProperties); + ncmpServiceCmHandle.setPublicProperties(publicProperties); + ncmpServiceCmHandle.setCompositeState(compositeState); + } + + private static void addProperty(final DataNode propertyDataNode, final Map propertiesAsMap) { + propertiesAsMap.put(String.valueOf(propertyDataNode.getLeaves().get("name")), + String.valueOf(propertyDataNode.getLeaves().get("value"))); + } + + private static void setDmiProperties(final List dmiProperties, + final NcmpServiceCmHandle ncmpServiceCmHandle) { + final Map dmiPropertiesMap = new LinkedHashMap<>(dmiProperties.size()); + asPropertiesMap(dmiProperties, dmiPropertiesMap); + ncmpServiceCmHandle.setDmiProperties(dmiPropertiesMap); + } + + private static void setPublicProperties(final List publicProperties, + final NcmpServiceCmHandle ncmpServiceCmHandle) { + final Map publicPropertiesMap = new LinkedHashMap<>(); + asPropertiesMap(publicProperties, publicPropertiesMap); + ncmpServiceCmHandle.setPublicProperties(publicPropertiesMap); + } +} 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 a0b7bd5826..130defb306 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 @@ -20,7 +20,7 @@ package org.onap.cps.ncmp.init; -import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME; +import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DATASPACE_NAME; import static org.onap.cps.utils.ContentType.JSON; import java.time.OffsetDateTime; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/InventoryModelLoader.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/InventoryModelLoader.java index 7c25953f0d..76d12f290c 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/InventoryModelLoader.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/InventoryModelLoader.java @@ -20,9 +20,9 @@ package org.onap.cps.ncmp.init; -import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME; -import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR; -import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME; +import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DATASPACE_NAME; +import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR; +import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME; import lombok.extern.slf4j.Slf4j; import org.onap.cps.api.CpsAnchorService; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/AlternateIdMatcher.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/AlternateIdMatcher.java deleted file mode 100644 index 3fad684437..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/AlternateIdMatcher.java +++ /dev/null @@ -1,63 +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.utils; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence; -import org.onap.cps.ncmp.exceptions.NoAlternateIdMatchFoundException; -import org.onap.cps.spi.exceptions.DataNodeNotFoundException; -import org.onap.cps.spi.model.DataNode; -import org.springframework.stereotype.Service; - -@Slf4j -@Service -@RequiredArgsConstructor -public class AlternateIdMatcher { - - private final InventoryPersistence inventoryPersistence; - - /** - * Get data node that matches longest alternate id by removing elements (as defined by the separator string) - * from right to left. - * - * @param alternateId alternate ID - * @param separator a string that separates each element from the next. - * @return data node - */ - public DataNode getCmHandleDataNodeByLongestMatchingAlternateId(final String alternateId, final String separator) { - String bestMatch = alternateId; - while (StringUtils.isNotEmpty(bestMatch)) { - try { - return inventoryPersistence.getCmHandleDataNodeByAlternateId(bestMatch); - } catch (final DataNodeNotFoundException ignored) { - bestMatch = getParentPath(bestMatch, separator); - } - } - throw new NoAlternateIdMatchFoundException(alternateId); - } - - private String getParentPath(final String path, final String separator) { - final int lastSeparatorIndex = path.lastIndexOf(separator); - return lastSeparatorIndex < 0 ? "" : path.substring(0, lastSeparatorIndex); - } -} -- cgit 1.2.3-korg