CompositeStateBuilder added for building the compositeState
Added composite state to YangModelCmHandleRetriever
Issue-ID: CPS-878
Signed-off-by: puthuparambil.aditya <aditya.puthuparambil@bell.ca>
Change-Id: I8bdea55c0a8e27a906e24fc367dedf81c9b3501c
Signed-off-by: puthuparambil.aditya <aditya.puthuparambil@bell.ca>
diff --git a/cps-ncmp-service/pom.xml b/cps-ncmp-service/pom.xml
index 573c76e..9467b8f 100644
--- a/cps-ncmp-service/pom.xml
+++ b/cps-ncmp-service/pom.xml
@@ -31,6 +31,9 @@
</parent>
<artifactId>cps-ncmp-service</artifactId>
+ <properties>
+ <minimum-coverage>0.93</minimum-coverage>
+ </properties>
<dependencies>
<dependency>
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/YangModelCmHandleRetriever.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/YangModelCmHandleRetriever.java
index 5063e82..0edd68c 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/YangModelCmHandleRetriever.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/YangModelCmHandleRetriever.java
@@ -1,6 +1,7 @@
/*
* ============LICENSE_START=======================================================
* Copyright (C) 2021-2022 Nordix Foundation
+ * Modifications Copyright (C) 2021 Bell Canada
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,6 +26,8 @@
import lombok.AllArgsConstructor;
import org.onap.cps.api.CpsDataService;
import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
+import org.onap.cps.ncmp.api.inventory.CompositeState;
+import org.onap.cps.ncmp.api.inventory.CompositeStateBuilder;
import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle;
import org.onap.cps.spi.FetchDescendantsOption;
import org.onap.cps.spi.model.DataNode;
@@ -53,7 +56,7 @@
final DataNode cmHandleDataNode = getCmHandleDataNode(cmHandleId);
final NcmpServiceCmHandle ncmpServiceCmHandle = new NcmpServiceCmHandle();
ncmpServiceCmHandle.setCmHandleId(cmHandleId);
- populateCmHandleProperties(cmHandleDataNode, ncmpServiceCmHandle);
+ populateCmHandleDetails(cmHandleDataNode, ncmpServiceCmHandle);
return YangModelCmHandle.toYangModelCmHandle(
(String) cmHandleDataNode.getLeaves().get("dmi-service-name"),
(String) cmHandleDataNode.getLeaves().get("dmi-data-service-name"),
@@ -70,19 +73,24 @@
FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS);
}
- private static void populateCmHandleProperties(final DataNode cmHandleDataNode,
+ private static void populateCmHandleDetails(final DataNode cmHandleDataNode,
final NcmpServiceCmHandle ncmpServiceCmHandle) {
final Map<String, String> dmiProperties = new LinkedHashMap<>();
final Map<String, String> publicProperties = new LinkedHashMap<>();
+ final CompositeStateBuilder compositeStateBuilder = new CompositeStateBuilder();
+ CompositeState compositeState = compositeStateBuilder.build();
for (final DataNode childDataNode: cmHandleDataNode.getChildDataNodes()) {
if (childDataNode.getXpath().contains("/additional-properties[@name=")) {
addProperty(childDataNode, dmiProperties);
} else if (childDataNode.getXpath().contains("/public-properties[@name=")) {
addProperty(childDataNode, publicProperties);
+ } else if (childDataNode.getXpath().endsWith("/state")) {
+ compositeState = compositeStateBuilder.fromDataNode(childDataNode).build();
}
}
ncmpServiceCmHandle.setDmiProperties(dmiProperties);
ncmpServiceCmHandle.setPublicProperties(publicProperties);
+ ncmpServiceCmHandle.setCompositeState(compositeState);
}
private static void addProperty(final DataNode propertyDataNode, final Map<String, String> propertiesAsMap) {
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CompositeStateBuilder.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CompositeStateBuilder.java
new file mode 100644
index 0000000..d8f7080
--- /dev/null
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CompositeStateBuilder.java
@@ -0,0 +1,147 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2022 Bell Canada
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.ncmp.api.inventory;
+
+import org.onap.cps.ncmp.api.inventory.CompositeState.DataStores;
+import org.onap.cps.ncmp.api.inventory.CompositeState.LockReason;
+import org.onap.cps.ncmp.api.inventory.CompositeState.Operational;
+import org.onap.cps.ncmp.api.inventory.CompositeState.Running;
+import org.onap.cps.spi.model.DataNode;
+
+public class CompositeStateBuilder {
+
+ private CmHandleState cmHandleState;
+ private LockReason lockReason;
+ private DataStores datastores;
+ private String lastUpdatedTime;
+
+ /**
+ * To create the {@link CompositeState}.
+ *
+ * @return {@link DataNode}
+ */
+ public CompositeState build() {
+ final CompositeState compositeState = new CompositeState();
+ compositeState.setCmhandleState(cmHandleState);
+ compositeState.setLockReason(lockReason);
+ compositeState.setDataStores(datastores);
+ compositeState.setLastUpdateTime(lastUpdatedTime);
+ return compositeState;
+ }
+
+ /**
+ * To use attributes for creating {@link CompositeState}.
+ *
+ * @param cmHandleState for the data node
+ * @return CompositeStateBuilder
+ */
+ public CompositeStateBuilder withCmHandleState(final CmHandleState cmHandleState) {
+ this.cmHandleState = cmHandleState;
+ return this;
+ }
+
+ /**
+ * To use attributes for creating {@link CompositeState}.
+ *
+ * @param reason for the locked state
+ * @param details for the locked state
+ * @return CompositeStateBuilder
+ */
+ public CompositeStateBuilder withLockReason(final String reason, final String details) {
+ this.lockReason = LockReason.builder().reason(reason).details(details).build();
+ return this;
+ }
+
+ /**
+ * To use attributes for creating {@link CompositeState}.
+ *
+ * @param time for the state change
+ * @return CompositeStateBuilder
+ */
+ public CompositeStateBuilder withLastUpdatedTime(final String time) {
+ this.lastUpdatedTime = time;
+ return this;
+ }
+
+ /**
+ * To use attributes for creating {@link CompositeState}.
+ *
+ * @param syncState for the locked state
+ * @param lastSyncTime for the locked state
+ * @return CompositeStateBuilder
+ */
+ public CompositeStateBuilder withOperationalDataStores(final String syncState, final String lastSyncTime) {
+ this.datastores = DataStores.builder().operationalDataStore(
+ Operational.builder().syncState(syncState).lastSyncTime(lastSyncTime).build()).build();
+ return this;
+ }
+
+ /**
+ * To use attributes for creating {@link CompositeState}.
+ *
+ * @param syncState for the locked state
+ * @param lastSyncTime for the locked state
+ * @return CompositeStateBuilder
+ */
+ public CompositeStateBuilder withRunningDataStores(final String syncState, final String lastSyncTime) {
+ this.datastores = DataStores.builder().runningDataStore(
+ Running.builder().syncState(syncState).lastSyncTime(lastSyncTime).build()).build();
+ return this;
+ }
+
+ /**
+ * To use dataNode for creating {@link CompositeState}.
+ *
+ * @param dataNode for the dataNode
+ * @return CompositeState
+ */
+ public CompositeStateBuilder fromDataNode(final DataNode dataNode) {
+ this.cmHandleState = CmHandleState.valueOf((String) dataNode.getLeaves()
+ .get("cm-handle-state"));
+ for (final DataNode stateChildNode : dataNode.getChildDataNodes()) {
+ if (stateChildNode.getXpath().endsWith("/lock-reason")) {
+ this.lockReason = new LockReason((String) stateChildNode.getLeaves().get("reason"),
+ (String) stateChildNode.getLeaves().get("details"));
+ }
+ if (stateChildNode.getXpath().endsWith("/datastores")) {
+ for (final DataNode dataStoreNodes : stateChildNode.getChildDataNodes()) {
+ Operational operationalDataStore = null;
+ Running runningDataStore = null;
+ if (dataStoreNodes.getXpath().contains("/operational")) {
+ operationalDataStore = Operational.builder()
+ .syncState((String) dataStoreNodes.getLeaves().get("sync-state"))
+ .lastSyncTime((String) dataStoreNodes.getLeaves().get("last-sync-time"))
+ .build();
+ } else {
+ runningDataStore = Running.builder()
+ .syncState((String) dataStoreNodes.getLeaves().get("sync-state"))
+ .lastSyncTime((String) dataStoreNodes.getLeaves().get("last-sync-time"))
+ .build();
+ }
+ this.datastores = DataStores.builder().operationalDataStore(operationalDataStore)
+ .runningDataStore(runningDataStore).build();
+ }
+ }
+ }
+ return this;
+ }
+
+}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/YangModelCmHandleRetrieverSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/YangModelCmHandleRetrieverSpec.groovy
index 5ecc8b0..7fbfa77 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/YangModelCmHandleRetrieverSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/YangModelCmHandleRetrieverSpec.groovy
@@ -22,6 +22,8 @@
import org.onap.cps.api.CpsDataService
import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle
+import org.onap.cps.ncmp.api.inventory.CmHandleState
+import org.onap.cps.ncmp.api.inventory.CompositeStateBuilder
import org.onap.cps.spi.exceptions.DataValidationException
import spock.lang.Shared
@@ -40,6 +42,9 @@
def xpath = "/dmi-registry/cm-handles[@id='some-cm-handle']"
@Shared
+ def compositeState = new CompositeStateBuilder().withCmHandleState(CmHandleState.ADVISED).build()
+
+ @Shared
def childDataNodesForCmHandleWithAllProperties = [new DataNode(xpath: "/dmi-registry/cm-handles[@id='some cm handle']/additional-properties[@name='name1']", leaves: ["name":"name1", "value":"value1"]),
new DataNode(xpath: "/dmi-registry/cm-handles[@id='some cm handle']/public-properties[@name='name2']", leaves: ["name":"name2","value":"value2"])]
@@ -49,6 +54,9 @@
@Shared
def childDataNodesForCmHandleWithPublicProperties = [new DataNode(xpath: "/dmi-registry/cm-handles[@id='some-cm-handle']/public-properties[@name='name2']", leaves: ["name":"name2","value":"value2"])]
+ @Shared
+ def childDataNodesForCmHandleWithState = [new DataNode(xpath: "/dmi-registry/cm-handles[@id='some-cm-handle']/state", leaves: ['cm-handle-state': 'ADVISED'])]
+
def "Retrieve CmHandle using datanode with #scenario."() {
given: 'the cps data service returns a data node from the DMI registry'
def dataNode = new DataNode(childDataNodes:childDataNodes, leaves: leaves)
@@ -63,12 +71,15 @@
and: 'the expected DMI properties'
result.dmiProperties == expectedDmiProperties
result.publicProperties == expectedPublicProperties
+ and: 'the state details are returned'
+ result.compositeState.cmhandleState == expectedCompositeState
where: 'the following parameters are used'
- scenario | childDataNodes || expectedDmiProperties || expectedPublicProperties
- 'no properties' | [] || [] || []
- 'DMI and public properties' | childDataNodesForCmHandleWithAllProperties || [new YangModelCmHandle.Property("name1", "value1")] || [new YangModelCmHandle.Property("name2", "value2")]
- 'just DMI properties' | childDataNodesForCmHandleWithDMIProperties || [new YangModelCmHandle.Property("name1", "value1")] || []
- 'just public properties' | childDataNodesForCmHandleWithPublicProperties || [] || [new YangModelCmHandle.Property("name2", "value2")]
+ scenario | childDataNodes || expectedDmiProperties || expectedPublicProperties || expectedCompositeState
+ 'no properties' | [] || [] || [] || null
+ 'DMI and public properties' | childDataNodesForCmHandleWithAllProperties || [new YangModelCmHandle.Property("name1", "value1")] || [new YangModelCmHandle.Property("name2", "value2")] || null
+ 'just DMI properties' | childDataNodesForCmHandleWithDMIProperties || [new YangModelCmHandle.Property("name1", "value1")] || [] || null
+ 'just public properties' | childDataNodesForCmHandleWithPublicProperties || [] || [new YangModelCmHandle.Property("name2", "value2")] || null
+ 'with state details' | childDataNodesForCmHandleWithState || [] || [] || CmHandleState.ADVISED
}
def "Retrieve CmHandle using datanode with invalid CmHandle id."() {
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/CompositeStateBuilderSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/CompositeStateBuilderSpec.groovy
new file mode 100644
index 0000000..2be5239
--- /dev/null
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/CompositeStateBuilderSpec.groovy
@@ -0,0 +1,65 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2022 Bell Canada
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.ncmp.api.inventory
+
+import org.onap.cps.spi.model.DataNode
+import org.onap.cps.spi.model.DataNodeBuilder
+import spock.lang.Specification
+
+import java.time.OffsetDateTime
+import java.time.ZoneOffset
+import java.time.format.DateTimeFormatter
+
+class CompositeStateBuilderSpec extends Specification {
+
+ def formattedDateAndTime = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
+ .format(OffsetDateTime.of(2022, 12, 31, 20, 30, 40, 1, ZoneOffset.UTC))
+
+ def static cmHandleId = 'myHandle1'
+ def static cmHandleXpath = "/dmi-registry/cm-handles[@id='${cmHandleId}/state']"
+ def static stateDataNodes = [new DataNodeBuilder().withXpath("/dmi-registry/cm-handles[@id='${cmHandleId}']/state/lock-reason")
+ .withLeaves(['reason': 'lock reason', 'details': 'lock details']).build(),
+ new DataNodeBuilder().withXpath("/dmi-registry/cm-handles[@id='${cmHandleId}']/state/datastores")
+ .withChildDataNodes(Arrays.asList(new DataNodeBuilder()
+ .withXpath("/dmi-registry/cm-handles[@id='${cmHandleId}']/state/datastores/operational")
+ .withLeaves(['sync-state': 'UNSYNCHRONIZED']).build())).build()]
+ def static cmHandleDataNode = new DataNode(xpath: cmHandleXpath, childDataNodes: stateDataNodes, leaves: ['cm-handle-state': 'ADVISED'])
+
+ def "Composite State Specification"() {
+ when: 'using composite state builder '
+ def compositeState = new CompositeStateBuilder().withCmHandleState(CmHandleState.ADVISED)
+ .withLockReason("lock-reason","").withOperationalDataStores("UNSYNCHRONIZED",
+ formattedDateAndTime.toString()).withLastUpdatedTime(formattedDateAndTime).build();
+ then: 'it matches expected cm handle state and data store sync state'
+ assert compositeState.getCmhandleState() == CmHandleState.ADVISED
+ assert compositeState.dataStores.operationalDataStore.syncState == 'UNSYNCHRONIZED'
+ }
+
+ def "Build composite state from DataNode "() {
+ given: "a Data Node "
+ def dataNode = new DataNode(leaves: ['cm-handle-state': 'ADVISED'])
+ when: 'build from data node function is invoked'
+ def compositeState = new CompositeStateBuilder().fromDataNode(cmHandleDataNode).build()
+ then: 'it matches expected state model as JSON'
+ assert compositeState.cmhandleState == CmHandleState.ADVISED
+ }
+
+}