}
}
}
+ removeAlternateIdsFromCache(yangModelCmHandles, tobeRemovedCmHandleBatch, notDeletedCmHandles);
}
yangModelCmHandles.removeIf(yangModelCmHandle -> notDeletedCmHandles.contains(yangModelCmHandle.getId()));
updateCmHandleStateBatch(yangModelCmHandles, CmHandleState.DELETED);
- removeAlternateIdsFromCache(yangModelCmHandles);
dmiPluginRegistrationResponse.setRemovedCmHandles(cmHandleRegistrationResponses);
}
ncmpServiceCmHandle.getDmiProperties());
}
- void removeAlternateIdsFromCache(final Collection<YangModelCmHandle> yangModelCmHandles) {
- for (final YangModelCmHandle yangModelCmHandle : yangModelCmHandles) {
+ void removeAlternateIdsFromCache(final Collection<YangModelCmHandle> yangModelCmHandles,
+ final List<String> toBeRemovedCmHandleBatch,
+ final Set<String> cmHandlesIdsToExclude) {
+ final Collection<YangModelCmHandle> removedYangModelCmHandles =
+ yangModelCmHandles.stream()
+ .filter(yangModelCmHandle ->
+ (new HashSet<>(toBeRemovedCmHandleBatch).contains(yangModelCmHandle.getId())
+ && !cmHandlesIdsToExclude.contains(yangModelCmHandle.getId())))
+ .toList();
+ for (final YangModelCmHandle yangModelCmHandle : removedYangModelCmHandles) {
final String cmHandleId = yangModelCmHandle.getId();
final String alternateId = yangModelCmHandle.getAlternateId();
if (StringUtils.isNotBlank(alternateId)) {
import static org.onap.cps.api.parameters.FetchDescendantsOption.OMIT_DESCENDANTS;
import com.google.common.collect.Lists;
+import com.hazelcast.map.IMap;
import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.Collection;
import org.onap.cps.utils.ContentType;
import org.onap.cps.utils.CpsValidator;
import org.onap.cps.utils.JsonObjectMapper;
+import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
@Slf4j
private final CpsModuleService cpsModuleService;
private final CpsValidator cpsValidator;
+ private final IMap<String, String> cmHandleIdPerAlternateId;
/**
* initialize an inventory persistence object.
final JsonObjectMapper jsonObjectMapper,
final CpsAnchorService cpsAnchorService,
final CpsModuleService cpsModuleService,
- final CpsDataService cpsDataService) {
+ final CpsDataService cpsDataService,
+ @Qualifier("cmHandleIdPerAlternateId")
+ final IMap<String, String> cmHandleIdPerAlternateId) {
super(jsonObjectMapper, cpsAnchorService, cpsDataService);
this.cpsModuleService = cpsModuleService;
this.cpsValidator = cpsValidator;
+ this.cmHandleIdPerAlternateId = cmHandleIdPerAlternateId;
}
@Override
@Override
public void saveCmHandleStateBatch(final Map<String, CompositeState> cmHandleStatePerCmHandleId) {
final Map<String, String> cmHandlesJsonDataMap = new HashMap<>();
- cmHandleStatePerCmHandleId.forEach((cmHandleId, compositeState) -> cmHandlesJsonDataMap.put(
- getXPathForCmHandleById(cmHandleId),
- createStateJsonData(jsonObjectMapper.asJsonString(compositeState))));
- cpsDataService.updateDataNodesAndDescendants(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
- cmHandlesJsonDataMap, OffsetDateTime.now(), ContentType.JSON);
+ cmHandleStatePerCmHandleId.forEach((cmHandleId, compositeState) -> {
+ if (exists(cmHandleId)) {
+ cmHandlesJsonDataMap.put(getXPathForCmHandleById(cmHandleId),
+ createStateJsonData(jsonObjectMapper.asJsonString(compositeState)));
+ } else {
+ log.warn("Failure to save state for cmHandle id '{}' as it does not exist in cache", cmHandleId);
+ }
+ });
+ if (!cmHandlesJsonDataMap.isEmpty()) {
+ cpsDataService.updateDataNodesAndDescendants(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
+ cmHandlesJsonDataMap, OffsetDateTime.now(), ContentType.JSON);
+ }
}
@Override
public YangModelCmHandle getYangModelCmHandle(final String cmHandleId) {
cpsValidator.validateNameCharacters(cmHandleId);
final DataNode dataNode =
- getCmHandleDataNodeByCmHandleId(cmHandleId, INCLUDE_ALL_DESCENDANTS).iterator().next();
+ getCmHandleDataNodeByCmHandleId(cmHandleId, INCLUDE_ALL_DESCENDANTS).iterator().next();
return YangDataConverter.toYangModelCmHandle(dataNode);
}
final String moduleRevision) {
cpsValidator.validateNameCharacters(cmHandleId, moduleName);
return cpsModuleService.getModuleDefinitionsByAnchorAndModule(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME,
- cmHandleId, moduleName, moduleRevision);
+ cmHandleId, moduleName, moduleRevision);
}
@Override
}
private Collection<YangModelCmHandle> getYangModelCmHandlesWithDescendantsOption(final Collection<String>
- cmHandleIds,
+ cmHandleIds,
final FetchDescendantsOption
- fetchDescendantsOption) {
+ fetchDescendantsOption) {
final Collection<String> validCmHandleIds = new ArrayList<>(cmHandleIds.size());
cmHandleIds.forEach(cmHandleId -> {
try {
validCmHandleIds.add(cmHandleId);
} catch (final DataValidationException dataValidationException) {
log.error("DataValidationException in CmHandleId {} to be ignored",
- dataValidationException.getMessage());
+ dataValidationException.getMessage());
}
});
return YangDataConverter.toYangModelCmHandles(getCmHandleDataNodes(validCmHandleIds, fetchDescendantsOption));
return this.getDataNodes(xpaths, fetchDescendantsOption);
}
+ private boolean exists(final String cmHandleId) {
+ return cmHandleIdPerAlternateId.containsKey(cmHandleId) || cmHandleIdPerAlternateId.containsValue(cmHandleId);
+ }
+
}
package org.onap.cps.ncmp.impl.inventory
import com.fasterxml.jackson.databind.ObjectMapper
+import com.hazelcast.map.IMap
+
import java.time.OffsetDateTime
import java.time.ZoneOffset
import java.time.format.DateTimeFormatter
def mockCpsValidator = Mock(CpsValidator)
- def objectUnderTest = new InventoryPersistenceImpl(mockCpsValidator, spiedJsonObjectMapper, mockCpsAnchorService, mockCpsModuleService, mockCpsDataService)
+ def mockCmHandleIdPerAlternateId = Mock(IMap)
+
+ def objectUnderTest = new InventoryPersistenceImpl(mockCpsValidator, spiedJsonObjectMapper, mockCpsAnchorService, mockCpsModuleService, mockCpsDataService, mockCmHandleIdPerAlternateId)
def formattedDateAndTime = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
.format(OffsetDateTime.of(2022, 12, 31, 20, 30, 40, 1, ZoneOffset.UTC))
given: 'a map of cm handles composite states'
def compositeState1 = new CompositeState(cmHandleState: cmHandleState, lastUpdateTime: formattedDateAndTime)
def compositeState2 = new CompositeState(cmHandleState: cmHandleState, lastUpdateTime: formattedDateAndTime)
+ and: 'alternate id cache contains the given cm handle reference'
+ mockCmHandleIdPerAlternateId.containsKey(_) >> true
when: 'update cm handle state is invoked with the #scenario state'
def cmHandleStateMap = ['Some-Cm-Handle1' : compositeState1, 'Some-Cm-Handle2' : compositeState2]
objectUnderTest.saveCmHandleStateBatch(cmHandleStateMap)
'DELETING' | CmHandleState.DELETING || ['/dmi-registry/cm-handles[@id=\'Some-Cm-Handle1\']':'{"state":{"cm-handle-state":"DELETING","last-update-time":"2022-12-31T20:30:40.000+0000"}}', '/dmi-registry/cm-handles[@id=\'Some-Cm-Handle2\']':'{"state":{"cm-handle-state":"DELETING","last-update-time":"2022-12-31T20:30:40.000+0000"}}']
}
+ def 'Update cm handle states when #scenario in alternate id cache'() {
+ given: 'a map of cm handles composite states'
+ def compositeState = new CompositeState(cmHandleState: CmHandleState.ADVISED, lastUpdateTime: formattedDateAndTime)
+ def cmHandleStateMap = ['some-cm-handle' : compositeState]
+ and: 'alternate id cache returns #scenario'
+ mockCmHandleIdPerAlternateId.containsKey(_) >> keyExists
+ mockCmHandleIdPerAlternateId.containsValue(_) >> valueExists
+ when: 'we update the state of a cm handle when #scenario'
+ objectUnderTest.saveCmHandleStateBatch(cmHandleStateMap)
+ then: 'update node leaves is invoked correct number of times'
+ expectedCalls * mockCpsDataService.updateDataNodesAndDescendants(*_)
+ where: 'the following cm handle ids are used'
+ scenario | keyExists | valueExists || expectedCalls
+ 'id exists as key' | true | false || 1
+ 'id exists as value'| false | true || 1
+ 'id does not exist' | false | false || 0
+
+ }
+
def 'Getting module definitions by module'() {
given: 'cps module service returns module definition for module name'
def moduleDefinitions = [new ModuleDefinition('moduleName','revision','content')]