summaryrefslogtreecommitdiffstats
path: root/cps-ncmp-service
diff options
context:
space:
mode:
Diffstat (limited to 'cps-ncmp-service')
-rwxr-xr-xcps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java186
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandler.java25
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/embeddedcache/AlternateIdCacheConfig.java59
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/embeddedcache/ModuleSetTagCacheConfig.java46
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/InventoryPersistence.java12
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/InventoryPersistenceImpl.java39
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleOperationsUtils.java21
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncService.java129
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncTasks.java2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/AlternateIdChecker.java142
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/CmHandleIdMapper.java95
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/YangDataConverter.java1
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandle.java8
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy38
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy34
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandlerSpec.groovy44
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/embeddedcache/AlternateIdCacheConfigSpec.groovy59
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/embeddedcache/ModuleSetTagCacheConfigSpec.groovy76
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/InventoryPersistenceImplSpec.groovy49
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleOperationsUtilsSpec.groovy2
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncServiceSpec.groovy16
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/AlternateIdCheckerSpec.groovy97
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/CmHandleIdMapperSpec.groovy126
23 files changed, 553 insertions, 753 deletions
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java
index 05b83b98e..1f2748b4a 100755
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java
@@ -35,11 +35,9 @@ import static org.onap.cps.ncmp.api.impl.utils.RestQueryParametersValidator.vali
import com.google.common.collect.Lists;
import com.hazelcast.map.IMap;
-import java.text.MessageFormat;
import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.EnumMap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -50,7 +48,6 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.onap.cps.api.CpsDataService;
-import org.onap.cps.ncmp.api.NcmpResponseStatus;
import org.onap.cps.ncmp.api.NetworkCmProxyCmHandleQueryService;
import org.onap.cps.ncmp.api.NetworkCmProxyDataService;
import org.onap.cps.ncmp.api.impl.events.lcm.LcmEventsCmHandleStateHandler;
@@ -66,7 +63,7 @@ import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations;
import org.onap.cps.ncmp.api.impl.operations.OperationType;
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.CmHandleIdMapper;
+import org.onap.cps.ncmp.api.impl.utils.AlternateIdChecker;
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;
@@ -106,37 +103,24 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
private final IMap<String, Object> moduleSyncStartedOnCmHandles;
private final Map<String, TrustLevel> trustLevelPerDmiPlugin;
private final TrustLevelManager trustLevelManager;
- private final CmHandleIdMapper cmHandleIdMapper;
- private final Map<String, Collection<ModuleReference>> moduleSetTagCache;
+ private final AlternateIdChecker alternateIdChecker;
@Override
public DmiPluginRegistrationResponse updateDmiRegistrationAndSyncModule(
final DmiPluginRegistration dmiPluginRegistration) {
- cacheAlternateIds(dmiPluginRegistration.getCreatedCmHandles());
+
dmiPluginRegistration.validateDmiPluginRegistration();
final DmiPluginRegistrationResponse dmiPluginRegistrationResponse = new DmiPluginRegistrationResponse();
setTrustLevelPerDmiPlugin(dmiPluginRegistration);
- if (!dmiPluginRegistration.getRemovedCmHandles().isEmpty()) {
- dmiPluginRegistrationResponse.setRemovedCmHandles(
- parseAndProcessDeletedCmHandlesInRegistration(dmiPluginRegistration.getRemovedCmHandles()));
- }
+ processRemovedCmHandles(dmiPluginRegistration, dmiPluginRegistrationResponse);
- if (!dmiPluginRegistration.getCreatedCmHandles().isEmpty()) {
- dmiPluginRegistrationResponse.setCreatedCmHandles(
- parseAndProcessCreatedCmHandlesInRegistration(dmiPluginRegistration));
- }
- if (!dmiPluginRegistration.getUpdatedCmHandles().isEmpty()) {
- dmiPluginRegistrationResponse.setUpdatedCmHandles(
- networkCmProxyDataServicePropertyHandler
- .updateCmHandleProperties(dmiPluginRegistration.getUpdatedCmHandles()));
- }
- if (dmiPluginRegistration.getUpgradedCmHandles() != null
- && !dmiPluginRegistration.getUpgradedCmHandles().getCmHandles().isEmpty()) {
- dmiPluginRegistrationResponse.setUpgradedCmHandles(
- parseAndProcessUpgradedCmHandlesInRegistration(dmiPluginRegistration));
- }
+ processCreatedCmHandles(dmiPluginRegistration, dmiPluginRegistrationResponse);
+
+ processUpdatedCmHandles(dmiPluginRegistration, dmiPluginRegistrationResponse);
+
+ processUpgradedCmHandles(dmiPluginRegistration, dmiPluginRegistrationResponse);
return dmiPluginRegistrationResponse;
}
@@ -329,21 +313,24 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
* @return cm-handle registration response for create cm-handle requests.
*/
public List<CmHandleRegistrationResponse> parseAndProcessCreatedCmHandlesInRegistration(
- final DmiPluginRegistration dmiPluginRegistration) {
+ final DmiPluginRegistration dmiPluginRegistration, final Collection<String> acceptedCmHandleIds) {
final List<NcmpServiceCmHandle> cmHandlesToBeCreated = dmiPluginRegistration.getCreatedCmHandles();
final Map<String, TrustLevel> initialTrustLevelPerCmHandleId = new HashMap<>(cmHandlesToBeCreated.size());
final List<YangModelCmHandle> yangModelCmHandles = new ArrayList<>(cmHandlesToBeCreated.size());
cmHandlesToBeCreated
.forEach(cmHandle -> {
- final YangModelCmHandle yangModelCmHandle = YangModelCmHandle.toYangModelCmHandle(
- dmiPluginRegistration.getDmiPlugin(),
- dmiPluginRegistration.getDmiDataPlugin(),
- dmiPluginRegistration.getDmiModelPlugin(),
- cmHandle,
- cmHandle.getModuleSetTag(),
- cmHandle.getAlternateId());
- yangModelCmHandles.add(yangModelCmHandle);
- initialTrustLevelPerCmHandleId.put(cmHandle.getCmHandleId(), cmHandle.getRegistrationTrustLevel());
+ if (acceptedCmHandleIds.contains(cmHandle.getCmHandleId())) {
+ final YangModelCmHandle yangModelCmHandle = YangModelCmHandle.toYangModelCmHandle(
+ dmiPluginRegistration.getDmiPlugin(),
+ dmiPluginRegistration.getDmiDataPlugin(),
+ dmiPluginRegistration.getDmiModelPlugin(),
+ cmHandle,
+ cmHandle.getModuleSetTag(),
+ cmHandle.getAlternateId());
+ yangModelCmHandles.add(yangModelCmHandle);
+ initialTrustLevelPerCmHandleId.put(cmHandle.getCmHandleId(),
+ cmHandle.getRegistrationTrustLevel());
+ }
});
return registerNewCmHandles(yangModelCmHandles, initialTrustLevelPerCmHandleId);
}
@@ -354,16 +341,12 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
new ArrayList<>(tobeRemovedCmHandles.size());
final Collection<YangModelCmHandle> yangModelCmHandles =
inventoryPersistence.getYangModelCmHandles(tobeRemovedCmHandles);
- final Set<String> moduleSetTags = yangModelCmHandles.stream().map(YangModelCmHandle::getModuleSetTag)
- .collect(Collectors.toSet());
updateCmHandleStateBatch(yangModelCmHandles, CmHandleState.DELETING);
final Set<String> notDeletedCmHandles = new HashSet<>();
for (final List<String> tobeRemovedCmHandleBatch : Lists.partition(tobeRemovedCmHandles, DELETE_BATCH_SIZE)) {
try {
batchDeleteCmHandlesFromDbAndModuleSyncMap(tobeRemovedCmHandleBatch);
- moduleSetTags.forEach(moduleSetTagCache::remove);
- log.debug("Removed module set tags: {}", moduleSetTags);
tobeRemovedCmHandleBatch.forEach(cmHandleId ->
cmHandleRegistrationResponses.add(CmHandleRegistrationResponse.createSuccessResponse(cmHandleId)));
@@ -382,68 +365,100 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
yangModelCmHandles.removeIf(yangModelCmHandle -> notDeletedCmHandles.contains(yangModelCmHandle.getId()));
updateCmHandleStateBatch(yangModelCmHandles, CmHandleState.DELETED);
- removeEntriesFromAlternateIdCache(yangModelCmHandles);
return cmHandleRegistrationResponses;
}
- private void removeEntriesFromAlternateIdCache(final Collection<YangModelCmHandle> yangModelCmHandles) {
- for (final YangModelCmHandle yangModelCmHandle : yangModelCmHandles) {
- cmHandleIdMapper.removeMapping(yangModelCmHandle.getId());
+ private void processRemovedCmHandles(final DmiPluginRegistration dmiPluginRegistration,
+ final DmiPluginRegistrationResponse dmiPluginRegistrationResponse) {
+ if (!dmiPluginRegistration.getRemovedCmHandles().isEmpty()) {
+ dmiPluginRegistrationResponse.setRemovedCmHandles(
+ parseAndProcessDeletedCmHandlesInRegistration(dmiPluginRegistration.getRemovedCmHandles()));
+ }
+ }
+
+ private void processCreatedCmHandles(final DmiPluginRegistration dmiPluginRegistration,
+ final DmiPluginRegistrationResponse dmiPluginRegistrationResponse) {
+ final Collection<String> acceptedCmHandleIds = alternateIdChecker
+ .getIdsOfCmHandlesWithAcceptableAlternateId(dmiPluginRegistration.getCreatedCmHandles());
+ if (!acceptedCmHandleIds.isEmpty()) {
+ dmiPluginRegistrationResponse.setCreatedCmHandles(
+ parseAndProcessCreatedCmHandlesInRegistration(dmiPluginRegistration, acceptedCmHandleIds));
+ }
+ }
+
+ private void processUpdatedCmHandles(final DmiPluginRegistration dmiPluginRegistration,
+ final DmiPluginRegistrationResponse dmiPluginRegistrationResponse) {
+ if (!dmiPluginRegistration.getUpdatedCmHandles().isEmpty()) {
+ dmiPluginRegistrationResponse.setUpdatedCmHandles(
+ networkCmProxyDataServicePropertyHandler
+ .updateCmHandleProperties(dmiPluginRegistration.getUpdatedCmHandles()));
}
}
+ private void processUpgradedCmHandles(final DmiPluginRegistration dmiPluginRegistration,
+ final DmiPluginRegistrationResponse dmiPluginRegistrationResponse) {
+ if (dmiPluginRegistration.getUpgradedCmHandles() != null
+ && !dmiPluginRegistration.getUpgradedCmHandles().getCmHandles().isEmpty()) {
+ dmiPluginRegistrationResponse.setUpgradedCmHandles(
+ parseAndProcessUpgradedCmHandlesInRegistration(dmiPluginRegistration));
+ }
+ }
+
+
protected List<CmHandleRegistrationResponse> parseAndProcessUpgradedCmHandlesInRegistration(
final DmiPluginRegistration dmiPluginRegistration) {
final List<String> upgradedCmHandleIds = dmiPluginRegistration.getUpgradedCmHandles().getCmHandles();
-
+ final String upgradedModuleSetTag = dmiPluginRegistration.getUpgradedCmHandles().getModuleSetTag();
final Map<YangModelCmHandle, CmHandleState> acceptedCmHandleStatePerCmHandle
= new HashMap<>(upgradedCmHandleIds.size());
+ final List<CmHandleRegistrationResponse> cmHandleUpgradeResponses = new ArrayList<>(upgradedCmHandleIds.size());
- final Map<NcmpResponseStatus, List<String>> failedCmHandlesPerResponseStatus
- = new EnumMap<>(NcmpResponseStatus.class);
- final List<String> nonExistingCmHandleIds = new ArrayList<>();
- final List<String> nonReadyCmHandleIds = new ArrayList<>();
- final List<String> invalidCmHandleIds = new ArrayList<>();
-
- upgradedCmHandleIds.forEach(cmHandleId -> {
+ for (final String cmHandleId : upgradedCmHandleIds) {
try {
- if (cmHandleQueries.cmHandleHasState(cmHandleId, CmHandleState.READY)) {
- final YangModelCmHandle yangModelCmHandleWithUpgradeDetails
- = createYangModelCmHandle(dmiPluginRegistration, cmHandleId);
- acceptedCmHandleStatePerCmHandle.put(yangModelCmHandleWithUpgradeDetails, CmHandleState.LOCKED);
+ 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 {
- nonReadyCmHandleIds.add(cmHandleId);
+ 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());
- nonExistingCmHandleIds.add(cmHandleId);
+ 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());
- invalidCmHandleIds.add(cmHandleId);
+ cmHandleUpgradeResponses.add(
+ CmHandleRegistrationResponse.createFailureResponse(cmHandleId, CM_HANDLE_INVALID_ID));
}
- });
- failedCmHandlesPerResponseStatus.put(CM_HANDLES_NOT_READY, nonReadyCmHandleIds);
- failedCmHandlesPerResponseStatus.put(CM_HANDLES_NOT_FOUND, nonExistingCmHandleIds);
- failedCmHandlesPerResponseStatus.put(CM_HANDLE_INVALID_ID, invalidCmHandleIds);
- return mergeAllCmHandleResponses(acceptedCmHandleStatePerCmHandle, failedCmHandlesPerResponseStatus);
- }
-
- private static YangModelCmHandle createYangModelCmHandle(final DmiPluginRegistration dmiPluginRegistration,
- final String cmHandleId) {
- final NcmpServiceCmHandle ncmpServiceCmHandle = new NcmpServiceCmHandle();
- ncmpServiceCmHandle.setCmHandleId(cmHandleId);
- final String moduleSetTag = dmiPluginRegistration.getUpgradedCmHandles().getModuleSetTag();
- final String lockReasonWithModuleSetTag = MessageFormat.format(
- ModuleOperationsUtils.MODULE_SET_TAG_MESSAGE_FORMAT, moduleSetTag);
- ncmpServiceCmHandle.setCompositeState(new CompositeStateBuilder().withCmHandleState(CmHandleState.READY)
+ }
+ cmHandleUpgradeResponses.addAll(upgradeCmHandles(acceptedCmHandleStatePerCmHandle));
+ return cmHandleUpgradeResponses;
+ }
+
+ 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());
- return YangModelCmHandle.toYangModelCmHandle(dmiPluginRegistration.getDmiPlugin(),
- dmiPluginRegistration.getDmiDataPlugin(), dmiPluginRegistration.getDmiModelPlugin(),
- ncmpServiceCmHandle, moduleSetTag, ncmpServiceCmHandle.getAlternateId());
}
private CmHandleRegistrationResponse deleteCmHandleAndGetCmHandleRegistrationResponse(final String cmHandleId) {
@@ -513,17 +528,6 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
}
}
- private List<CmHandleRegistrationResponse> mergeAllCmHandleResponses(
- final Map<YangModelCmHandle, CmHandleState> acceptedCmHandleStatePerCmHandle,
- final Map<NcmpResponseStatus, List<String>> failedCmHandlesPerResponseStatus) {
- final List<CmHandleRegistrationResponse> cmHandleUpgradeResponses
- = upgradeCmHandles(acceptedCmHandleStatePerCmHandle);
- failedCmHandlesPerResponseStatus.forEach((ncmpResponseStatus, cmHandleIds) ->
- cmHandleIds.forEach(cmHandleId -> cmHandleUpgradeResponses.add(CmHandleRegistrationResponse
- .createFailureResponse(cmHandleId, ncmpResponseStatus))));
- return cmHandleUpgradeResponses;
- }
-
private List<CmHandleRegistrationResponse> upgradeCmHandles(final Map<YangModelCmHandle, CmHandleState>
cmHandleStatePerCmHandle) {
final List<String> cmHandleIds = getCmHandleIds(cmHandleStatePerCmHandle);
@@ -549,12 +553,6 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
}
}
- private void cacheAlternateIds(final Collection<NcmpServiceCmHandle> ncmpServiceCmHandles) {
- for (final NcmpServiceCmHandle ncmpServiceCmHandle : ncmpServiceCmHandles) {
- if (!StringUtils.isEmpty(ncmpServiceCmHandle.getAlternateId())) {
- cmHandleIdMapper.addMapping(ncmpServiceCmHandle.getCmHandleId(), ncmpServiceCmHandle.getAlternateId());
- }
- }
- }
+
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandler.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandler.java
index 13b3fcafb..84075a489 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandler.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandler.java
@@ -45,7 +45,7 @@ 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.CmHandleIdMapper;
+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;
@@ -67,7 +67,7 @@ public class NetworkCmProxyDataServicePropertyHandler {
private final InventoryPersistence inventoryPersistence;
private final CpsDataService cpsDataService;
private final JsonObjectMapper jsonObjectMapper;
- private final CmHandleIdMapper cmHandleIdMapper;
+ private final AlternateIdChecker alternateIdChecker;
/**
* Iterates over incoming ncmpServiceCmHandles and update the dataNodes based on the updated attributes.
@@ -81,8 +81,8 @@ public class NetworkCmProxyDataServicePropertyHandler {
for (final NcmpServiceCmHandle ncmpServiceCmHandle : ncmpServiceCmHandles) {
final String cmHandleId = ncmpServiceCmHandle.getCmHandleId();
try {
- final DataNode existingCmHandleDataNode = inventoryPersistence.getCmHandleDataNode(cmHandleId)
- .iterator().next();
+ final DataNode existingCmHandleDataNode = inventoryPersistence
+ .getCmHandleDataNodeByCmHandleId(cmHandleId).iterator().next();
updateAlternateId(existingCmHandleDataNode, ncmpServiceCmHandle);
processUpdates(existingCmHandleDataNode, ncmpServiceCmHandle);
cmHandleRegistrationResponses.add(CmHandleRegistrationResponse.createSuccessResponse(cmHandleId));
@@ -105,17 +105,14 @@ public class NetworkCmProxyDataServicePropertyHandler {
private void updateAlternateId(final DataNode existingCmHandleDataNode,
final NcmpServiceCmHandle ncmpServiceCmHandle) {
+ final YangModelCmHandle yangModelCmHandle =
+ YangDataConverter.convertCmHandleToYangModel(existingCmHandleDataNode,
+ ncmpServiceCmHandle.getCmHandleId());
+ final String currentAlternateId = yangModelCmHandle.getAlternateId();
final String newAlternateId = ncmpServiceCmHandle.getAlternateId();
- if (cmHandleIdMapper.addMapping(ncmpServiceCmHandle.getCmHandleId(), newAlternateId)) {
- try {
- final YangModelCmHandle yangModelCmHandle =
- YangDataConverter.convertCmHandleToYangModel(existingCmHandleDataNode,
- ncmpServiceCmHandle.getCmHandleId());
- setAndUpdateAlternateId(yangModelCmHandle, newAlternateId);
- } catch (final Exception e) {
- cmHandleIdMapper.removeMapping(ncmpServiceCmHandle.getCmHandleId());
- throw e;
- }
+ if (alternateIdChecker.canApplyAlternateId(ncmpServiceCmHandle.getCmHandleId(),
+ currentAlternateId, newAlternateId)) {
+ setAndUpdateAlternateId(yangModelCmHandle, newAlternateId);
}
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/embeddedcache/AlternateIdCacheConfig.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/embeddedcache/AlternateIdCacheConfig.java
deleted file mode 100644
index a69d14476..000000000
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/embeddedcache/AlternateIdCacheConfig.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * ============LICENSE_START========================================================
- * Copyright (C) 2024 Nordix Foundation
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * SPDX-License-Identifier: Apache-2.0
- * ============LICENSE_END=========================================================
- */
-
-package org.onap.cps.ncmp.api.impl.config.embeddedcache;
-
-import com.hazelcast.config.MapConfig;
-import java.util.Map;
-import org.onap.cps.cache.HazelcastCacheConfig;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-@Configuration
-public class AlternateIdCacheConfig extends HazelcastCacheConfig {
-
- private static final MapConfig alternateIdPerCmHandleIdMapConfig =
- createMapConfig("alternateIdPerCmHandleIdMapConfig");
-
- private static final MapConfig cmHandleIdPerAlternateIdMapConfig =
- createMapConfig("cmHandleIdPerAlternateIdMapConfig");
-
- /**
- * Distributed instance of alternate id cache containing the alternate id per cm handle id.
- *
- * @return the cached map.
- */
- @Bean
- public Map<String, String> alternateIdPerCmHandleId() {
- return createHazelcastInstance("hazelcastInstanceAlternateIdPerCmHandleIdMap",
- alternateIdPerCmHandleIdMapConfig).getMap("alternateIdPerCmHandleId");
- }
-
- /**
- * Distributed instance of alternate id cache containing the cm handle id per alternate id.
- *
- * @return the cached map.
- */
- @Bean
- public Map<String, String> cmHandleIdPerAlternateId() {
- return createHazelcastInstance("hazelcastInstanceCmHandleIdPerAlternateIdMap",
- cmHandleIdPerAlternateIdMapConfig).getMap("cmHandleIdPerAlternateId");
- }
-}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/embeddedcache/ModuleSetTagCacheConfig.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/embeddedcache/ModuleSetTagCacheConfig.java
deleted file mode 100644
index a791a3bbd..000000000
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/embeddedcache/ModuleSetTagCacheConfig.java
+++ /dev/null
@@ -1,46 +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.config.embeddedcache;
-
-import com.hazelcast.config.MapConfig;
-import java.util.Collection;
-import java.util.Map;
-import org.onap.cps.cache.HazelcastCacheConfig;
-import org.onap.cps.spi.model.ModuleReference;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-@Configuration
-public class ModuleSetTagCacheConfig extends HazelcastCacheConfig {
-
- private static final MapConfig moduleSetTagCacheMapConfig = createMapConfig("moduleSetTagCacheMapConfig");
-
- /**
- * Map instance for cached ModulesSetTags.
- *
- * @return configured map of ModuleSetTags
- */
- @Bean
- public Map<String, Collection<ModuleReference>> moduleSetTagCache() {
- return createHazelcastInstance("moduleSetTags", moduleSetTagCacheMapConfig)
- .getMap("moduleSetTagCache");
- }
-}
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
index dcd036870..e230b3fcb 100644
--- 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
@@ -114,12 +114,20 @@ public interface InventoryPersistence extends NcmpPersistence {
void saveCmHandleBatch(List<YangModelCmHandle> yangModelCmHandles);
/**
- * Get data node of given cm handle.
+ * Get data node with the given cm handle id.
*
* @param cmHandleId cmHandle ID
* @return data node
*/
- Collection<DataNode> getCmHandleDataNode(String cmHandleId);
+ Collection<DataNode> 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.
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
index 3b7078603..08ab15eaa 100644
--- 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
@@ -22,6 +22,8 @@
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;
@@ -37,6 +39,7 @@ 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;
@@ -54,6 +57,7 @@ public class InventoryPersistenceImpl extends NcmpPersistenceImpl implements Inv
private final CpsModuleService cpsModuleService;
private final CpsAnchorService cpsAnchorService;
private final CpsValidator cpsValidator;
+ private final CmHandleQueries cmHandleQueries;
/**
* initialize an inventory persistence object.
@@ -66,18 +70,19 @@ public class InventoryPersistenceImpl extends NcmpPersistenceImpl implements Inv
*/
public InventoryPersistenceImpl(final JsonObjectMapper jsonObjectMapper, final CpsDataService cpsDataService,
final CpsModuleService cpsModuleService, final CpsValidator cpsValidator,
- final CpsAnchorService cpsAnchorService) {
+ final CpsAnchorService cpsAnchorService, final CmHandleQueries cmHandleQueries) {
super(jsonObjectMapper, cpsDataService, cpsModuleService, cpsValidator);
this.cpsModuleService = cpsModuleService;
this.cpsAnchorService = cpsAnchorService;
this.cpsValidator = cpsValidator;
+ this.cmHandleQueries = cmHandleQueries;
}
@Override
public CompositeState getCmHandleState(final String cmHandleId) {
final DataNode stateAsDataNode = cpsDataService.getDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
- createCmHandleXPath(cmHandleId) + "/state", FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS)
+ getXPathForCmHandleById(cmHandleId) + "/state", FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS)
.iterator().next();
cpsValidator.validateNameCharacters(cmHandleId);
return new CompositeStateBuilder().fromDataNode(stateAsDataNode).build();
@@ -87,14 +92,14 @@ public class InventoryPersistenceImpl extends NcmpPersistenceImpl implements Inv
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,
- createCmHandleXPath(cmHandleId), cmHandleJsonData, OffsetDateTime.now());
+ getXPathForCmHandleById(cmHandleId), cmHandleJsonData, OffsetDateTime.now());
}
@Override
public void saveCmHandleStateBatch(final Map<String, CompositeState> cmHandleStatePerCmHandleId) {
final Map<String, String> cmHandlesJsonDataMap = new HashMap<>();
cmHandleStatePerCmHandleId.forEach((cmHandleId, compositeState) -> cmHandlesJsonDataMap.put(
- createCmHandleXPath(cmHandleId),
+ getXPathForCmHandleById(cmHandleId),
createStateJsonData(jsonObjectMapper.asJsonString(compositeState))));
cpsDataService.updateDataNodesAndDescendants(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
cmHandlesJsonDataMap, OffsetDateTime.now());
@@ -103,7 +108,7 @@ public class InventoryPersistenceImpl extends NcmpPersistenceImpl implements Inv
@Override
public YangModelCmHandle getYangModelCmHandle(final String cmHandleId) {
cpsValidator.validateNameCharacters(cmHandleId);
- final DataNode dataNode = getCmHandleDataNode(cmHandleId).iterator().next();
+ final DataNode dataNode = getCmHandleDataNodeByCmHandleId(cmHandleId).iterator().next();
return YangDataConverter.convertCmHandleToYangModel(dataNode, cmHandleId);
}
@@ -158,14 +163,26 @@ public class InventoryPersistenceImpl extends NcmpPersistenceImpl implements Inv
}
@Override
- public Collection<DataNode> getCmHandleDataNode(final String cmHandleId) {
- return this.getDataNode(createCmHandleXPath(cmHandleId));
+ public Collection<DataNode> getCmHandleDataNodeByCmHandleId(final String cmHandleId) {
+ return this.getDataNode(getXPathForCmHandleById(cmHandleId));
+ }
+
+ @Override
+ public DataNode getCmHandleDataNodeByAlternateId(final String alternateId) {
+ final String xPathForCmHandleByAlternateId = getXPathForCmHandleByAlternateId(alternateId);
+ final Collection<DataNode> dataNodes = cmHandleQueries
+ .queryNcmpRegistryByCpsPath(xPathForCmHandleByAlternateId, OMIT_DESCENDANTS);
+ if (dataNodes.isEmpty()) {
+ throw new DataNodeNotFoundException(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
+ xPathForCmHandleByAlternateId);
+ }
+ return dataNodes.iterator().next();
}
@Override
public Collection<DataNode> getCmHandleDataNodes(final Collection<String> cmHandleIds) {
final Collection<String> xpaths = new ArrayList<>(cmHandleIds.size());
- cmHandleIds.forEach(cmHandleId -> xpaths.add(createCmHandleXPath(cmHandleId)));
+ cmHandleIds.forEach(cmHandleId -> xpaths.add(getXPathForCmHandleById(cmHandleId)));
return this.getDataNodes(xpaths);
}
@@ -174,10 +191,14 @@ public class InventoryPersistenceImpl extends NcmpPersistenceImpl implements Inv
return cpsAnchorService.queryAnchorNames(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, moduleNamesForQuery);
}
- private static String createCmHandleXPath(final String cmHandleId) {
+ private static String getXPathForCmHandleById(final String cmHandleId) {
return NCMP_DMI_REGISTRY_PARENT + "/cm-handles[@id='" + cmHandleId + "']";
}
+ private static String getXPathForCmHandleByAlternateId(final String alternateId) {
+ return NCMP_DMI_REGISTRY_PARENT + "/cm-handles[@alternate-id='" + alternateId + "']";
+ }
+
private static String createStateJsonData(final String state) {
return "{\"state\":" + state + "}";
}
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
index 22bbc7383..9f95131cf 100644
--- 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
@@ -38,7 +38,6 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.StringUtils;
import org.onap.cps.ncmp.api.impl.inventory.CmHandleQueries;
import org.onap.cps.ncmp.api.impl.inventory.CmHandleState;
import org.onap.cps.ncmp.api.impl.inventory.CompositeState;
@@ -62,10 +61,10 @@ public class ModuleOperationsUtils {
private final DmiDataOperations dmiDataOperations;
private final JsonObjectMapper jsonObjectMapper;
private static final String RETRY_ATTEMPT_KEY = "attempt";
- public static final String MODULE_SET_TAG_KEY = "moduleSetTag";
- public static final String MODULE_SET_TAG_MESSAGE_FORMAT = "Upgrade to ModuleSetTag: {0}";
- private static final String UPGRADE_FORMAT = "Upgrade to ModuleSetTag: %s";
- private static final String LOCK_REASON_DETAILS_MSG_FORMAT = UPGRADE_FORMAT + " Attempt #%d failed: %s";
+ 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 = """
@@ -134,10 +133,10 @@ public class ModuleOperationsUtils {
if (!compositeStateDetails.isEmpty() && compositeStateDetails.containsKey(RETRY_ATTEMPT_KEY)) {
attempt = 1 + Integer.parseInt(compositeStateDetails.get(RETRY_ATTEMPT_KEY));
}
- final String moduleSetTag = compositeStateDetails.get(MODULE_SET_TAG_KEY);
+ final String moduleSetTag = compositeStateDetails.getOrDefault(MODULE_SET_TAG_KEY, "");
compositeState.setLockReason(CompositeState.LockReason.builder()
- .details(String.format(LOCK_REASON_DETAILS_MSG_FORMAT, StringUtils.isNotBlank(moduleSetTag)
- ? moduleSetTag : "not-specified", attempt, errorMessage)).lockReasonCategory(lockReasonCategory)
+ .details(String.format(LOCK_REASON_DETAILS_MSG_FORMAT, moduleSetTag, attempt, errorMessage))
+ .lockReasonCategory(lockReasonCategory)
.build());
}
@@ -221,13 +220,17 @@ public class ModuleOperationsUtils {
* @param compositeState current lock reason of cm handle
* @return true or false based on lock reason category
*/
- public static boolean isInUpgradeOrUpgradeFailed(final CompositeState compositeState) {
+ 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);
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
index 72d322605..8b70798eb 100644
--- 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
@@ -35,12 +35,12 @@ import java.util.Optional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.ImmutableTriple;
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.CmHandleQueries;
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.operations.DmiModelOperations;
import org.onap.cps.ncmp.api.impl.utils.YangDataConverter;
import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
@@ -63,7 +63,6 @@ public class ModuleSyncService {
private final CpsDataService cpsDataService;
private final CpsAnchorService cpsAnchorService;
private final JsonObjectMapper jsonObjectMapper;
- private final Map<String, Collection<ModuleReference>> moduleSetTagCache;
private static final Map<String, String> NO_NEW_MODULES = Collections.emptyMap();
/**
@@ -73,44 +72,27 @@ public class ModuleSyncService {
*/
public void syncAndCreateOrUpgradeSchemaSetAndAnchor(final YangModelCmHandle yangModelCmHandle) {
+ final boolean inUpgrade = ModuleOperationsUtils.inUpgradeOrUpgradeFailed(yangModelCmHandle.getCompositeState());
+
+ final ImmutableTriple<String, Map<String, String>, Collection<ModuleReference>>
+ allModuleReferencesAndNewModuleNameByModuleSetTag
+ = getAllModuleReferencesAndNewYangResourcesByModuleSetTag(yangModelCmHandle, inUpgrade);
+
+ final String moduleSetTag = allModuleReferencesAndNewModuleNameByModuleSetTag.getLeft();
+ final Map<String, String> newYangResources = allModuleReferencesAndNewModuleNameByModuleSetTag.getMiddle();
+ final Collection<ModuleReference> allModuleReferences
+ = allModuleReferencesAndNewModuleNameByModuleSetTag.getRight();
final String cmHandleId = yangModelCmHandle.getId();
- final CompositeState compositeState = yangModelCmHandle.getCompositeState();
- final boolean inUpgrade = ModuleOperationsUtils.isInUpgradeOrUpgradeFailed(compositeState);
- final String moduleSetTag = getModuleSetTag(yangModelCmHandle, compositeState, inUpgrade);
-
- final Collection<ModuleReference> moduleReferencesFromCache = moduleSetTagCache.get(moduleSetTag);
-
- if (moduleReferencesFromCache == null) {
- final Optional<DataNode> existingCmHandleWithSameModuleSetTag
- = getFirstReadyDataNodeWithModuleSetTag(moduleSetTag);
-
- if (existingCmHandleWithSameModuleSetTag.isPresent()) {
- final String existingAnchorName = existingCmHandleWithSameModuleSetTag.get().getAnchorName();
- final Collection<ModuleReference> moduleReferencesFromExistingCmHandle =
- upgradeOrCreateSchemaSetUsingModuleSetTag(yangModelCmHandle.getId(), moduleSetTag,
- existingAnchorName, inUpgrade);
- updateModuleSetTagCache(moduleSetTag, moduleReferencesFromExistingCmHandle);
- } else {
- if (inUpgrade) {
- deleteSchemaSetIfExists(cmHandleId);
- }
- final Collection<ModuleReference> allModuleReferencesFromCmHandle
- = syncAndCreateSchemaSet(yangModelCmHandle);
- updateModuleSetTagCache(moduleSetTag, allModuleReferencesFromCmHandle);
- }
+
+ if (inUpgrade) {
+ cpsModuleService.upgradeSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId,
+ newYangResources, allModuleReferences);
+ setCmHandleModuleSetTag(yangModelCmHandle, moduleSetTag);
} else {
- if (inUpgrade) {
- cpsModuleService.upgradeSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId,
- NO_NEW_MODULES, moduleReferencesFromCache);
- } else {
- cpsModuleService.createSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME,
- cmHandleId, NO_NEW_MODULES, moduleReferencesFromCache);
- }
- }
- if (!inUpgrade) {
+ cpsModuleService.createSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId,
+ newYangResources, allModuleReferences);
cpsAnchorService.createAnchor(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId, cmHandleId);
}
- setCmHandleModuleSetTag(yangModelCmHandle, moduleSetTag);
}
/**
@@ -128,7 +110,30 @@ public class ModuleSyncService {
}
}
- private Optional<DataNode> getFirstReadyDataNodeWithModuleSetTag(final String moduleSetTag) {
+ private ImmutableTriple<String, Map<String, String>, Collection<ModuleReference>>
+ getAllModuleReferencesAndNewYangResourcesByModuleSetTag(final YangModelCmHandle yangModelCmHandle,
+ final boolean inUpgrade) {
+
+ final String moduleSetTag = getModuleSetTag(yangModelCmHandle, inUpgrade);
+ final Collection<ModuleReference> allModuleReferences;
+ Map<String, String> newYangResources = Collections.emptyMap();
+
+ final Optional<DataNode> optionalDataNode = getFirstReadyDataNodeByModuleSetTagProvidedInDb(moduleSetTag);
+
+ if (optionalDataNode.isPresent()) {
+ log.info("Found other cm handle having same module set tag: {}", moduleSetTag);
+ final String otherAnchorWithSameModuleSetTag
+ = YangDataConverter.extractCmHandleIdFromXpath(optionalDataNode.get().getXpath());
+ allModuleReferences = cpsModuleService.getYangResourcesModuleReferences(
+ NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, otherAnchorWithSameModuleSetTag);
+ } else {
+ allModuleReferences = dmiModelOperations.getModuleReferences(yangModelCmHandle);
+ newYangResources = getNewModuleNameToContentMap(yangModelCmHandle, allModuleReferences);
+ }
+ return ImmutableTriple.of(moduleSetTag, newYangResources, allModuleReferences);
+ }
+
+ private Optional<DataNode> getFirstReadyDataNodeByModuleSetTagProvidedInDb(final String moduleSetTag) {
final List<DataNode> dataNodes = StringUtils.isNotBlank(moduleSetTag) ? cmHandleQueries
.queryNcmpRegistryByCpsPath("//cm-handles[@module-set-tag='" + moduleSetTag + "']",
FetchDescendantsOption.OMIT_DESCENDANTS) : Collections.emptyList();
@@ -148,56 +153,26 @@ public class ModuleSyncService {
jsonObjectMapper.asJsonString(dmiRegistryProperties), OffsetDateTime.now());
}
- private Collection<ModuleReference> syncAndCreateSchemaSet(final YangModelCmHandle yangModelCmHandle) {
- final Collection<ModuleReference> allModuleReferencesFromCmHandle =
- dmiModelOperations.getModuleReferences(yangModelCmHandle);
- final Collection<ModuleReference> identifiedNewModuleReferencesFromCmHandle = cpsModuleService
- .identifyNewModuleReferences(allModuleReferencesFromCmHandle);
+ private Map<String, String> getNewModuleNameToContentMap(final YangModelCmHandle yangModelCmHandle,
+ final Collection<ModuleReference> moduleReferences) {
+ final Collection<ModuleReference> identifiedNewModuleReferences = cpsModuleService
+ .identifyNewModuleReferences(moduleReferences);
final Map<String, String> newModuleNameToContentMap;
- if (identifiedNewModuleReferencesFromCmHandle.isEmpty()) {
+ if (identifiedNewModuleReferences.isEmpty()) {
newModuleNameToContentMap = NO_NEW_MODULES;
} else {
newModuleNameToContentMap = dmiModelOperations.getNewYangResourcesFromDmi(yangModelCmHandle,
- identifiedNewModuleReferencesFromCmHandle);
- }
- cpsModuleService.createSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME,
- yangModelCmHandle.getId(), newModuleNameToContentMap, allModuleReferencesFromCmHandle);
- return allModuleReferencesFromCmHandle;
- }
-
- private Collection<ModuleReference> upgradeOrCreateSchemaSetUsingModuleSetTag(final String schemaSetName,
- final String moduleSetTag,
- final String existingAnchorName,
- final boolean inUpgrade) {
- log.info("Found cm handle having module set tag: {}", moduleSetTag);
- final Collection<ModuleReference> moduleReferencesFromExistingCmHandle =
- cpsModuleService.getYangResourcesModuleReferences(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME,
- existingAnchorName);
- if (inUpgrade) {
- cpsModuleService.upgradeSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, schemaSetName,
- NO_NEW_MODULES, moduleReferencesFromExistingCmHandle);
- } else {
- cpsModuleService.createSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME,
- schemaSetName, NO_NEW_MODULES, moduleReferencesFromExistingCmHandle);
+ identifiedNewModuleReferences);
}
- return moduleReferencesFromExistingCmHandle;
+ return newModuleNameToContentMap;
}
- private String getModuleSetTag(final YangModelCmHandle yangModelCmHandle,
- final CompositeState compositeState,
- final boolean inUpgrade) {
+ private String getModuleSetTag(final YangModelCmHandle yangModelCmHandle, final boolean inUpgrade) {
if (inUpgrade) {
- return ModuleOperationsUtils.getLockedCompositeStateDetails(compositeState.getLockReason())
- .get(ModuleOperationsUtils.MODULE_SET_TAG_KEY);
+ return ModuleOperationsUtils.getUpgradedModuleSetTagFromLockReason(
+ yangModelCmHandle.getCompositeState().getLockReason());
}
return yangModelCmHandle.getModuleSetTag();
}
- private void updateModuleSetTagCache(final String moduleSetTag,
- final Collection<ModuleReference> allModuleReferencesFromCmHandle) {
- if (StringUtils.isNotBlank(moduleSetTag)) {
- moduleSetTagCache.putIfAbsent(moduleSetTag, allModuleReferencesFromCmHandle);
- }
- }
-
}
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
index e21404418..804653a16 100644
--- 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
@@ -67,7 +67,7 @@ public class ModuleSyncTasks {
final YangModelCmHandle yangModelCmHandle =
YangDataConverter.convertCmHandleToYangModel(cmHandleAsDataNode, cmHandleId);
final CompositeState compositeState = inventoryPersistence.getCmHandleState(cmHandleId);
- final boolean inUpgrade = ModuleOperationsUtils.isInUpgradeOrUpgradeFailed(compositeState);
+ final boolean inUpgrade = ModuleOperationsUtils.inUpgradeOrUpgradeFailed(compositeState);
try {
if (!inUpgrade) {
moduleSyncService.deleteSchemaSetIfExists(cmHandleId);
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
new file mode 100644
index 000000000..1be1a9085
--- /dev/null
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/AlternateIdChecker.java
@@ -0,0 +1,142 @@
+/*
+ * ============LICENSE_START========================================================
+ * Copyright (c) 2024 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.ncmp.api.impl.utils;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence;
+import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
+import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle;
+import org.onap.cps.spi.exceptions.DataNodeNotFoundException;
+import org.springframework.stereotype.Service;
+
+@Service
+@Slf4j
+@RequiredArgsConstructor
+public class AlternateIdChecker {
+
+ private final InventoryPersistence inventoryPersistence;
+
+ private static final String NO_CURRENT_ALTERNATE_ID = "";
+
+ /**
+ * Check if the alternate can be applied to the given cm handle (id).
+ * Conditions:
+ * - proposed alternate is blank (it wil be ignored)
+ * - proposed alternate is same as current (no change)
+ * - proposed alternate is not in use for a different cm handle (in the DB)
+ *
+ * @param cmHandleId cm handle id
+ * @param proposedAlternateId proposed alternate id
+ * @return true if the new alternate id not in use or equal to current alternate id, false otherwise
+ */
+ public boolean canApplyAlternateId(final String cmHandleId, final String proposedAlternateId) {
+ String currentAlternateId = "";
+ try {
+ final YangModelCmHandle yangModelCmHandle = inventoryPersistence.getYangModelCmHandle(cmHandleId);
+ currentAlternateId = yangModelCmHandle.getAlternateId();
+ } catch (final DataNodeNotFoundException dataNodeNotFoundException) {
+ // work with blank current alternate id
+ }
+ return this.canApplyAlternateId(cmHandleId, currentAlternateId, proposedAlternateId);
+ }
+
+ /**
+ * Check if the alternate can be applied to the given cm handle.
+ * Conditions:
+ * - proposed alternate is blank (it wil be ignored)
+ * - proposed alternate is same as current (no change)
+ * - proposed alternate is not in use for a different cm handle (in the DB)
+ *
+ * @param cmHandleId cm handle id
+ * @param currentAlternateId current alternate id
+ * @param proposedAlternateId new alternate id
+ * @return true if the new alternate id not in use or equal to current alternate id, false otherwise
+ */
+ public boolean canApplyAlternateId(final String cmHandleId,
+ final String currentAlternateId,
+ final String proposedAlternateId) {
+ if (StringUtils.isBlank(currentAlternateId)) {
+ if (alternateIdAlreadyInDb(proposedAlternateId)) {
+ log.warn("Alternate id update ignored, cannot update cm handle {}, alternate id is already "
+ + "assigned to a different cm handle", cmHandleId);
+ return false;
+ }
+ return true;
+ }
+ if (currentAlternateId.equals(proposedAlternateId)) {
+ return true;
+ }
+ log.warn("Alternate id update ignored, cannot update cm handle {}, already has an alternate id of {}",
+ cmHandleId, currentAlternateId);
+ return false;
+ }
+
+ /**
+ * Check all alternate ids of a batch of NEW cm handles.
+ * Includes cross-checks in the batch itself for duplicates. Only the first entry encountered wil be accepted.
+ * This method can only be used for NEW cm handle registrations NOT for updating existing ones
+ *
+ * @param newNcmpServiceCmHandles the proposed new cm handles
+ * @return collection of cm handles ids which are acceptable
+ */
+ public Collection<String> getIdsOfCmHandlesWithAcceptableAlternateId(
+ final Collection<NcmpServiceCmHandle> newNcmpServiceCmHandles) {
+ final Set<String> acceptedAlternateIds = new HashSet<>(newNcmpServiceCmHandles.size());
+ final Collection<String> acceptedCmHandleIds = new ArrayList<>(newNcmpServiceCmHandles.size());
+ for (final NcmpServiceCmHandle ncmpServiceCmHandle : newNcmpServiceCmHandles) {
+ final String cmHandleId = ncmpServiceCmHandle.getCmHandleId();
+ final String proposedAlternateId = ncmpServiceCmHandle.getAlternateId();
+ final boolean isAcceptable;
+ if (StringUtils.isEmpty(proposedAlternateId)) {
+ isAcceptable = true;
+ } else {
+ if (acceptedAlternateIds.contains(proposedAlternateId)) {
+ isAcceptable = false;
+ log.warn("Alternate id update ignored, cannot update cm handle {}, alternate id is already "
+ + "assigned to a different cm handle (in this batch)", cmHandleId);
+ } else {
+ isAcceptable = canApplyAlternateId(cmHandleId, NO_CURRENT_ALTERNATE_ID, proposedAlternateId);
+ }
+ }
+ if (isAcceptable) {
+ acceptedAlternateIds.add(proposedAlternateId);
+ acceptedCmHandleIds.add(cmHandleId);
+ }
+ }
+ return acceptedCmHandleIds;
+ }
+
+ private boolean alternateIdAlreadyInDb(final String alternateId) {
+ try {
+ inventoryPersistence.getCmHandleDataNodeByAlternateId(alternateId);
+ } catch (final DataNodeNotFoundException dataNodeNotFoundException) {
+ return false;
+ }
+ return true;
+ }
+
+}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/CmHandleIdMapper.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/CmHandleIdMapper.java
deleted file mode 100644
index a88adbd11..000000000
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/CmHandleIdMapper.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * ============LICENSE_START========================================================
- * Copyright (c) 2024 Nordix Foundation.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an 'AS IS' BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * SPDX-License-Identifier: Apache-2.0
- * ============LICENSE_END=========================================================
- */
-
-package org.onap.cps.ncmp.api.impl.utils;
-
-import java.util.Map;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.StringUtils;
-import org.onap.cps.ncmp.api.NetworkCmProxyCmHandleQueryService;
-import org.springframework.stereotype.Service;
-
-@Service
-@Slf4j
-@RequiredArgsConstructor
-public class CmHandleIdMapper {
-
- private final Map<String, String> alternateIdPerCmHandleId;
- private final Map<String, String> cmHandleIdPerAlternateId;
- private final NetworkCmProxyCmHandleQueryService networkCmProxyCmHandleQueryService;
-
- private boolean cacheIsInitialized = false;
-
- public String cmHandleIdToAlternateId(final String cmHandleId) {
- initializeCache();
- return alternateIdPerCmHandleId.get(cmHandleId);
- }
-
- public String alternateIdToCmHandleId(final String alternateId) {
- initializeCache();
- return cmHandleIdPerAlternateId.get(alternateId);
- }
-
- public boolean addMapping(final String cmHandleId, final String alternateId) {
- initializeCache();
- return addMappingWithValidation(cmHandleId, alternateId);
- }
-
-
- private boolean addMappingWithValidation(final String cmHandleId, final String alternateId) {
- if (alternateIdPerCmHandleId.containsKey(cmHandleId)) {
- final String originalAlternateId = alternateIdPerCmHandleId.get(cmHandleId);
- if (!originalAlternateId.equals(alternateId)) {
- log.warn("Alternate id update ignored, cannot update cm handle {}, already has an alternate id of {}",
- cmHandleId, originalAlternateId);
- }
- return false;
- }
- if (StringUtils.isBlank(alternateId)) {
- return false;
- }
- alternateIdPerCmHandleId.put(cmHandleId, alternateId);
- cmHandleIdPerAlternateId.put(alternateId, cmHandleId);
- return true;
- }
-
- public void removeMapping(final String cmHandleId) {
- final String alternateId = alternateIdPerCmHandleId.remove(cmHandleId);
- removeAlternateIdWithValidation(alternateId);
- }
-
- private void removeAlternateIdWithValidation(final String alternateId) {
- if (alternateId != null) {
- cmHandleIdPerAlternateId.remove(alternateId);
- }
- }
-
- private void initializeCache() {
- if (!cacheIsInitialized) {
- networkCmProxyCmHandleQueryService.getAllCmHandles().forEach(cmHandle ->
- addMappingWithValidation(cmHandle.getCmHandleId(), cmHandle.getAlternateId())
- );
- log.info("Alternate ID cache initialized from DB with {} cm handle/alternate id pairs ",
- alternateIdPerCmHandleId.size());
- cacheIsInitialized = true;
- }
- }
-}
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
index 3be97e8ee..c77e9aa7a 100644
--- 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
@@ -54,6 +54,7 @@ public class YangDataConverter {
final List<YangModelCmHandle.Property> publicProperties = yangModelCmHandle.getPublicProperties();
ncmpServiceCmHandle.setCmHandleId(yangModelCmHandle.getId());
ncmpServiceCmHandle.setCompositeState(yangModelCmHandle.getCompositeState());
+ ncmpServiceCmHandle.setModuleSetTag(yangModelCmHandle.getModuleSetTag());
ncmpServiceCmHandle.setAlternateId(yangModelCmHandle.getAlternateId());
setDmiProperties(dmiProperties, ncmpServiceCmHandle);
setPublicProperties(publicProperties, ncmpServiceCmHandle);
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
index 03e53fc42..b2758d9d5 100644
--- 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
@@ -24,7 +24,6 @@ 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 com.google.common.base.Strings;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -94,6 +93,7 @@ public class YangModelCmHandle {
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();
return copy;
}
@@ -134,7 +134,7 @@ public class YangModelCmHandle {
* @return dmi service name
*/
public String resolveDmiServiceName(final RequiredDmiService requiredService) {
- if (isNullEmptyOrBlank(dmiServiceName)) {
+ if (StringUtils.isBlank(dmiServiceName)) {
if (RequiredDmiService.DATA.equals(requiredService)) {
return dmiDataServiceName;
}
@@ -151,10 +151,6 @@ public class YangModelCmHandle {
return yangModelCmHandleProperties;
}
- private static boolean isNullEmptyOrBlank(final String serviceName) {
- return Strings.isNullOrEmpty(serviceName) || serviceName.isBlank();
- }
-
@AllArgsConstructor
@Data
public static class Property {
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy
index c7ac8ab8b..313d1b4af 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy
@@ -27,8 +27,10 @@ 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.NcmpResponseStatus.UNKNOWN_ERROR
+import java.util.stream.Collectors
+import org.onap.cps.ncmp.api.impl.inventory.CompositeState
import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevelManager
-import org.onap.cps.ncmp.api.impl.utils.CmHandleIdMapper
+import org.onap.cps.ncmp.api.impl.utils.AlternateIdChecker
import org.onap.cps.ncmp.api.models.UpgradedCmHandles
import com.fasterxml.jackson.databind.ObjectMapper
import com.hazelcast.map.IMap
@@ -68,9 +70,14 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
def mockModuleSyncStartedOnCmHandles = Mock(IMap<String, Object>)
def trustLevelPerDmiPlugin = [:]
def mockTrustLevelManager = Mock(TrustLevelManager)
- def mockCmHandleIdMapper = Mock(CmHandleIdMapper)
+ def mockAlternateIdChecker = Mock(AlternateIdChecker)
def objectUnderTest = getObjectUnderTest()
- def mockModuleSetTagCache = [:]
+
+ def setup() {
+ // always accept all cm handles
+ mockAlternateIdChecker.getIdsOfCmHandlesWithAcceptableAlternateId(_) >>
+ { args -> args[0].stream().map(it -> it.cmHandleId).collect(Collectors.toList()) }
+ }
def 'DMI Registration: Create, Update, Delete & Upgrade operations are processed in the right order'() {
given: 'a registration with operations of all types'
@@ -81,6 +88,7 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
dmiRegistration.setUpgradedCmHandles(new UpgradedCmHandles(cmHandles: ['cmhandle-3'], moduleSetTag: 'some-module-set-tag'))
and: 'cm handles are persisted'
mockInventoryPersistence.getYangModelCmHandles(['cmhandle-2']) >> [new YangModelCmHandle()]
+ mockInventoryPersistence.getYangModelCmHandle('cmhandle-3') >> new YangModelCmHandle(id: 'cmhandle-3', moduleSetTag: '', compositeState: new CompositeState(cmHandleState: CmHandleState.READY))
and: 'cm handle is in READY state'
mockCmHandleQueries.cmHandleHasState('cmhandle-3', CmHandleState.READY) >> true
when: 'registration is processed'
@@ -88,7 +96,7 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
then: 'cm-handles are removed first'
1 * objectUnderTest.parseAndProcessDeletedCmHandlesInRegistration(*_)
and: 'de-registered cm handle entry is removed from in progress map'
- 2 * mockModuleSyncStartedOnCmHandles.remove('cmhandle-2')
+ 1 * mockModuleSyncStartedOnCmHandles.remove('cmhandle-2')
then: 'cm-handles are created'
1 * objectUnderTest.parseAndProcessCreatedCmHandlesInRegistration(*_)
then: 'cm-handles are updated'
@@ -102,15 +110,15 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
def dmiRegistration = new DmiPluginRegistration(dmiPlugin: 'my-server')
dmiRegistration.setUpgradedCmHandles(new UpgradedCmHandles(cmHandles: ['cmhandle-3'], moduleSetTag: 'some-module-set-tag'))
and: 'exception while checking cm handle state'
- mockCmHandleQueries.cmHandleHasState('cmhandle-3', CmHandleState.READY) >> isReady
+ mockInventoryPersistence.getYangModelCmHandle('cmhandle-3') >> new YangModelCmHandle(id: 'cmhandle-3', moduleSetTag: '', compositeState: new CompositeState(cmHandleState: cmHandleState))
when: 'registration is processed'
def result = objectUnderTest.updateDmiRegistrationAndSyncModule(dmiRegistration)
then: 'upgrade operation contains expected error code'
- assert result.upgradedCmHandles.status[0] == expectedResponseStatus
+ assert result.upgradedCmHandles[0].status == expectedResponseStatus
where: 'the following parameters are used'
- scenario | isReady || expectedResponseStatus
- 'READY' | true || Status.SUCCESS
- 'Not READY' | false || Status.FAILURE
+ scenario | cmHandleState || expectedResponseStatus
+ 'READY' | CmHandleState.READY || Status.SUCCESS
+ 'Not READY' | CmHandleState.LOCKED || Status.FAILURE
}
def 'DMI Registration upgrade with exception #scenario'() {
@@ -118,7 +126,7 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
def dmiRegistration = new DmiPluginRegistration(dmiPlugin: 'my-server')
dmiRegistration.setUpgradedCmHandles(new UpgradedCmHandles(cmHandles: ['cmhandle-3'], moduleSetTag: 'some-module-set-tag'))
and: 'exception while checking cm handle state'
- mockCmHandleQueries.cmHandleHasState('cmhandle-3', CmHandleState.READY) >> { throw exception }
+ mockInventoryPersistence.getYangModelCmHandle('cmhandle-3') >> { throw exception }
when: 'registration is processed'
def result = objectUnderTest.updateDmiRegistrationAndSyncModule(dmiRegistration)
then: 'upgrade operation contains expected error code'
@@ -160,7 +168,7 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
when: 'update registration and sync module is called with correct DMI plugin information'
objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
then: 'create cm handles registration and sync modules is called with the correct plugin information'
- 1 * objectUnderTest.parseAndProcessCreatedCmHandlesInRegistration(dmiPluginRegistration)
+ 1 * objectUnderTest.parseAndProcessCreatedCmHandlesInRegistration(dmiPluginRegistration, _)
and: 'dmi is added to the dmi trustLevel map'
assert trustLevelPerDmiPlugin.size() == 1
assert trustLevelPerDmiPlugin.containsKey(expectedDmiPluginRegisteredName)
@@ -433,19 +441,19 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
def 'Adding data to alternate id caches.'() {
given: 'a registration with three CM Handles to be created'
- def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: 'my-server',
- createdCmHandles: [new NcmpServiceCmHandle(cmHandleId: 'cmhandle1', alternateId: 'my-alternate-id-1')])
+ def ncmpServiceCmHandles = [new NcmpServiceCmHandle(cmHandleId: 'cmhandle1', alternateId: 'my-alternate-id-1')]
+ def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: 'my-server', createdCmHandles: ncmpServiceCmHandles)
when: 'the DMI plugin registration happens'
objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
then: 'the new alternate id is added to the cache'
- 1 * mockCmHandleIdMapper.addMapping('cmhandle1', 'my-alternate-id-1')
+ 1 * mockAlternateIdChecker.getIdsOfCmHandlesWithAcceptableAlternateId(ncmpServiceCmHandles) >> ['cmhandle1']
}
def getObjectUnderTest() {
return Spy(new NetworkCmProxyDataServiceImpl(spiedJsonObjectMapper, mockDmiDataOperations,
mockNetworkCmProxyDataServicePropertyHandler, mockInventoryPersistence, mockCmHandleQueries,
stubbedNetworkCmProxyCmHandlerQueryService, mockLcmEventsCmHandleStateHandler, mockCpsDataService,
- mockModuleSyncStartedOnCmHandles, trustLevelPerDmiPlugin, mockTrustLevelManager, mockCmHandleIdMapper, mockModuleSetTagCache))
+ mockModuleSyncStartedOnCmHandles, trustLevelPerDmiPlugin, mockTrustLevelManager, mockAlternateIdChecker))
}
def addPersistedYangModelCmHandles(ids) {
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy
index c835056f3..fc548ebe9 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy
@@ -32,7 +32,7 @@ import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_RU
import static org.onap.cps.ncmp.api.impl.operations.OperationType.CREATE
import static org.onap.cps.ncmp.api.impl.operations.OperationType.UPDATE
-import org.onap.cps.ncmp.api.impl.utils.CmHandleIdMapper
+import org.onap.cps.ncmp.api.impl.utils.AlternateIdChecker
import com.hazelcast.map.IMap
import org.onap.cps.ncmp.api.NetworkCmProxyCmHandleQueryService
import org.onap.cps.ncmp.api.impl.events.lcm.LcmEventsCmHandleStateHandler
@@ -54,7 +54,7 @@ import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle
import org.onap.cps.ncmp.api.models.DataOperationRequest
import org.onap.cps.spi.exceptions.CpsException
import org.onap.cps.spi.model.ConditionProperties
-import spock.lang.Shared
+
import java.util.stream.Collectors
import org.onap.cps.utils.JsonObjectMapper
import com.fasterxml.jackson.databind.ObjectMapper
@@ -80,14 +80,11 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
def stubModuleSyncStartedOnCmHandles = Stub(IMap<String, Object>)
def stubTrustLevelPerDmiPlugin = Stub(Map<String, TrustLevel>)
def mockTrustLevelManager = Mock(TrustLevelManager)
- def mockCmHandleIdMapper = Mock(CmHandleIdMapper)
- def mockModuleSetTagCache = [:]
+ def mockAlternateIdChecker = Mock(AlternateIdChecker)
def NO_TOPIC = null
def NO_REQUEST_ID = null
- @Shared
def OPTIONS_PARAM = '(a=1,b=2)'
- @Shared
def ncmpServiceCmHandle = new NcmpServiceCmHandle(cmHandleId: 'test-cm-handle-id')
def objectUnderTest = new NetworkCmProxyDataServiceImpl(
@@ -102,8 +99,7 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
stubModuleSyncStartedOnCmHandles,
stubTrustLevelPerDmiPlugin,
mockTrustLevelManager,
- mockCmHandleIdMapper,
- mockModuleSetTagCache)
+ mockAlternateIdChecker)
def cmHandleXPath = "/dmi-registry/cm-handles[@id='testCmHandle']"
@@ -177,14 +173,17 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
given: 'the system returns a yang modelled cm handle'
def dmiServiceName = 'some service name'
def compositeState = new CompositeState(cmHandleState: CmHandleState.ADVISED,
- lockReason: CompositeState.LockReason.builder().lockReasonCategory(LockReasonCategory.MODULE_SYNC_FAILED).details("lock details").build(),
- lastUpdateTime: 'some-timestamp',
- dataSyncEnabled: false,
- dataStores: dataStores())
+ lockReason: CompositeState.LockReason.builder().lockReasonCategory(LockReasonCategory.MODULE_SYNC_FAILED).details("lock details").build(),
+ lastUpdateTime: 'some-timestamp',
+ dataSyncEnabled: false,
+ dataStores: dataStores())
def dmiProperties = [new YangModelCmHandle.Property('Book', 'Romance Novel')]
def publicProperties = [new YangModelCmHandle.Property('Public Book', 'Public Romance Novel')]
+ def moduleSetTag = 'some-module-set-tag'
+ def alternateId = 'some-alternate-id'
def yangModelCmHandle = new YangModelCmHandle(id: 'some-cm-handle', dmiServiceName: dmiServiceName,
- dmiProperties: dmiProperties, publicProperties: publicProperties, compositeState: compositeState)
+ dmiProperties: dmiProperties, publicProperties: publicProperties, compositeState: compositeState,
+ moduleSetTag: moduleSetTag, alternateId: alternateId)
1 * mockInventoryPersistence.getYangModelCmHandle('some-cm-handle') >> yangModelCmHandle
when: 'getting cm handle details for a given cm handle id from ncmp service'
def result = objectUnderTest.getNcmpServiceCmHandle('some-cm-handle')
@@ -192,13 +191,16 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
result.class == NcmpServiceCmHandle.class
and: 'the cm handle contains the cm handle id'
result.cmHandleId == 'some-cm-handle'
+ and: 'the cm handle contains the alternate id'
+ result.alternateId == 'some-alternate-id'
+ and: 'the cm handle contains the module-set-tag'
+ result.moduleSetTag == 'some-module-set-tag'
and: 'the cm handle contains the DMI Properties'
result.dmiProperties ==[ Book:'Romance Novel' ]
and: 'the cm handle contains the public Properties'
result.publicProperties == [ "Public Book":'Public Romance Novel' ]
and: 'the cm handle contains the cm handle composite state'
result.compositeState == compositeState
-
}
def 'Get cm handle public properties'() {
@@ -269,7 +271,7 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
dmiPluginRegistration.createdCmHandles = [ncmpServiceCmHandle]
mockDmiPluginRegistration.getCreatedCmHandles() >> [ncmpServiceCmHandle]
when: 'parse and create cm handle in dmi registration then sync module'
- objectUnderTest.parseAndProcessCreatedCmHandlesInRegistration(mockDmiPluginRegistration)
+ objectUnderTest.parseAndProcessCreatedCmHandlesInRegistration(mockDmiPluginRegistration, ['test-cm-handle-id'])
then: 'system persists the cm handle state'
1 * mockLcmEventsCmHandleStateHandler.initiateStateAdvised(_) >> {
args -> {
@@ -280,7 +282,7 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
}
}
}
-
+
def 'Execute cm handle id search'() {
given: 'valid CmHandleQueryApiParameters input'
def cmHandleQueryApiParameters = new CmHandleQueryApiParameters()
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandlerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandlerSpec.groovy
index f94c34c58..d822f2e63 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandlerSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandlerSpec.groovy
@@ -22,35 +22,33 @@
package org.onap.cps.ncmp.api.impl
-
import com.fasterxml.jackson.databind.ObjectMapper
-import org.onap.cps.ncmp.api.impl.utils.CmHandleIdMapper
-
-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.NcmpResponseStatus.CM_HANDLES_NOT_FOUND
-import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLE_INVALID_ID
-import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNKNOWN_ERROR
-import static org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.Status
-
import org.onap.cps.api.CpsDataService
-import org.onap.cps.utils.JsonObjectMapper
import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence
-import org.onap.cps.spi.exceptions.DataValidationException
+import org.onap.cps.ncmp.api.impl.utils.AlternateIdChecker
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.JsonObjectMapper
import spock.lang.Specification
+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.NcmpResponseStatus.UNKNOWN_ERROR
+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.models.CmHandleRegistrationResponse.Status
+
class NetworkCmProxyDataServicePropertyHandlerSpec extends Specification {
def mockInventoryPersistence = Mock(InventoryPersistence)
def mockCpsDataService = Mock(CpsDataService)
def jsonObjectMapper = new JsonObjectMapper(new ObjectMapper())
- def mockCmHandleIdMapper = Mock(CmHandleIdMapper)
+ def mockAlternateIdChecker = Mock(AlternateIdChecker)
- def objectUnderTest = new NetworkCmProxyDataServicePropertyHandler(mockInventoryPersistence, mockCpsDataService, jsonObjectMapper, mockCmHandleIdMapper)
+ def objectUnderTest = new NetworkCmProxyDataServicePropertyHandler(mockInventoryPersistence, mockCpsDataService, jsonObjectMapper, mockAlternateIdChecker)
def static cmHandleId = 'myHandle1'
def static cmHandleXpath = "/dmi-registry/cm-handles[@id='${cmHandleId}']"
@@ -62,7 +60,7 @@ class NetworkCmProxyDataServicePropertyHandlerSpec extends Specification {
def 'Update CM Handle Public Properties: #scenario'() {
given: 'the CPS service return a CM handle'
- mockInventoryPersistence.getCmHandleDataNode(cmHandleId) >> cmHandleDataNodeAsCollection
+ mockInventoryPersistence.getCmHandleDataNodeByCmHandleId(cmHandleId) >> cmHandleDataNodeAsCollection
and: 'an update cm handle request with public properties updates'
def cmHandleUpdateRequest = [new NcmpServiceCmHandle(cmHandleId: cmHandleId, publicProperties: updatedPublicProperties)]
when: 'update data node leaves is called with the update request'
@@ -84,7 +82,7 @@ class NetworkCmProxyDataServicePropertyHandlerSpec extends Specification {
def 'Update DMI Properties: #scenario'() {
given: 'the CPS service return a CM handle'
- mockInventoryPersistence.getCmHandleDataNode(cmHandleId) >> cmHandleDataNodeAsCollection
+ mockInventoryPersistence.getCmHandleDataNodeByCmHandleId(cmHandleId) >> cmHandleDataNodeAsCollection
and: 'an update cm handle request with DMI properties updates'
def cmHandleUpdateRequest = [new NcmpServiceCmHandle(cmHandleId: cmHandleId, dmiProperties: updatedDmiProperties)]
when: 'update data node leaves is called with the update request'
@@ -108,7 +106,7 @@ class NetworkCmProxyDataServicePropertyHandlerSpec extends Specification {
def 'Update CM Handle Properties, remove all properties: #scenario'() {
given: 'the CPS service return a CM handle'
def cmHandleDataNode = new DataNode(xpath: cmHandleXpath, childDataNodes: originalPropertyDataNodes)
- mockInventoryPersistence.getCmHandleDataNode(cmHandleId) >> [cmHandleDataNode]
+ mockInventoryPersistence.getCmHandleDataNodeByCmHandleId(cmHandleId) >> [cmHandleDataNode]
and: 'an update cm handle request that removes all public properties(existing and non-existing)'
def cmHandleUpdateRequest = [new NcmpServiceCmHandle(cmHandleId: cmHandleId, publicProperties: ['publicProp3': null, 'publicProp4': null])]
when: 'update data node leaves is called with the update request'
@@ -131,7 +129,7 @@ class NetworkCmProxyDataServicePropertyHandlerSpec extends Specification {
given: 'cm handles request'
def cmHandleUpdateRequest = [new NcmpServiceCmHandle(cmHandleId: cmHandleId, publicProperties: [:], dmiProperties: [:])]
and: 'data node cannot be found'
- mockInventoryPersistence.getCmHandleDataNode(*_) >> { throw exception }
+ mockInventoryPersistence.getCmHandleDataNodeByCmHandleId(*_) >> { throw exception }
when: 'update data node leaves is called using correct parameters'
def response = objectUnderTest.updateCmHandleProperties(cmHandleUpdateRequest)
then: 'one failed registration response'
@@ -156,7 +154,7 @@ class NetworkCmProxyDataServicePropertyHandlerSpec extends Specification {
new NcmpServiceCmHandle(cmHandleId: cmHandleId, publicProperties: ['publicProp1': "value"], dmiProperties: [:]),
new NcmpServiceCmHandle(cmHandleId: cmHandleId, publicProperties: ['publicProp1': "value"], dmiProperties: [:])]
and: 'data node can be found for 1st and 3rd cm-handle but not for 2nd cm-handle'
- mockInventoryPersistence.getCmHandleDataNode(*_) >> cmHandleDataNodeAsCollection >> {
+ mockInventoryPersistence.getCmHandleDataNodeByCmHandleId(*_) >> cmHandleDataNodeAsCollection >> {
throw new DataNodeNotFoundException(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR) } >> cmHandleDataNodeAsCollection
when: 'update data node leaves is called using correct parameters'
def cmHandleResponseList = objectUnderTest.updateCmHandleProperties(cmHandleUpdateRequest)
@@ -194,7 +192,7 @@ class NetworkCmProxyDataServicePropertyHandlerSpec extends Specification {
{ args ->
assert args[3].contains('alt-1')
}
- mockCmHandleIdMapper.addMapping(cmHandleId, 'alt-1') >> isNewMapping
+ mockAlternateIdChecker.canApplyAlternateId(cmHandleId, '','alt-1') >> isNewMapping
where: 'following updates are attempted'
scenario | isNewMapping || callsToDataService
'new alternate id ' | true || 1
@@ -205,8 +203,8 @@ class NetworkCmProxyDataServicePropertyHandlerSpec extends Specification {
given: 'an existing data node and an update request with an alternate id'
def ncmpServiceCmHandle = new NcmpServiceCmHandle(cmHandleId: cmHandleId, alternateId: 'alt-1')
DataNode existingCmHandleDataNode = new DataNode(xpath: cmHandleXpath, leaves: ['alternate-id': null])
- and: 'a new mapping is added'
- mockCmHandleIdMapper.addMapping(cmHandleId, 'alt-1') >> true
+ and: 'an applicable alternate id for the cm handle'
+ mockAlternateIdChecker.canApplyAlternateId(cmHandleId, '','alt-1') >> true
and: 'but an exception occurs while saving'
def originalException = new NullPointerException('some exception')
mockCpsDataService.updateNodeLeaves(*_) >> { throw originalException }
@@ -215,8 +213,6 @@ class NetworkCmProxyDataServicePropertyHandlerSpec extends Specification {
then: 'the original exception is thrown up'
def thrownException = thrown(NullPointerException)
assert thrownException == originalException
- and: 'the mapping is removed from the cache'
- 1 * mockCmHandleIdMapper.removeMapping(cmHandleId)
}
def convertToProperties(expectedPropertiesAfterUpdateAsMap) {
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/embeddedcache/AlternateIdCacheConfigSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/embeddedcache/AlternateIdCacheConfigSpec.groovy
deleted file mode 100644
index 71c5293e2..000000000
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/embeddedcache/AlternateIdCacheConfigSpec.groovy
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * ============LICENSE_START========================================================
- * Copyright (C) 2024 Nordix Foundation
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * SPDX-License-Identifier: Apache-2.0
- * ============LICENSE_END=========================================================
- */
-
-package org.onap.cps.ncmp.api.impl.config.embeddedcache
-
-import com.hazelcast.core.Hazelcast
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.boot.test.context.SpringBootTest
-import spock.lang.Specification
-
-@SpringBootTest(classes = [AlternateIdCacheConfig])
-class AlternateIdCacheConfigSpec extends Specification {
-
- @Autowired
- private Map<String, String> cmHandleIdPerAlternateId
- @Autowired
- private Map<String, String> alternateIdPerCmHandleId
-
- def 'Embedded (hazelcast) cache for alternate id - cm handle id caches.'() {
- expect: 'system is able to create an instance of the Alternate ID Cache'
- assert null != cmHandleIdPerAlternateId
- assert null != alternateIdPerCmHandleId
- and: 'there are at least 2 instances'
- assert Hazelcast.allHazelcastInstances.size() > 1
- and: 'Alternate ID Caches are present'
- assert Hazelcast.allHazelcastInstances.name.contains('hazelcastInstanceAlternateIdPerCmHandleIdMap')
- && Hazelcast.allHazelcastInstances.name.contains('hazelcastInstanceCmHandleIdPerAlternateIdMap')
- }
-
- def 'Verify configs of the alternate id distributed objects.'(){
- when: 'retrieving the map config of module set tag'
- def alternateIdConfig = Hazelcast.getHazelcastInstanceByName('hazelcastInstanceAlternateIdPerCmHandleIdMap').config
- def alternateIdMapConfig = alternateIdConfig.mapConfigs.get('alternateIdPerCmHandleIdMapConfig')
- def cmHandleIdConfig = Hazelcast.getHazelcastInstanceByName('hazelcastInstanceCmHandleIdPerAlternateIdMap').config
- def cmHandleIdIdMapConfig = cmHandleIdConfig.mapConfigs.get('cmHandleIdPerAlternateIdMapConfig')
- then: 'the map configs have the correct number of backups'
- assert alternateIdMapConfig.backupCount == 3
- assert alternateIdMapConfig.asyncBackupCount == 3
- assert cmHandleIdIdMapConfig.backupCount == 3
- assert cmHandleIdIdMapConfig.asyncBackupCount == 3
- }
-}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/embeddedcache/ModuleSetTagCacheConfigSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/embeddedcache/ModuleSetTagCacheConfigSpec.groovy
deleted file mode 100644
index 8a6a32bd8..000000000
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/embeddedcache/ModuleSetTagCacheConfigSpec.groovy
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * Copyright (C) 2023 Nordix Foundation
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * SPDX-License-Identifier: Apache-2.0
- * ============LICENSE_END=========================================================
- */
-
-package org.onap.cps.ncmp.api.impl.config.embeddedcache
-
-import com.hazelcast.config.Config
-import com.hazelcast.core.Hazelcast
-import org.onap.cps.spi.model.ModuleReference
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.boot.test.context.SpringBootTest
-import spock.lang.Specification
-
-@SpringBootTest(classes = [ModuleSetTagCacheConfig])
-class ModuleSetTagCacheConfigSpec extends Specification {
-
- @Autowired
- private Map<String, Collection<ModuleReference>> moduleSetTagCache
-
- def 'Embedded (hazelcast) caches for module set tag.'() {
- expect: 'system is able to create an instance of a map to hold module set tags'
- assert null != moduleSetTagCache
- and: 'there is at least 1 instance'
- assert Hazelcast.allHazelcastInstances.size() > 0
- and: 'hazelcast instance name of module set tag is correct'
- assert Hazelcast.allHazelcastInstances.name.contains('moduleSetTags')
- }
-
- def 'Verify configs of module set tag distributed object.'(){
- when: 'retrieving the map config of module set tag'
- def cacheConfig = Hazelcast.getHazelcastInstanceByName('moduleSetTags').config
- def moduleSetTagMapConfig = cacheConfig.mapConfigs.get('moduleSetTagCacheMapConfig')
- then: 'the module set tag map config has correct backup counts'
- assert moduleSetTagMapConfig.backupCount == 3
- assert moduleSetTagMapConfig.asyncBackupCount == 3
- }
-
- def 'Verify deployment network configs of distributed cache of module set tag object.'() {
- given: 'network config of module set tag cache'
- def moduleSetTagNetworkConfig = Hazelcast.getHazelcastInstanceByName('moduleSetTags').config.networkConfig
- expect: 'module set tag cache has the correct settings'
- assert moduleSetTagNetworkConfig.join.autoDetectionConfig.enabled
- assert !moduleSetTagNetworkConfig.join.kubernetesConfig.enabled
- }
-
- def 'Verify network of module set tag cache'() {
- given: 'Synchronization config object and test configuration'
- def objectUnderTest = new ModuleSetTagCacheConfig()
- def testConfig = new Config()
- when: 'kubernetes properties are enabled'
- objectUnderTest.cacheKubernetesEnabled = true
- objectUnderTest.cacheKubernetesServiceName = 'test-service-name'
- and: 'method called to update the discovery mode'
- objectUnderTest.updateDiscoveryMode(testConfig)
- then: 'applied properties are reflected'
- assert testConfig.networkConfig.join.kubernetesConfig.enabled
- assert testConfig.networkConfig.join.kubernetesConfig.properties.get('service-name') == 'test-service-name'
-
- }
-}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/InventoryPersistenceImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/InventoryPersistenceImplSpec.groovy
index a3b923f93..83acb2238 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/InventoryPersistenceImplSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/InventoryPersistenceImplSpec.groovy
@@ -22,32 +22,34 @@
package org.onap.cps.ncmp.api.impl.inventory
-import org.onap.cps.api.CpsAnchorService
-
-import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME
-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.NO_TIMESTAMP
-import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS
-
import com.fasterxml.jackson.databind.ObjectMapper
+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.yangmodels.YangModelCmHandle
import org.onap.cps.spi.CascadeDeleteAllowed
import org.onap.cps.spi.FetchDescendantsOption
+import org.onap.cps.spi.exceptions.DataNodeNotFoundException
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.utils.JsonObjectMapper
import org.onap.cps.spi.utils.CpsValidator
+import org.onap.cps.utils.JsonObjectMapper
import spock.lang.Shared
import spock.lang.Specification
+
import java.time.OffsetDateTime
import java.time.ZoneOffset
import java.time.format.DateTimeFormatter
+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 static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NO_TIMESTAMP
+import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS
+import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS
+
class InventoryPersistenceImplSpec extends Specification {
def spiedJsonObjectMapper = Spy(new JsonObjectMapper(new ObjectMapper()))
@@ -60,8 +62,10 @@ class InventoryPersistenceImplSpec extends Specification {
def mockCpsValidator = Mock(CpsValidator)
+ def mockCmHandleQueries = Mock(CmHandleQueries)
+
def objectUnderTest = new InventoryPersistenceImpl(spiedJsonObjectMapper, mockCpsDataService, mockCpsModuleService,
- mockCpsValidator, mockCpsAnchorService)
+ mockCpsValidator, mockCpsAnchorService, mockCmHandleQueries)
def formattedDateAndTime = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
.format(OffsetDateTime.of(2022, 12, 31, 20, 30, 40, 1, ZoneOffset.UTC))
@@ -283,13 +287,32 @@ class InventoryPersistenceImplSpec extends Specification {
def 'Get cmHandle data node'() {
given: 'expected xPath to get cmHandle data node'
- def expectedXPath = '/dmi-registry/cm-handles[@id=\'sample cmHandleId\']';
+ def expectedXPath = '/dmi-registry/cm-handles[@id=\'sample cmHandleId\']'
when: 'the method to get data nodes is called'
- objectUnderTest.getCmHandleDataNode('sample cmHandleId')
+ objectUnderTest.getCmHandleDataNodeByCmHandleId('sample cmHandleId')
then: 'the data persistence service method to get cmHandle data node is invoked once with expected xPath'
1 * mockCpsDataService.getDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, expectedXPath, INCLUDE_ALL_DESCENDANTS)
}
+ def 'Get cm handle data node'() {
+ given: 'expected xPath to get cmHandle data node'
+ def expectedXPath = '/dmi-registry/cm-handles[@alternate-id=\'alternate id\']'
+ and: 'query service is invoked with expected xpath'
+ mockCmHandleQueries.queryNcmpRegistryByCpsPath(expectedXPath, OMIT_DESCENDANTS) >> [new DataNode()]
+ expect: 'getting the cm handle data node'
+ assert objectUnderTest.getCmHandleDataNodeByAlternateId('alternate id') == new DataNode()
+ }
+
+ def 'Attempt to get non existing cm handle data node by alternate id'() {
+ given: 'query service is invoked and returns empty collection of data nodes'
+ mockCmHandleQueries.queryNcmpRegistryByCpsPath(*_) >> []
+ when: 'getting the cm handle data node'
+ objectUnderTest.getCmHandleDataNodeByAlternateId('alternate id')
+ then: 'no data found exception thrown'
+ def thrownException = thrown(DataNodeNotFoundException)
+ assert thrownException.getMessage().contains('DataNode not found')
+ }
+
def 'Get CM handles that has given module names'() {
when: 'the method to get cm handles is called'
objectUnderTest.getCmHandleIdsWithGivenModules(['sample-module-name'])
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleOperationsUtilsSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleOperationsUtilsSpec.groovy
index 827a548ae..44bc18200 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleOperationsUtilsSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleOperationsUtilsSpec.groovy
@@ -125,7 +125,7 @@ class ModuleOperationsUtilsSpec extends Specification{
where:
scenario | moduleSetTag || expectedDetails
'a module set tag' | 'someModuleSetTag' || 'someModuleSetTag'
- 'empty module set tag' | '' || 'not-specified'
+ 'empty module set tag' | '' || ''
}
def 'Get all locked cm-Handles where lock reasons are model sync failed or upgrade'() {
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncServiceSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncServiceSpec.groovy
index de783ed2c..b0ff6d886 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncServiceSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncServiceSpec.groovy
@@ -50,10 +50,9 @@ class ModuleSyncServiceSpec extends Specification {
def mockCmHandleQueries = Mock(CmHandleQueries)
def mockCpsDataService = Mock(CpsDataService)
def mockJsonObjectMapper = Mock(JsonObjectMapper)
- def mockModuleSetTagCache = [:]
def objectUnderTest = new ModuleSyncService(mockDmiModelOperations, mockCpsModuleService,
- mockCmHandleQueries, mockCpsDataService, mockCpsAnchorService, mockJsonObjectMapper, mockModuleSetTagCache)
+ mockCmHandleQueries, mockCpsDataService, mockCpsAnchorService, mockJsonObjectMapper)
def expectedDataspaceName = NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME
def static cmHandleWithModuleSetTag = new DataNodeBuilder().withXpath("//cm-handles[@module-set-tag='tag-1'][@id='otherId']").withAnchor('otherId').build()
@@ -96,11 +95,7 @@ class ModuleSyncServiceSpec extends Specification {
and: 'some module references'
def moduleReferences = [ new ModuleReference('module1','1') ]
and: 'cache or DMI operations returns some module references for upgraded cm handle'
- if (populateCache) {
- mockModuleSetTagCache.put('tag-1', moduleReferences)
- } else {
- mockDmiModelOperations.getModuleReferences(yangModelCmHandle) >> moduleReferences
- }
+ mockDmiModelOperations.getModuleReferences(yangModelCmHandle) >> moduleReferences
and: 'none of these module references are new (unknown to the system)'
mockCpsModuleService.identifyNewModuleReferences(moduleReferences) >> []
and: 'CPS-Core returns list of existing module resources for TBD'
@@ -118,10 +113,9 @@ class ModuleSyncServiceSpec extends Specification {
and: 'No anchor is created for the upgraded cm handle'
0 * mockCpsAnchorService.createAnchor(*_)
where: 'the following parameters are used'
- scenario | populateCache | existingCmHandlesWithSameTag || expectedCallsToUpgradeSchemaSet | expectedCallsToCeateSchemaSet
- 'new' | false | [] || 0 | 1
- 'in cache' | true | [] || 1 | 0
- 'in database' | false | [cmHandleWithModuleSetTag] || 1 | 0
+ scenario | existingCmHandlesWithSameTag || expectedCallsToUpgradeSchemaSet | expectedCallsToCeateSchemaSet
+ 'new' | [] || 1 | 0
+ 'in database' | [cmHandleWithModuleSetTag] || 1 | 0
}
def 'upgrade model for a existing cm handle'() {
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/AlternateIdCheckerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/AlternateIdCheckerSpec.groovy
new file mode 100644
index 000000000..f41fd6cdf
--- /dev/null
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/AlternateIdCheckerSpec.groovy
@@ -0,0 +1,97 @@
+/*
+ * ============LICENSE_START========================================================
+ * Copyright (c) 2024 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.ncmp.api.impl.utils
+
+
+import 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.spi.exceptions.DataNodeNotFoundException
+import org.onap.cps.spi.model.DataNode
+import org.onap.cps.spi.model.DataNodeBuilder
+import spock.lang.Specification
+
+class AlternateIdCheckerSpec extends Specification {
+
+ def mockInventoryPersistenceService = Mock(InventoryPersistence)
+ def someDataNode = new DataNodeBuilder().build()
+ def dataNodeFoundException = new DataNodeNotFoundException('', '')
+
+ def objectUnderTest = new AlternateIdChecker(mockInventoryPersistenceService)
+
+ def 'Check new cm handle with new alternate id.'() {
+ given: 'inventory persistence can not find cm handle id'
+ mockInventoryPersistenceService.getYangModelCmHandle('ch 1') >> {throw dataNodeFoundException}
+ and: 'inventory persistence can not find alternate id'
+ mockInventoryPersistenceService.getCmHandleDataNodeByAlternateId('alternate id') >> {throw dataNodeFoundException}
+ expect: 'mapping can be added'
+ assert objectUnderTest.canApplyAlternateId('ch 1', 'alternate id')
+ }
+
+ def 'Check new cm handle with used alternate id.'() {
+ given: 'inventory persistence can not find cm handle id'
+ mockInventoryPersistenceService.getYangModelCmHandle('ch 1') >> {throw dataNodeFoundException}
+ and: 'inventory persistence can find alternate id'
+ mockInventoryPersistenceService.getCmHandleDataNodeByAlternateId('alternate id') >> { someDataNode }
+ expect: 'mapping can not be added'
+ assert objectUnderTest.canApplyAlternateId('ch 1', 'alternate id') == false
+ }
+
+ def 'Check for existing cm handle with #currentAlternateId.'() {
+ given: 'a cm handle with the #currentAlternateId'
+ def yangModelCmHandle = new YangModelCmHandle(alternateId: currentAlternateId)
+ and: 'inventory service finds the cm handle'
+ mockInventoryPersistenceService.getYangModelCmHandle('my cm handle') >> yangModelCmHandle
+ expect: 'add mapping returns expected result'
+ assert canAdd == objectUnderTest.canApplyAlternateId('my cm handle', 'same alternate id')
+ where: 'following alternate ids is used'
+ currentAlternateId || canAdd
+ 'same alternate id' || true
+ 'other alternate id' || false
+ }
+
+ def 'Check a batch of NEW cm handles with #scenario.'() {
+ given: 'a batch of 2 new cm handles alternate id ids #alt1 and #alt2'
+ def batch = [new NcmpServiceCmHandle(cmHandleId: 'ch-1', alternateId: alt1),
+ new NcmpServiceCmHandle(cmHandleId: 'ch-2', alternateId: alt2)]
+ and: 'the database already contains cm handle(s) with these alternate ids: #alreadyinDb'
+ mockInventoryPersistenceService.getCmHandleDataNodeByAlternateId(_) >>
+ { args -> altAlreadyInDb.contains(args[0]) ? new DataNode() : throwDataNodeNotFoundException() }
+ when: 'the batch of new cm handles is checked'
+ def result = objectUnderTest.getIdsOfCmHandlesWithAcceptableAlternateId(batch)
+ then: 'the result only contains the ids of the acceptable cm handles'
+ assert result.contains('ch-1') == acceptCh1
+ assert result.contains('ch-2') == acceptCh2
+ where: 'the following alternate ids are used'
+ scenario | alt1 | alt2 | altAlreadyInDb || acceptCh1 | acceptCh2
+ 'no alternate ids' | '' | '' | ['dont matter'] || true | true
+ 'new alternate ids' | 'fdn1' | 'fdn2' | ['other fdn'] || true | true
+ 'one already used alternate id' | 'fdn1' | 'fdn2' | ['fdn1'] || false | true
+ 'two already used alternate ids' | 'fdn1' | 'fdn2' | ['fdn1','fdn2'] || false | false
+ 'duplicate alternate id in batch' | 'fdn1' | 'fdn1' | ['dont matter'] || true | false
+ }
+
+ def throwDataNodeNotFoundException() {
+ // cannot 'return' an exception in conditional stub behavior, so hence a method call that will always throw this exception
+ throw dataNodeFoundException
+ }
+
+}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/CmHandleIdMapperSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/CmHandleIdMapperSpec.groovy
deleted file mode 100644
index 55ccdf3be..000000000
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/CmHandleIdMapperSpec.groovy
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * ============LICENSE_START========================================================
- * Copyright (c) 2024 Nordix Foundation.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an 'AS IS' BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * SPDX-License-Identifier: Apache-2.0
- * ============LICENSE_END=========================================================
- */
-
-package org.onap.cps.ncmp.api.impl.utils
-
-import ch.qos.logback.classic.Level
-import ch.qos.logback.classic.Logger
-import ch.qos.logback.classic.spi.ILoggingEvent
-import ch.qos.logback.core.read.ListAppender
-import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle
-import org.slf4j.LoggerFactory
-import org.onap.cps.ncmp.api.NetworkCmProxyCmHandleQueryService
-import spock.lang.Specification
-
-class CmHandleIdMapperSpec extends Specification {
-
- def alternateIdPerCmHandle = new HashMap<String, String>()
- def cmHandlePerAlternateId = new HashMap<String, String>()
- def mockCpsCmHandlerQueryService = Mock(NetworkCmProxyCmHandleQueryService)
-
- def objectUnderTest = new CmHandleIdMapper(alternateIdPerCmHandle, cmHandlePerAlternateId, mockCpsCmHandlerQueryService)
-
- def logger = Spy(ListAppender<ILoggingEvent>)
-
- def setup() {
- ((Logger) LoggerFactory.getLogger(CmHandleIdMapper.class)).addAppender(logger)
- logger.start()
- mockCpsCmHandlerQueryService.getAllCmHandles() >> []
- assert objectUnderTest.addMapping('my cmhandle id', 'my alternate id')
- }
-
- void cleanup() {
- ((Logger) LoggerFactory.getLogger(CmHandleIdMapper.class)).detachAndStopAllAppenders()
- }
-
- def 'Checking entries in the cache.'() {
- expect: 'the alternate id can be converted to cmhandle id'
- assert objectUnderTest.alternateIdToCmHandleId('my alternate id') == 'my cmhandle id'
- and: 'the cmhandle id can be converted to alternate id'
- assert objectUnderTest.cmHandleIdToAlternateId('my cmhandle id') == 'my alternate id'
- }
-
- def 'Attempt adding #scenario alternate id.'() {
- expect: 'cmhandle id - alternate id mapping fails'
- assert objectUnderTest.addMapping('ch-1', alternateId) == false
- and: 'alternate id looked up by cmhandle id unsuccessfully'
- assert objectUnderTest.cmHandleIdToAlternateId('ch-1') == null
- where: 'alternate id has an invalid value'
- scenario | alternateId
- 'empty' | ''
- 'blank' | ' '
- 'null' | null
- }
-
- def 'Remove an entry from the cache.'() {
- when: 'removing an entry'
- objectUnderTest.removeMapping('my cmhandle id')
- then: 'converting alternate id returns null'
- assert objectUnderTest.alternateIdToCmHandleId('my alternate id') == null
- and: 'converting cmhandle id returns null'
- assert objectUnderTest.cmHandleIdToAlternateId('my cmhandle id') == null
- }
-
- def 'Attempt to remove a non-existing entry from the cache.'() {
- when: 'removing an entry that is not cached'
- objectUnderTest.removeMapping('non-cached cmhandle id')
- then: 'deleting from the cmhandle cache returns null'
- assert alternateIdPerCmHandle.remove('non-cached cmhandle id') == null
- and: 'removal from the alternate id cache is skipped'
- 0 * cmHandlePerAlternateId.remove(_)
- }
-
- def 'Cannot update existing alternate id.'() {
- given: 'attempt to update an existing alternate id'
- objectUnderTest.addMapping('my cmhandle id', 'other id')
- expect: 'still returns the original alternate id'
- assert objectUnderTest.cmHandleIdToAlternateId('my cmhandle id') == 'my alternate id'
- and: 'converting other alternate id returns null'
- assert objectUnderTest.alternateIdToCmHandleId('other id') == null
- and: 'a warning is logged with the original alternate id'
- def lastLoggingEvent = logger.list[1]
- assert lastLoggingEvent.level == Level.WARN
- assert lastLoggingEvent.formattedMessage.contains('my alternate id')
- }
-
- def 'Update existing alternate id with the same value.'() {
- expect: 'update an existing alternate id with the same value returns false (no update)'
- assert objectUnderTest.addMapping('my cmhandle id', 'my alternate id') == false
- and: 'conversion still returns the original alternate id'
- assert objectUnderTest.cmHandleIdToAlternateId('my cmhandle id') == 'my alternate id'
- }
-
- def 'Initializing cache #scenario.'() {
- when: 'the cache is (re-)initialized'
- objectUnderTest.cacheIsInitialized = false
- objectUnderTest.initializeCache()
- then: 'the alternate id can be converted to cmhandle id'
- assert objectUnderTest.alternateIdToCmHandleId('alt-1') == convertedCmHandleId
- and: 'the cm handle id can be converted to alternate id'
- assert objectUnderTest.cmHandleIdToAlternateId('ch-1') == convertedAlternatId
- and: 'the query service is called to get the initial data'
- 1 * mockCpsCmHandlerQueryService.getAllCmHandles() >> persistedCmHandles
- where: 'the initial data has a cm handle #scenario'
- scenario | persistedCmHandles || convertedAlternatId | convertedCmHandleId
- 'with alternate id' | [new NcmpServiceCmHandle(cmHandleId: 'ch-1', alternateId: 'alt-1')] || 'alt-1' | 'ch-1'
- 'without alternate id' | [new NcmpServiceCmHandle(cmHandleId: 'ch-1')] || null | null
- 'with blank alternate id' | [new NcmpServiceCmHandle(cmHandleId: 'ch-1', alternateId: ' ')] || null | null
- }
-} \ No newline at end of file