lcm:
events:
topic: ${LCM_EVENTS_TOPIC:ncmp-events}
+ event-schema-version: "v1"
dmi:
cm-events:
topic: ${DMI_CM_EVENTS_TOPIC:dmi-cm-events}
"description": "cmHandle id",
"type": "string"
},
- "oldProperties": {
+ "oldValues": {
"description": "the old cmHandle properties(values) that have changed or been deleted",
"type": "object",
"default": null,
"existingJavaType": "java.util.Map<String,Object>",
"additionalProperties": false
},
- "newProperties": {
+ "newValues": {
"description": "cmHandle properties(values) that have been changed or been created",
"type": "object",
"default": null,
+++ /dev/null
-/*
- * ============LICENSE_START=======================================================
- * Copyright (C) 2025-2026 OpenInfra Foundation Europe. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * SPDX-License-Identifier: Apache-2.0
- * ============LICENSE_END=========================================================
- */
-
-package org.onap.cps.ncmp.impl.inventory.sync.lcm;
-
-import com.google.common.collect.MapDifference;
-import com.google.common.collect.Maps;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle;
-import org.onap.cps.ncmp.events.lcm.Values;
-
-/**
- * Utility class for examining and determining changes in CM handle properties.
- */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class CmHandlePropertyChangeDetector {
-
- /**
- * Determines property (update) values for creating a new CM handle.
- *
- * @param ncmpServiceCmHandle the CM handle being created
- * @return CmHandlePropertyUpdates containing new values for the created CM handle
- */
- static CmHandlePropertyUpdates determineUpdatesForCreate(final NcmpServiceCmHandle ncmpServiceCmHandle) {
- final CmHandlePropertyUpdates cmHandlePropertyUpdates = new CmHandlePropertyUpdates();
- cmHandlePropertyUpdates.setNewValues(new Values());
- cmHandlePropertyUpdates.getNewValues().setDataSyncEnabled(getDataSyncEnabledFlag(ncmpServiceCmHandle));
- cmHandlePropertyUpdates.getNewValues()
- .setCmHandleState(mapCmHandleStateToLcmEventCmHandleState(ncmpServiceCmHandle));
- cmHandlePropertyUpdates.getNewValues()
- .setCmHandleProperties(List.of(ncmpServiceCmHandle.getPublicProperties()));
- return cmHandlePropertyUpdates;
- }
-
- /**
- * Determines property updates between current and target CM handle states.
- *
- * @param currentNcmpServiceCmHandle the current CM handle state
- * @param targetNcmpServiceCmHandle the target CM handle state
- * @return CmHandlePropertyUpdates containing old and new values for changed properties
- */
- static CmHandlePropertyUpdates determineUpdates(final NcmpServiceCmHandle currentNcmpServiceCmHandle,
- final NcmpServiceCmHandle targetNcmpServiceCmHandle) {
- final boolean hasDataSyncFlagEnabledChanged =
- hasDataSyncEnabledFlagChanged(currentNcmpServiceCmHandle, targetNcmpServiceCmHandle);
- final boolean hasCmHandleStateChanged =
- hasCmHandleStateChanged(currentNcmpServiceCmHandle, targetNcmpServiceCmHandle);
- final boolean arePublicCmHandlePropertiesEqual =
- arePublicCmHandlePropertiesEqual(currentNcmpServiceCmHandle.getPublicProperties(),
- targetNcmpServiceCmHandle.getPublicProperties()
- );
-
- final CmHandlePropertyUpdates cmHandlePropertyUpdates = new CmHandlePropertyUpdates();
-
- if (hasDataSyncFlagEnabledChanged || hasCmHandleStateChanged || (!arePublicCmHandlePropertiesEqual)) {
- cmHandlePropertyUpdates.setOldValues(new Values());
- cmHandlePropertyUpdates.setNewValues(new Values());
- } else {
- return cmHandlePropertyUpdates;
- }
-
- if (hasDataSyncFlagEnabledChanged) {
- setDataSyncEnabledFlag(currentNcmpServiceCmHandle, targetNcmpServiceCmHandle, cmHandlePropertyUpdates);
- }
-
- if (hasCmHandleStateChanged) {
- setCmHandleStateChange(currentNcmpServiceCmHandle, targetNcmpServiceCmHandle, cmHandlePropertyUpdates);
- }
-
- if (!arePublicCmHandlePropertiesEqual) {
- setPublicCmHandlePropertiesChange(currentNcmpServiceCmHandle, targetNcmpServiceCmHandle,
- cmHandlePropertyUpdates);
- }
-
- return cmHandlePropertyUpdates;
-
- }
-
- private static void setDataSyncEnabledFlag(final NcmpServiceCmHandle currentNcmpServiceCmHandle,
- final NcmpServiceCmHandle targetNcmpServiceCmHandle,
- final CmHandlePropertyUpdates cmHandlePropertyUpdates) {
- cmHandlePropertyUpdates.getOldValues().setDataSyncEnabled(getDataSyncEnabledFlag(currentNcmpServiceCmHandle));
- cmHandlePropertyUpdates.getNewValues().setDataSyncEnabled(getDataSyncEnabledFlag(targetNcmpServiceCmHandle));
-
- }
-
- private static void setCmHandleStateChange(final NcmpServiceCmHandle currentNcmpServiceCmHandle,
- final NcmpServiceCmHandle targetNcmpServiceCmHandle,
- final CmHandlePropertyUpdates cmHandlePropertyUpdates) {
- cmHandlePropertyUpdates.getOldValues()
- .setCmHandleState(mapCmHandleStateToLcmEventCmHandleState(currentNcmpServiceCmHandle));
- cmHandlePropertyUpdates.getNewValues()
- .setCmHandleState(mapCmHandleStateToLcmEventCmHandleState(targetNcmpServiceCmHandle));
- }
-
- private static void setPublicCmHandlePropertiesChange(final NcmpServiceCmHandle currentNcmpServiceCmHandle,
- final NcmpServiceCmHandle targetNcmpServiceCmHandle,
- final CmHandlePropertyUpdates cmHandlePropertyUpdates) {
-
- final Map<String, Map<String, String>> publicCmHandlePropertiesDifference =
- getPublicCmHandlePropertiesDifference(currentNcmpServiceCmHandle.getPublicProperties(),
- targetNcmpServiceCmHandle.getPublicProperties()
- );
- cmHandlePropertyUpdates.getOldValues()
- .setCmHandleProperties(List.of(publicCmHandlePropertiesDifference.get("oldValues")));
- cmHandlePropertyUpdates.getNewValues()
- .setCmHandleProperties(List.of(publicCmHandlePropertiesDifference.get("newValues")));
-
- }
-
- private static Values.CmHandleState mapCmHandleStateToLcmEventCmHandleState(
- final NcmpServiceCmHandle ncmpServiceCmHandle) {
- return Values.CmHandleState.fromValue(ncmpServiceCmHandle.getCompositeState().getCmHandleState().name());
- }
-
- private static Boolean getDataSyncEnabledFlag(final NcmpServiceCmHandle ncmpServiceCmHandle) {
- return ncmpServiceCmHandle.getCompositeState().getDataSyncEnabled();
- }
-
- private static boolean hasDataSyncEnabledFlagChanged(final NcmpServiceCmHandle currentNcmpServiceCmHandle,
- final NcmpServiceCmHandle targetNcmpServiceCmHandle) {
- final Boolean currentDataSyncFlag = currentNcmpServiceCmHandle.getCompositeState().getDataSyncEnabled();
- final Boolean targetDataSyncFlag = targetNcmpServiceCmHandle.getCompositeState().getDataSyncEnabled();
-
- if (targetDataSyncFlag == null) {
- return currentDataSyncFlag != null;
- }
-
- return !targetDataSyncFlag.equals(currentDataSyncFlag);
- }
-
- private static boolean hasCmHandleStateChanged(final NcmpServiceCmHandle currentNcmpServiceCmHandle,
- final NcmpServiceCmHandle targetNcmpServiceCmHandle) {
- return targetNcmpServiceCmHandle.getCompositeState().getCmHandleState()
- != currentNcmpServiceCmHandle.getCompositeState().getCmHandleState();
- }
-
- private static boolean arePublicCmHandlePropertiesEqual(final Map<String, String> currentCmHandleProperties,
- final Map<String, String> targetCmHandleProperties) {
- if (targetCmHandleProperties.size() != currentCmHandleProperties.size()) {
- return false;
- }
- return targetCmHandleProperties.equals(currentCmHandleProperties);
- }
-
- private static Map<String, Map<String, String>> getPublicCmHandlePropertiesDifference(
- final Map<String, String> currentCmHandleProperties,
- final Map<String, String> targetCmHandleProperties) {
- final Map<String, Map<String, String>> oldAndNewPropertiesDifferenceMap = new HashMap<>(2);
-
- final MapDifference<String, String> cmHandlePropertiesDifference =
- Maps.difference(targetCmHandleProperties, currentCmHandleProperties);
-
- final Map<String, String> oldValues = new HashMap<>(cmHandlePropertiesDifference.entriesOnlyOnRight());
- final Map<String, String> newValues = new HashMap<>(cmHandlePropertiesDifference.entriesOnlyOnLeft());
-
- cmHandlePropertiesDifference.entriesDiffering().keySet().forEach(cmHandlePropertyName -> {
- oldValues.put(cmHandlePropertyName, currentCmHandleProperties.get(cmHandlePropertyName));
- newValues.put(cmHandlePropertyName, targetCmHandleProperties.get(cmHandlePropertyName));
- });
-
- oldAndNewPropertiesDifferenceMap.put("oldValues", oldValues);
- oldAndNewPropertiesDifferenceMap.put("newValues", newValues);
-
- return oldAndNewPropertiesDifferenceMap;
- }
-
-}
+++ /dev/null
-/*
- * ============LICENSE_START=======================================================
- * Copyright (C) 2025-2026 OpenInfra Foundation Europe. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * SPDX-License-Identifier: Apache-2.0
- * ============LICENSE_END=========================================================
- */
-
-package org.onap.cps.ncmp.impl.inventory.sync.lcm;
-
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-import org.onap.cps.ncmp.events.lcm.Values;
-
-@NoArgsConstructor
-@Getter
-@Setter
-class CmHandlePropertyUpdates {
- private Values oldValues;
- private Values newValues;
-}
import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle;
import org.onap.cps.ncmp.events.lcm.LcmEventBase;
import org.onap.cps.ncmp.events.lcm.LcmEventV1;
+import org.onap.cps.ncmp.events.lcm.LcmEventV2;
import org.onap.cps.ncmp.events.lcm.PayloadV1;
+import org.onap.cps.ncmp.events.lcm.PayloadV2;
import org.onap.cps.ncmp.impl.utils.EventDateTimeFormatter;
import org.springframework.stereotype.Service;
determineEventType(currentNcmpServiceCmHandle, targetNcmpServiceCmHandle);
final LcmEventV1 lcmEventV1 = new LcmEventV1();
populateHeaderDetails(lcmEventV1, cmHandleId, lcmEventType);
- final PayloadV1 payloadV1 = new PayloadV1();
- payloadV1.setCmHandleId(cmHandleId);
- payloadV1.setAlternateId(targetNcmpServiceCmHandle.getAlternateId());
- payloadV1.setModuleSetTag(targetNcmpServiceCmHandle.getModuleSetTag());
- payloadV1.setDataProducerIdentifier(targetNcmpServiceCmHandle.getDataProducerIdentifier());
- final CmHandlePropertyUpdates cmHandlePropertyUpdates =
- determineEventValues(lcmEventType, currentNcmpServiceCmHandle, targetNcmpServiceCmHandle);
- payloadV1.setOldValues(cmHandlePropertyUpdates.getOldValues());
- payloadV1.setNewValues(cmHandlePropertyUpdates.getNewValues());
+ final PayloadV1 payloadV1 = PayloadFactory.createPayloadV1(lcmEventType, currentNcmpServiceCmHandle,
+ targetNcmpServiceCmHandle);
lcmEventV1.setEvent(payloadV1);
return lcmEventV1;
}
+ /**
+ * Create Lifecycle Management Event Version 2.
+ *
+ * @param currentNcmpServiceCmHandle current ncmp service cmhandle
+ * @param targetNcmpServiceCmHandle target ncmp service cmhandle
+ * @return Populated LcmEvent Version 2
+ */
+ public LcmEventV2 createLcmEventV2(final NcmpServiceCmHandle currentNcmpServiceCmHandle,
+ final NcmpServiceCmHandle targetNcmpServiceCmHandle) {
+ final LcmEventV2 lcmEventV2 = new LcmEventV2();
+ final String cmHandleId = targetNcmpServiceCmHandle.getCmHandleId();
+ final LcmEventType lcmEventType =
+ determineEventType(currentNcmpServiceCmHandle, targetNcmpServiceCmHandle);
+ populateHeaderDetails(lcmEventV2, cmHandleId, lcmEventType);
+ final PayloadV2 payloadV2 = PayloadFactory.createPayloadV2(lcmEventType, currentNcmpServiceCmHandle,
+ targetNcmpServiceCmHandle);
+ lcmEventV2.setEvent(payloadV2);
+ return lcmEventV2;
+ }
+
private static LcmEventType determineEventType(final NcmpServiceCmHandle currentNcmpServiceCmHandle,
final NcmpServiceCmHandle targetNcmpServiceCmHandle) {
-
if (currentNcmpServiceCmHandle.getCompositeState() == null) {
return CREATE;
} else if (targetNcmpServiceCmHandle.getCompositeState().getCmHandleState() == DELETED) {
return UPDATE;
}
- private static CmHandlePropertyUpdates determineEventValues(final LcmEventType lcmEventType,
- final NcmpServiceCmHandle currentNcmpServiceCmHandle,
- final NcmpServiceCmHandle targetNcmpServiceCmHandle) {
- if (CREATE == lcmEventType) {
- return CmHandlePropertyChangeDetector.determineUpdatesForCreate(targetNcmpServiceCmHandle);
- }
- if (UPDATE == lcmEventType) {
- return CmHandlePropertyChangeDetector.determineUpdates(currentNcmpServiceCmHandle,
- targetNcmpServiceCmHandle);
- }
- return new CmHandlePropertyUpdates();
- }
-
private void populateHeaderDetails(final LcmEventBase lcmEventBase,
final String eventCorrelationId,
final LcmEventType lcmEventType) {
import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle;
import org.onap.cps.ncmp.events.lcm.LcmEventBase;
import org.onap.cps.ncmp.events.lcm.LcmEventV1;
+import org.onap.cps.ncmp.events.lcm.LcmEventV2;
+import org.onap.cps.ncmp.events.lcm.PayloadV1;
+import org.onap.cps.ncmp.events.lcm.PayloadV2;
import org.onap.cps.ncmp.events.lcm.Values;
import org.onap.cps.ncmp.impl.utils.YangDataConverter;
import org.springframework.beans.factory.annotation.Value;
@Value("${app.lcm.events.topic:ncmp-events}")
private String topicName;
+ @Value("${app.lcm.events.event-schema-version:v1}")
+ private String eventSchemaVersion;
+
@Value("${notification.enabled:true}")
private boolean notificationsEnabled;
private void sendLcmEvent(final NcmpServiceCmHandle currentNcmpServiceCmHandle,
final NcmpServiceCmHandle targetNcmpServiceCmHandle) {
if (notificationsEnabled) {
- final LcmEventV1 lcmEventV1 = lcmEventObjectCreator.createLcmEventV1(currentNcmpServiceCmHandle,
- targetNcmpServiceCmHandle);
final Timer.Sample timerSample = Timer.start(meterRegistry);
+ final LcmEventBase lcmEvent;
+ if (useSchemaV2()) {
+ lcmEvent = lcmEventObjectCreator.createLcmEventV2(currentNcmpServiceCmHandle,
+ targetNcmpServiceCmHandle);
+ } else {
+ lcmEvent = lcmEventObjectCreator.createLcmEventV1(currentNcmpServiceCmHandle,
+ targetNcmpServiceCmHandle);
+ }
try {
- final Map<String, Object> headersAsMap = extractHeadersAsMap(lcmEventV1);
+ final Map<String, Object> headersAsMap = extractHeadersAsMap(lcmEvent);
final String eventKey = currentNcmpServiceCmHandle.getCmHandleId();
- eventProducer.sendLegacyEvent(topicName, eventKey, headersAsMap, lcmEventV1);
- recordMetrics(lcmEventV1, timerSample);
+ eventProducer.sendLegacyEvent(topicName, eventKey, headersAsMap, lcmEvent);
+ recordMetrics(lcmEvent, timerSample);
} catch (final KafkaException e) {
log.error("Unable to send message to topic : {} and cause : {}", topicName, e.getMessage());
}
return headersAsMap;
}
- private void recordMetrics(final LcmEventV1 lcmEventV1, final Timer.Sample timerSample) {
+ private void recordMetrics(final LcmEventBase lcmEvent, final Timer.Sample timerSample) {
final List<Tag> tags = new ArrayList<>(4);
tags.add(METRIC_TAG_CLASS);
tags.add(METRIC_TAG_METHOD);
- tags.add(createCmHandleStateTag("oldCmHandleState", lcmEventV1.getEvent().getOldValues()));
- tags.add(createCmHandleStateTag("newCmHandleState", lcmEventV1.getEvent().getNewValues()));
+ if (lcmEvent instanceof LcmEventV2) {
+ final PayloadV2 payloadV2 = ((LcmEventV2) lcmEvent).getEvent();
+ tags.add(createCmHandleStateTagForV2("oldCmHandleState", payloadV2.getOldValues()));
+ tags.add(createCmHandleStateTagForV2("newCmHandleState", payloadV2.getNewValues()));
+ } else {
+ final PayloadV1 payloadV1 = ((LcmEventV1) lcmEvent).getEvent();
+ tags.add(createCmHandleStateTagForV1("oldCmHandleState", payloadV1.getOldValues()));
+ tags.add(createCmHandleStateTagForV1("newCmHandleState", payloadV1.getNewValues()));
+ }
timerSample.stop(Timer.builder("cps.ncmp.lcm.events.send")
.description("Time taken to send a LCM event")
.tags(tags)
.register(meterRegistry));
}
- private Tag createCmHandleStateTag(final String tagLabel, final Values values) {
+ private Tag createCmHandleStateTagForV1(final String tagLabel, final Values values) {
if (values == null) {
return Tag.of(tagLabel, "N/A");
}
return Tag.of(tagLabel, values.getCmHandleState().value());
}
+ private Tag createCmHandleStateTagForV2(final String tagLabel, final Map<String, Object> properties) {
+ if (properties == null || !properties.containsKey("cmHandleState")) {
+ return Tag.of(tagLabel, "N/A");
+ }
+ return Tag.of(tagLabel, properties.get("cmHandleState").toString());
+ }
+
+ private boolean useSchemaV2() {
+ return "v2".equals(eventSchemaVersion);
+ }
+
}
--- /dev/null
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2025-2026 OpenInfra Foundation Europe. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.ncmp.impl.inventory.sync.lcm;
+
+import com.google.common.collect.MapDifference;
+import com.google.common.collect.Maps;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.onap.cps.ncmp.api.inventory.models.CmHandleState;
+import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle;
+import org.onap.cps.ncmp.events.lcm.PayloadV1;
+import org.onap.cps.ncmp.events.lcm.PayloadV2;
+import org.onap.cps.ncmp.events.lcm.Values;
+
+/**
+ * Utility class for examining and identifying changes in CM handle properties.
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class PayloadFactory {
+
+ static PayloadV1 createPayloadV1(final LcmEventType lcmEventType,
+ final NcmpServiceCmHandle currentNcmpServiceCmHandle,
+ final NcmpServiceCmHandle targetNcmpServiceCmHandle) {
+ final PayloadV2 payloadV2 = createPayloadV2(lcmEventType, currentNcmpServiceCmHandle,
+ targetNcmpServiceCmHandle);
+ final PayloadV1 payloadV1 = toV1Format(payloadV2);
+ payloadV1.setAlternateId(targetNcmpServiceCmHandle.getAlternateId());
+ payloadV1.setModuleSetTag(targetNcmpServiceCmHandle.getModuleSetTag());
+ payloadV1.setDataProducerIdentifier(targetNcmpServiceCmHandle.getDataProducerIdentifier());
+ return payloadV1;
+ }
+
+ static PayloadV2 createPayloadV2(final LcmEventType lcmEventType,
+ final NcmpServiceCmHandle currentNcmpServiceCmHandle,
+ final NcmpServiceCmHandle targetNcmpServiceCmHandle) {
+ final PayloadV2 payloadV2 = switch (lcmEventType) {
+ case CREATE -> getPayLoadForCreate(targetNcmpServiceCmHandle);
+ case UPDATE -> identifyChanges(currentNcmpServiceCmHandle, targetNcmpServiceCmHandle);
+ default -> new PayloadV2();
+ };
+ payloadV2.setCmHandleId(targetNcmpServiceCmHandle.getCmHandleId());
+ return payloadV2;
+ }
+
+ static PayloadV2 getPayLoadForCreate(final NcmpServiceCmHandle ncmpServiceCmHandle) {
+ final PayloadV2 payload = new PayloadV2();
+ final Map<String, Object> newProperties = new HashMap<>();
+ newProperties.put("dataSyncEnabled", ncmpServiceCmHandle.getCompositeState().getDataSyncEnabled());
+ newProperties.put("cmHandleState", ncmpServiceCmHandle.getCompositeState().getCmHandleState().name());
+ newProperties.putAll(ncmpServiceCmHandle.getPublicProperties());
+ payload.setNewValues(newProperties);
+ return payload;
+ }
+
+ static PayloadV2 identifyChanges(final NcmpServiceCmHandle currentNcmpServiceCmHandle,
+ final NcmpServiceCmHandle targetNcmpServiceCmHandle) {
+ final Boolean currentDataSync = currentNcmpServiceCmHandle.getCompositeState().getDataSyncEnabled();
+ final Boolean targetDataSync = targetNcmpServiceCmHandle.getCompositeState().getDataSyncEnabled();
+ final boolean dataSyncEnabledChanged = !Objects.equals(currentDataSync, targetDataSync);
+
+ final CmHandleState currentCmHandleState = currentNcmpServiceCmHandle.getCompositeState().getCmHandleState();
+ final CmHandleState targetCmHandleState = targetNcmpServiceCmHandle.getCompositeState().getCmHandleState();
+ final boolean cmHandleStateChanged = !Objects.equals(currentCmHandleState, targetCmHandleState);
+
+ final Map<String, String> currentPublicProperties = currentNcmpServiceCmHandle.getPublicProperties();
+ final Map<String, String> targetPublicProperties = targetNcmpServiceCmHandle.getPublicProperties();
+ final boolean publicPropertiesChanged = !Objects.equals(currentPublicProperties, targetPublicProperties);
+
+ final PayloadV2 payload = new PayloadV2();
+ if (!dataSyncEnabledChanged && !cmHandleStateChanged && !publicPropertiesChanged) {
+ return payload;
+ }
+
+ final Map<String, Object> oldProperties = new HashMap<>();
+ final Map<String, Object> newProperties = new HashMap<>();
+
+ if (dataSyncEnabledChanged) {
+ oldProperties.put("dataSyncEnabled", currentDataSync);
+ newProperties.put("dataSyncEnabled", targetDataSync);
+ }
+
+ if (cmHandleStateChanged) {
+ oldProperties.put("cmHandleState",
+ currentNcmpServiceCmHandle.getCompositeState().getCmHandleState().name());
+ newProperties.put("cmHandleState",
+ targetNcmpServiceCmHandle.getCompositeState().getCmHandleState().name());
+ }
+
+ if (publicPropertiesChanged) {
+ final MapDifference<String, String> mapDifference = Maps.difference(
+ targetNcmpServiceCmHandle.getPublicProperties(),
+ currentNcmpServiceCmHandle.getPublicProperties());
+
+ oldProperties.putAll(mapDifference.entriesOnlyOnRight());
+ newProperties.putAll(mapDifference.entriesOnlyOnLeft());
+
+ mapDifference.entriesDiffering().forEach((key, valueDifference) -> {
+ oldProperties.put(key, valueDifference.rightValue());
+ newProperties.put(key, valueDifference.leftValue());
+ });
+ }
+ payload.setOldValues(oldProperties);
+ payload.setNewValues(newProperties);
+ return payload;
+ }
+
+ private static PayloadV1 toV1Format(final PayloadV2 payloadV2) {
+ final PayloadV1 payloadV1 = new PayloadV1();
+ payloadV1.setCmHandleId(payloadV2.getCmHandleId());
+ if (payloadV2.getOldValues() != null) {
+ payloadV1.setOldValues(mapToValues(payloadV2.getOldValues()));
+ }
+ if (payloadV2.getNewValues() != null) {
+ payloadV1.setNewValues(mapToValues(payloadV2.getNewValues()));
+ }
+ return payloadV1;
+ }
+
+ private static Values mapToValues(final Map<String, Object> properties) {
+ final Values values = new Values();
+ if (properties.containsKey("dataSyncEnabled")) {
+ values.setDataSyncEnabled((Boolean) properties.get("dataSyncEnabled"));
+ }
+ if (properties.containsKey("cmHandleState")) {
+ values.setCmHandleState(Values.CmHandleState.fromValue((String) properties.get("cmHandleState")));
+ }
+ final Map<String, String> publicProperties = new HashMap<>();
+ properties.forEach((key, value) -> {
+ if (!"dataSyncEnabled".equals(key) && !"cmHandleState".equals(key)) {
+ publicProperties.put(key, (String) value);
+ }
+ });
+ if (!publicProperties.isEmpty()) {
+ values.setCmHandleProperties(List.of(publicProperties));
+ }
+ return values;
+ }
+
+}
new YangModelCmHandle(id: 'ch-1', compositeState: new CompositeState(cmHandleState: ADVISED), additionalProperties: [], publicProperties: [])
)
- def 'Create and send lcm event where notifications are #scenario.'() {
+ def 'Create and send lcm event #eventVersion where notifications are #scenario.'() {
given: 'notificationsEnabled is #notificationsEnabled'
objectUnderTest.notificationsEnabled = notificationsEnabled
+ objectUnderTest.eventSchemaVersion = eventVersion
when: 'event send for (batch of) 1 cm handle transition pair (new cm handle going to READY)'
objectUnderTest.sendLcmEventBatchAsynchronously([cmHandleTransitionPair])
then: 'producer is called #expectedTimesMethodCalled times with correct identifiers'
expectedTimesMethodCalled * mockEventProducer.sendLegacyEvent(_, 'ch-1', _, _) >> {
args -> {
def eventHeaders = args[2]
+ def event = args[3]
assert UUID.fromString(eventHeaders.get('eventId')) != null
assert eventHeaders.get('eventCorrelationId') == 'ch-1'
+ assert event.class.simpleName == expectedEventClass
}
}
and: 'metrics are recorded with correct tags'
assert timer == null
}
where: 'the following values are used'
- scenario | notificationsEnabled || expectedTimesMethodCalled
- 'enabled' | true || 1
- 'disabled' | false || 0
+ scenario | eventVersion | notificationsEnabled || expectedTimesMethodCalled | expectedEventClass
+ 'enabled' | 'v1' | true || 1 | 'LcmEventV1'
+ 'enabled' | 'v2' | true || 1 | 'LcmEventV2'
+ 'disabled' | 'v1' | false || 0 | 'N/A'
}
def 'Exception while sending message.'(){
import org.onap.cps.ncmp.events.lcm.Values
import spock.lang.Specification
-class CmHandlePropertyChangeDetectorSpec extends Specification {
-
- def 'Determine updates for create operation.'() {
+class PayloadFactorySpec extends Specification {
+ def 'Create payload for create operation.'() {
given: 'a new cm handle'
- def ncmpServiceCmHandle = new NcmpServiceCmHandle(
+ def ncmpServiceCmHandle = new NcmpServiceCmHandle(cmHandleId: 'ch',
compositeState: new CompositeState(dataSyncEnabled: true, cmHandleState: CmHandleState.READY),
publicProperties: ['prop1': 'value1']
)
- when: 'updates are determined for create'
- def result = CmHandlePropertyChangeDetector.determineUpdatesForCreate(ncmpServiceCmHandle)
+ when: 'payload is created for create'
+ def result = PayloadFactory.createPayloadV1(LcmEventType.CREATE, null, ncmpServiceCmHandle)
then: 'new values are populated'
+ assert result.cmHandleId == 'ch'
assert result.newValues.dataSyncEnabled == true
assert result.newValues.cmHandleState == Values.CmHandleState.READY
assert result.newValues.cmHandleProperties == [['prop1': 'value1']]
assert result.oldValues == null
}
- def 'Determine updates when no changes detected.'() {
+ def 'Create payload when no changes detected.'() {
given: 'current and target cm handles with same properties'
def currentCmHandle = new NcmpServiceCmHandle(
compositeState: new CompositeState(dataSyncEnabled: true, cmHandleState: CmHandleState.READY),
publicProperties: ['prop1': 'value1']
)
- def targetCmHandle = new NcmpServiceCmHandle(
+ def targetCmHandle = new NcmpServiceCmHandle(cmHandleId: 'ch',
compositeState: new CompositeState(dataSyncEnabled: true, cmHandleState: CmHandleState.READY),
publicProperties: ['prop1': 'value1']
)
- when: 'updates are determined'
- def result = CmHandlePropertyChangeDetector.determineUpdates(currentCmHandle, targetCmHandle)
+ when: 'payload is created'
+ def result = PayloadFactory.createPayloadV1(LcmEventType.UPDATE, currentCmHandle, targetCmHandle)
then: 'no updates are detected'
+ assert result.cmHandleId == 'ch'
assert result.oldValues == null
assert result.newValues == null
}
- def 'Determine updates when data sync flag changes.'() {
+ def 'Create payload when data sync flag changes.'() {
given: 'current and target cm handles with different data sync flags'
def currentCmHandle = new NcmpServiceCmHandle(
compositeState: new CompositeState(dataSyncEnabled: false, cmHandleState: CmHandleState.READY),
compositeState: new CompositeState(dataSyncEnabled: true, cmHandleState: CmHandleState.READY),
publicProperties: [:]
)
- when: 'updates are determined'
- def result = CmHandlePropertyChangeDetector.determineUpdates(currentCmHandle, targetCmHandle)
+ when: 'payload is created'
+ def result = PayloadFactory.createPayloadV1(LcmEventType.UPDATE,currentCmHandle, targetCmHandle)
then: 'data sync flag change is detected'
assert result.oldValues.dataSyncEnabled == false
assert result.newValues.dataSyncEnabled == true
}
- def 'Determine updates when cm handle state changes.'() {
+ def 'Create payload when cm handle state changes.'() {
given: 'current and target cm handles with different states'
def currentCmHandle = new NcmpServiceCmHandle(
compositeState: new CompositeState(dataSyncEnabled: true, cmHandleState: CmHandleState.ADVISED),
compositeState: new CompositeState(dataSyncEnabled: true, cmHandleState: CmHandleState.READY),
publicProperties: [:]
)
- when: 'updates are determined'
- def result = CmHandlePropertyChangeDetector.determineUpdates(currentCmHandle, targetCmHandle)
+ when: 'payload is created'
+ def result = PayloadFactory.createPayloadV1(LcmEventType.UPDATE,currentCmHandle, targetCmHandle)
then: 'state change is detected'
assert result.oldValues.cmHandleState == Values.CmHandleState.ADVISED
assert result.newValues.cmHandleState == Values.CmHandleState.READY
}
- def 'Determine updates when public properties change.'() {
+ def 'Create payload when public properties change.'() {
given: 'current and target cm handles with different properties'
def currentCmHandle = new NcmpServiceCmHandle(
compositeState: new CompositeState(dataSyncEnabled: true, cmHandleState: CmHandleState.READY),
- publicProperties: ['prop1': 'value1', 'prop2': 'value2', 'unchanged': 'sameValue']
+ publicProperties: ['prop1': 'old value', 'prop2': 'to be deleted', 'prop4': 'unchanged']
)
def targetCmHandle = new NcmpServiceCmHandle(
compositeState: new CompositeState(dataSyncEnabled: true, cmHandleState: CmHandleState.READY),
- publicProperties: ['prop1': 'newValue1', 'prop3': 'value3', 'unchanged': 'sameValue']
+ publicProperties: ['prop1': 'new value', 'prop3': 'new', 'prop4': 'unchanged']
)
- when: 'updates are determined'
- def result = CmHandlePropertyChangeDetector.determineUpdates(currentCmHandle, targetCmHandle)
+ when: 'payload is created'
+ def result = PayloadFactory.createPayloadV1(LcmEventType.UPDATE,currentCmHandle, targetCmHandle)
then: 'property changes are detected'
- assert result.oldValues.cmHandleProperties[0]['prop1'] == 'value1'
- assert result.oldValues.cmHandleProperties[0]['prop2'] == 'value2'
- assert result.newValues.cmHandleProperties[0]['prop1'] == 'newValue1'
- assert result.newValues.cmHandleProperties[0]['prop3'] == 'value3'
+ assert result.oldValues.cmHandleProperties[0]['prop1'] == 'old value'
+ assert result.oldValues.cmHandleProperties[0]['prop2'] == 'to be deleted'
+ assert result.newValues.cmHandleProperties[0]['prop1'] == 'new value'
+ assert result.newValues.cmHandleProperties[0]['prop3'] == 'new'
and: 'unchanged property is not included in the result'
- assert !result.oldValues.cmHandleProperties[0].containsKey('unchanged')
- assert !result.newValues.cmHandleProperties[0].containsKey('unchanged')
+ assert !result.oldValues.cmHandleProperties[0].containsKey('prop4')
+ assert !result.newValues.cmHandleProperties[0].containsKey('prop4')
}
- def 'Determine updates when multiple changes occur.'() {
+ def 'Create payload when multiple changes occur.'() {
given: 'current and target cm handles with multiple differences'
def currentCmHandle = new NcmpServiceCmHandle(
compositeState: new CompositeState(dataSyncEnabled: false, cmHandleState: CmHandleState.ADVISED),
compositeState: new CompositeState(dataSyncEnabled: true, cmHandleState: CmHandleState.READY),
publicProperties: ['prop1': 'newValue1']
)
- when: 'updates are determined'
- def result = CmHandlePropertyChangeDetector.determineUpdates(currentCmHandle, targetCmHandle)
+ when: 'payload is created'
+ def result = PayloadFactory.createPayloadV1(LcmEventType.UPDATE,currentCmHandle, targetCmHandle)
then: 'all changes are detected'
assert result.oldValues.dataSyncEnabled == false
assert result.newValues.dataSyncEnabled == true
assert result.oldValues.cmHandleProperties[0]['prop1'] == 'value1'
assert result.newValues.cmHandleProperties[0]['prop1'] == 'newValue1'
}
+
+ def 'Create payload for delete operation.'() {
+ given: 'a cm handle being deleted'
+ def currentCmHandle = new NcmpServiceCmHandle(
+ compositeState: new CompositeState(dataSyncEnabled: true, cmHandleState: CmHandleState.READY),
+ publicProperties: ['prop1': 'value1']
+ )
+ def targetCmHandle = new NcmpServiceCmHandle(cmHandleId: 'ch',
+ compositeState: new CompositeState(dataSyncEnabled: false, cmHandleState: CmHandleState.DELETED),
+ publicProperties: ['prop1': 'value1']
+ )
+ when: 'payload is created for delete'
+ def result = PayloadFactory.createPayloadV1(LcmEventType.DELETE, currentCmHandle, targetCmHandle)
+ then: 'cmHandleId is populated'
+ assert result.cmHandleId == 'ch'
+ and: 'no values are populated'
+ assert result.oldValues == null
+ assert result.newValues == null
+ }
}