Merge "Add module name to cps core output"
diff --git a/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java b/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java
index ded234b..4dbbfd2 100644
--- a/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java
+++ b/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java
@@ -48,6 +48,8 @@
 import org.onap.cps.spi.entities.AnchorEntity;
 import org.onap.cps.spi.entities.DataspaceEntity;
 import org.onap.cps.spi.entities.FragmentEntity;
+import org.onap.cps.spi.entities.SchemaSetEntity;
+import org.onap.cps.spi.entities.YangResourceEntity;
 import org.onap.cps.spi.exceptions.AlreadyDefinedException;
 import org.onap.cps.spi.exceptions.ConcurrencyException;
 import org.onap.cps.spi.exceptions.CpsAdminException;
@@ -60,6 +62,8 @@
 import org.onap.cps.spi.repository.FragmentRepository;
 import org.onap.cps.spi.utils.SessionManager;
 import org.onap.cps.utils.JsonObjectMapper;
+import org.onap.cps.yang.YangTextSchemaSourceSetBuilder;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.springframework.dao.DataIntegrityViolationException;
 import org.springframework.stereotype.Service;
 
@@ -242,16 +246,27 @@
     }
 
     private DataNode toDataNode(final FragmentEntity fragmentEntity,
-        final FetchDescendantsOption fetchDescendantsOption) {
+                                final FetchDescendantsOption fetchDescendantsOption) {
         final List<DataNode> childDataNodes = getChildDataNodes(fragmentEntity, fetchDescendantsOption);
         Map<String, Object> leaves = new HashMap<>();
         if (fragmentEntity.getAttributes() != null) {
             leaves = jsonObjectMapper.convertJsonString(fragmentEntity.getAttributes(), Map.class);
         }
         return new DataNodeBuilder()
-            .withXpath(fragmentEntity.getXpath())
-            .withLeaves(leaves)
-            .withChildDataNodes(childDataNodes).build();
+                .withModuleNamePrefix(getFirstModuleName(fragmentEntity))
+                .withXpath(fragmentEntity.getXpath())
+                .withLeaves(leaves)
+                .withChildDataNodes(childDataNodes).build();
+    }
+
+    private String getFirstModuleName(final FragmentEntity fragmentEntity) {
+        final SchemaSetEntity schemaSetEntity = fragmentEntity.getAnchor().getSchemaSet();
+        final Map<String, String> yangResourceNameToContent =
+                schemaSetEntity.getYangResources().stream().collect(
+                        Collectors.toMap(YangResourceEntity::getName, YangResourceEntity::getContent));
+        final SchemaContext schemaContext = YangTextSchemaSourceSetBuilder.of(yangResourceNameToContent)
+                .getSchemaContext();
+        return schemaContext.getModules().iterator().next().getName();
     }
 
     private List<DataNode> getChildDataNodes(final FragmentEntity fragmentEntity,
diff --git a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceSpec.groovy b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceSpec.groovy
index a96b6af..bb80199 100644
--- a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceSpec.groovy
+++ b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceSpec.groovy
@@ -22,7 +22,11 @@
 import com.fasterxml.jackson.databind.ObjectMapper
 import org.hibernate.StaleStateException
 import org.onap.cps.spi.FetchDescendantsOption
+import org.onap.cps.spi.entities.AnchorEntity
+import org.onap.cps.spi.entities.DataspaceEntity
 import org.onap.cps.spi.entities.FragmentEntity
+import org.onap.cps.spi.entities.SchemaSetEntity
+import org.onap.cps.spi.entities.YangResourceEntity
 import org.onap.cps.spi.exceptions.ConcurrencyException
 import org.onap.cps.spi.exceptions.DataValidationException
 import org.onap.cps.spi.model.DataNodeBuilder
@@ -31,6 +35,10 @@
 import org.onap.cps.spi.repository.FragmentRepository
 import org.onap.cps.spi.utils.SessionManager
 import org.onap.cps.utils.JsonObjectMapper
+import org.onap.cps.yang.YangTextSchemaSourceSet
+import org.onap.cps.yang.YangTextSchemaSourceSetBuilder
+import org.opendaylight.yangtools.yang.model.api.SchemaContext
+import spock.lang.Shared
 import spock.lang.Specification
 
 class CpsDataPersistenceServiceSpec extends Specification {
@@ -44,6 +52,25 @@
     def objectUnderTest = new CpsDataPersistenceServiceImpl(
             mockDataspaceRepository, mockAnchorRepository, mockFragmentRepository, jsonObjectMapper,mockSessionManager)
 
+    @Shared
+    def NEW_RESOURCE_CONTENT = 'module stores {\n' +
+            '    yang-version 1.1;\n' +
+            '    namespace "org:onap:ccsdk:sample";\n' +
+            '\n' +
+            '    prefix book-store;\n' +
+            '\n' +
+            '    revision "2020-09-15" {\n' +
+            '        description\n' +
+            '        "Sample Model";\n' +
+            '    }' +
+            '}'
+
+    @Shared
+    def yangResourceSet = [new YangResourceEntity(moduleName: 'moduleName', content: NEW_RESOURCE_CONTENT,
+            name: 'sampleYangResource'
+    )] as Set
+
+
     def 'Handling of StaleStateException (caused by concurrent updates) during data node tree update.'() {
 
         def parentXpath = '/parent-01'
@@ -51,67 +78,68 @@
         def myAnchorName = 'my-anchor'
 
         given: 'data node object'
-        def submittedDataNode = new DataNodeBuilder()
-                .withXpath(parentXpath)
-                .withLeaves(['leaf-name': 'leaf-value'])
-                .build()
+            def submittedDataNode = new DataNodeBuilder()
+                    .withXpath(parentXpath)
+                    .withLeaves(['leaf-name': 'leaf-value'])
+                    .build()
         and: 'fragment to be updated'
-        mockFragmentRepository.getByDataspaceAndAnchorAndXpath(_, _, _) >> {
-            def fragmentEntity = new FragmentEntity()
-            fragmentEntity.setXpath(parentXpath)
-            fragmentEntity.setChildFragments(Collections.emptySet())
-            return fragmentEntity
-        }
+            mockFragmentRepository.getByDataspaceAndAnchorAndXpath(_, _, _) >> {
+                def fragmentEntity = new FragmentEntity()
+                fragmentEntity.setXpath(parentXpath)
+                fragmentEntity.setChildFragments(Collections.emptySet())
+                return fragmentEntity
+            }
         and: 'data node is concurrently updated by another transaction'
-        mockFragmentRepository.save(_) >> { throw new StaleStateException("concurrent updates") }
+            mockFragmentRepository.save(_) >> { throw new StaleStateException("concurrent updates") }
 
         when: 'attempt to update data node'
-        objectUnderTest.replaceDataNodeTree(myDataspaceName, myAnchorName, submittedDataNode)
+            objectUnderTest.replaceDataNodeTree(myDataspaceName, myAnchorName, submittedDataNode)
 
         then: 'concurrency exception is thrown'
-        def concurrencyException = thrown(ConcurrencyException)
-        assert concurrencyException.getDetails().contains(myDataspaceName)
-        assert concurrencyException.getDetails().contains(myAnchorName)
-        assert concurrencyException.getDetails().contains(parentXpath)
+            def concurrencyException = thrown(ConcurrencyException)
+            assert concurrencyException.getDetails().contains(myDataspaceName)
+            assert concurrencyException.getDetails().contains(myAnchorName)
+            assert concurrencyException.getDetails().contains(parentXpath)
     }
 
     def 'Retrieving a data node with a property JSON value of #scenario'() {
         given: 'a fragment with a property JSON value of #scenario'
         mockFragmentRepository.getByDataspaceAndAnchorAndXpath(_, _, _) >> {
             new FragmentEntity(childFragments: Collections.emptySet(),
-                    attributes: "{\"some attribute\": ${dataString}}")
+                    attributes: "{\"some attribute\": ${dataString}}",
+                    anchor: new AnchorEntity(schemaSet: new SchemaSetEntity(yangResources: yangResourceSet )))
         }
         when: 'getting the data node represented by this fragment'
-        def dataNode = objectUnderTest.getDataNode('my-dataspace', 'my-anchor',
-                '/parent-01', FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS)
+            def dataNode = objectUnderTest.getDataNode('my-dataspace', 'my-anchor',
+                    '/parent-01', FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS)
         then: 'the leaf is of the correct value and data type'
-        def attributeValue = dataNode.leaves.get('some attribute')
-        assert attributeValue == expectedValue
-        assert attributeValue.class == expectedDataClass
+            def attributeValue = dataNode.leaves.get('some attribute')
+            assert attributeValue == expectedValue
+            assert attributeValue.class == expectedDataClass
         where: 'the following Data Type is passed'
-        scenario                              | dataString            || expectedValue     | expectedDataClass
-        'just numbers'                        | '15174'               || 15174             | Integer
-        'number with dot'                     | '15174.32'            || 15174.32          | Double
-        'number with 0 value after dot'       | '15174.0'             || 15174.0           | Double
-        'number with 0 value before dot'      | '0.32'                || 0.32              | Double
-        'number higher than max int'          | '2147483648'          || 2147483648        | Long
-        'just text'                           | '"Test"'              || 'Test'            | String
-        'number with exponent'                | '1.2345e5'            || 1.2345e5          | Double
-        'number higher than max int with dot' | '123456789101112.0'   || 123456789101112.0 | Double
-        'text and numbers'                    | '"String = \'1234\'"' || "String = '1234'" | String
-        'number as String'                    | '"12345"'             || '12345'           | String
+            scenario                              | dataString            || expectedValue     | expectedDataClass
+            'just numbers'                        | '15174'               || 15174             | Integer
+            'number with dot'                     | '15174.32'            || 15174.32          | Double
+            'number with 0 value after dot'       | '15174.0'             || 15174.0           | Double
+            'number with 0 value before dot'      | '0.32'                || 0.32              | Double
+            'number higher than max int'          | '2147483648'          || 2147483648        | Long
+            'just text'                           | '"Test"'              || 'Test'            | String
+            'number with exponent'                | '1.2345e5'            || 1.2345e5          | Double
+            'number higher than max int with dot' | '123456789101112.0'   || 123456789101112.0 | Double
+            'text and numbers'                    | '"String = \'1234\'"' || "String = '1234'" | String
+            'number as String'                    | '"12345"'             || '12345'           | String
     }
 
     def 'Retrieving a data node with invalid JSON'() {
         given: 'a fragment with invalid JSON'
-        mockFragmentRepository.getByDataspaceAndAnchorAndXpath(_, _, _) >> {
-            new FragmentEntity(childFragments: Collections.emptySet(), attributes: '{invalid json')
-        }
+            mockFragmentRepository.getByDataspaceAndAnchorAndXpath(_, _, _) >> {
+                new FragmentEntity(childFragments: Collections.emptySet(), attributes: '{invalid json')
+            }
         when: 'getting the data node represented by this fragment'
-        def dataNode = objectUnderTest.getDataNode('my-dataspace', 'my-anchor',
-                '/parent-01', FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS)
+            def dataNode = objectUnderTest.getDataNode('my-dataspace', 'my-anchor',
+                    '/parent-01', FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS)
         then: 'a data validation exception is thrown'
-        thrown(DataValidationException)
+            thrown(DataValidationException)
     }
 
     def 'start session'() {
diff --git a/cps-ri/src/test/resources/data/cps-path-query.sql b/cps-ri/src/test/resources/data/cps-path-query.sql
index d1a6220..c406203 100644
--- a/cps-ri/src/test/resources/data/cps-path-query.sql
+++ b/cps-ri/src/test/resources/data/cps-path-query.sql
@@ -25,6 +25,28 @@
 INSERT INTO SCHEMA_SET (ID, NAME, DATASPACE_ID) VALUES
     (2001, 'SCHEMA-SET-001', 1001);
 
+INSERT INTO YANG_RESOURCE (ID, NAME, CONTENT, CHECKSUM, MODULE_NAME, REVISION) VALUES
+    (4001, 'TEST','', 'SAMPLECHECKSUM','TESTMODULENAME', 'SAMPLEREVISION');
+
+UPDATE YANG_RESOURCE SET
+content = 'module stores {
+               yang-version 1.1;
+               namespace "org:onap:ccsdk:sample";
+
+               prefix book-store;
+
+               revision "2020-09-15" {
+                   description
+                   "Sample Model";
+               }
+           }
+'
+where ID = 4001;
+
+
+INSERT INTO SCHEMA_SET_YANG_RESOURCES (SCHEMA_SET_ID, YANG_RESOURCE_ID) VALUES
+    (2001, 4001);
+
 INSERT INTO ANCHOR (ID, NAME, DATASPACE_ID, SCHEMA_SET_ID) VALUES
     (1003, 'ANCHOR-004', 1001, 2001);
 
diff --git a/cps-ri/src/test/resources/data/fragment.sql b/cps-ri/src/test/resources/data/fragment.sql
index 4106541..fd05900 100755
--- a/cps-ri/src/test/resources/data/fragment.sql
+++ b/cps-ri/src/test/resources/data/fragment.sql
@@ -27,6 +27,27 @@
 INSERT INTO SCHEMA_SET (ID, NAME, DATASPACE_ID) VALUES
     (2001, 'SCHEMA-SET-001', 1001);
 
+INSERT INTO YANG_RESOURCE (ID, NAME, CONTENT, CHECKSUM, MODULE_NAME, REVISION) VALUES
+    (4001, 'TEST','', 'SAMPLECHECKSUM','TESTMODULENAME', 'SAMPLEREVISION');
+
+UPDATE YANG_RESOURCE SET
+content = 'module stores {
+               yang-version 1.1;
+               namespace "org:onap:ccsdk:sample";
+
+               prefix book-store;
+
+               revision "2020-09-15" {
+                   description
+                   "Sample Model";
+               }
+           }
+'
+where ID = 4001;
+
+INSERT INTO SCHEMA_SET_YANG_RESOURCES (SCHEMA_SET_ID, YANG_RESOURCE_ID) VALUES
+    (2001, 4001);
+
 INSERT INTO ANCHOR (ID, NAME, DATASPACE_ID, SCHEMA_SET_ID) VALUES
     (3001, 'ANCHOR-001', 1001, 2001),
     (3003, 'ANCHOR-003', 1001, 2001),
diff --git a/cps-service/src/main/java/org/onap/cps/spi/model/DataNode.java b/cps-service/src/main/java/org/onap/cps/spi/model/DataNode.java
index 43aa06b..d80306b 100644
--- a/cps-service/src/main/java/org/onap/cps/spi/model/DataNode.java
+++ b/cps-service/src/main/java/org/onap/cps/spi/model/DataNode.java
@@ -42,6 +42,7 @@
     private String anchorName;
     private ModuleReference moduleReference;
     private String xpath;
+    private String moduleNamePrefix;
     private Map<String, Object> leaves = Collections.emptyMap();
     private Collection<String> xpathsChildren;
     private Collection<DataNode> childDataNodes = Collections.emptySet();
diff --git a/cps-service/src/main/java/org/onap/cps/spi/model/DataNodeBuilder.java b/cps-service/src/main/java/org/onap/cps/spi/model/DataNodeBuilder.java
index 4a9957d..f2bde03 100644
--- a/cps-service/src/main/java/org/onap/cps/spi/model/DataNodeBuilder.java
+++ b/cps-service/src/main/java/org/onap/cps/spi/model/DataNodeBuilder.java
@@ -2,6 +2,7 @@
  * ============LICENSE_START=======================================================
  *  Copyright (C) 2021 Bell Canada. All rights reserved.
  *  Modifications Copyright (C) 2021 Pantheon.tech
+ *  Modifications Copyright (C) 2022 Nordix Foundation.
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -45,6 +46,7 @@
 
     private NormalizedNode<?, ?> normalizedNodeTree;
     private String xpath;
+    private String moduleNamePrefix;
     private String parentNodeXpath = "";
     private Map<String, Object> leaves = Collections.emptyMap();
     private Collection<DataNode> childDataNodes = Collections.emptySet();
@@ -84,6 +86,17 @@
     }
 
     /**
+     * To use module name for prefix for creating {@link DataNode}.
+     *
+     * @param moduleNamePrefix module name as prefix
+     * @return DataNodeBuilder
+     */
+    public DataNodeBuilder withModuleNamePrefix(final String moduleNamePrefix) {
+        this.moduleNamePrefix = moduleNamePrefix;
+        return this;
+    }
+
+    /**
      * To use attributes for creating {@link DataNode}.
      *
      * @param leaves for the data node
@@ -136,6 +149,7 @@
     private DataNode buildFromAttributes() {
         final var dataNode = new DataNode();
         dataNode.setXpath(xpath);
+        dataNode.setModuleNamePrefix(moduleNamePrefix);
         dataNode.setLeaves(leaves);
         dataNode.setChildDataNodes(childDataNodes);
         return dataNode;
diff --git a/cps-service/src/main/java/org/onap/cps/utils/DataMapUtils.java b/cps-service/src/main/java/org/onap/cps/utils/DataMapUtils.java
index 42719d9..ff5204f 100644
--- a/cps-service/src/main/java/org/onap/cps/utils/DataMapUtils.java
+++ b/cps-service/src/main/java/org/onap/cps/utils/DataMapUtils.java
@@ -1,7 +1,7 @@
 /*
  *  ============LICENSE_START=======================================================
  *  Copyright (C) 2021 Pantheon.tech
- *  Modifications (C) 2021 Nordix Foundation
+ *  Modifications (C) 2021-2022 Nordix Foundation
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -44,7 +44,7 @@
      */
     public static Map<String, Object> toDataMapWithIdentifier(final DataNode dataNode) {
         return ImmutableMap.<String, Object>builder()
-            .put(getNodeIdentifier(dataNode.getXpath()), toDataMap(dataNode))
+            .put(getNodeIdentifierWithPrefix(dataNode.getXpath(), dataNode.getModuleNamePrefix()), toDataMap(dataNode))
             .build();
     }
 
@@ -96,6 +96,13 @@
         return toIndex > 0 ? xpath.substring(fromIndex, toIndex) : xpath.substring(fromIndex);
     }
 
+    private static String getNodeIdentifierWithPrefix(final String xpath, final String moduleNamePrefix) {
+        if (moduleNamePrefix != null) {
+            return moduleNamePrefix + ":" + getNodeIdentifier(xpath);
+        }
+        return getNodeIdentifier(xpath);
+    }
+
     private static boolean isContainerNode(final String xpath) {
         return !isListElement(xpath);
     }
diff --git a/cps-service/src/test/groovy/org/onap/cps/spi/model/DataNodeBuilderSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/spi/model/DataNodeBuilderSpec.groovy
index ce54ead..16d4efc 100644
--- a/cps-service/src/test/groovy/org/onap/cps/spi/model/DataNodeBuilderSpec.groovy
+++ b/cps-service/src/test/groovy/org/onap/cps/spi/model/DataNodeBuilderSpec.groovy
@@ -22,6 +22,7 @@
 
 import org.onap.cps.TestUtils
 import org.onap.cps.spi.model.DataNodeBuilder
+import org.onap.cps.utils.DataMapUtils
 import org.onap.cps.utils.YangUtils
 import org.onap.cps.yang.YangTextSchemaSourceSetBuilder
 import org.opendaylight.yangtools.yang.common.QName
@@ -172,6 +173,22 @@
             'NormalizedNode is an unsupported type' | 'not supported' | Mock(NormalizedNode) | 0            | [ ]
     }
 
+    def 'Use of adding the module name prefix attribute of data node.'() {
+        when: 'data node is built with a prefix'
+            def testDataNode = new DataNodeBuilder()
+                    .withModuleNamePrefix('sampleModuleNamePrefix')
+                    .withXpath(xPath)
+                    .withLeaves(sampleLeaves)
+                    .build()
+        then: 'the result when node request is a #scenario includes the correct prefix'
+            def result = new DataMapUtils().toDataMapWithIdentifier(testDataNode)
+            result.toString() == expectedResult
+        where: 'the following parameters are used'
+            scenario          | xPath                                       | sampleLeaves                   | expectedResult
+            'list attribute'  | '/test-tree/branch[@name=\'Right\']/nest'   | [name: 'Big', birds: ['Owl']]  | '{sampleModuleNamePrefix:nest={name=Big, birds=[Owl]}}'
+            'container xpath' | '/test-tree/branch[@name=\'Left\']'         | [name: 'Left']                 | '{sampleModuleNamePrefix:branch={name=Left}}'
+    }
+
     def static assertLeavesMaps(actualLeavesMap, expectedLeavesMap) {
         expectedLeavesMap.each { key, value ->
             {
diff --git a/cps-service/src/test/groovy/org/onap/cps/utils/DataMapUtilsSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/utils/DataMapUtilsSpec.groovy
index 90563c0..24e8061 100644
--- a/cps-service/src/test/groovy/org/onap/cps/utils/DataMapUtilsSpec.groovy
+++ b/cps-service/src/test/groovy/org/onap/cps/utils/DataMapUtilsSpec.groovy
@@ -1,7 +1,7 @@
 /*
  *  ============LICENSE_START=======================================================
  *  Copyright (C) 2021 Pantheon.tech
- *  Modifications Copyright (C) 2020 Nordix Foundation
+ *  Modifications Copyright (C) 2020-2022 Nordix Foundation
  *  Modifications Copyright (C) 2022 Bell Canada.
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
@@ -29,13 +29,13 @@
     def noChildren = []
 
     def dataNode = buildDataNode(
-        "/parent",[parentLeaf:'parentLeafValue', parentLeafList:['parentLeafListEntry1','parentLeafListEntry2']],[
-                buildDataNode('/parent/child-list[@id=1]',[listElementLeaf:'listElement1leafValue'],noChildren),
-                buildDataNode('/parent/child-list[@id=2]',[listElementLeaf:'listElement2leafValue'],noChildren),
-                buildDataNode('/parent/child-object',[childLeaf:'childLeafValue'],
-                        [buildDataNode('/parent/child-object/grand-child-object',[grandChildLeaf:'grandChildLeafValue'],noChildren)]
-                ),
-            ])
+            "/parent",[parentLeaf:'parentLeafValue', parentLeafList:['parentLeafListEntry1','parentLeafListEntry2']],[
+            buildDataNode('/parent/child-list[@id=1]',[listElementLeaf:'listElement1leafValue'],noChildren),
+            buildDataNode('/parent/child-list[@id=2]',[listElementLeaf:'listElement2leafValue'],noChildren),
+            buildDataNode('/parent/child-object',[childLeaf:'childLeafValue'],
+                    [buildDataNode('/parent/child-object/grand-child-object',[grandChildLeaf:'grandChildLeafValue'],noChildren)]
+            ),
+    ])
 
     static def buildDataNode(xpath,  leaves,  children) {
         return new DataNodeBuilder().withXpath(xpath).withLeaves(leaves).withChildDataNodes(children).build()
@@ -81,4 +81,16 @@
         and: 'leaves for grandchild element is populated under its node identifier'
             parentNode.'child-object'.'grand-child-object'.grandChildLeaf == 'grandChildLeafValue'
     }
+
+    def 'Adding prefix to data node identifier.'() {
+        when: 'a valid xPath is passed to the addPrefixToXpath method'
+            def result = new DataMapUtils().getNodeIdentifierWithPrefix(xPath,'sampleModuleName')
+        then: 'the correct modified node identifier is given'
+            assert result == expectedNodeIdentifier
+        where: 'the following parameters are used'
+            scenario                        | xPath                                       | expectedNodeIdentifier
+            'container xpath'               | '/bookstore'                                | 'sampleModuleName:bookstore'
+            'xpath contains list attribute' | '/bookstore/categories[@code=1]'            | 'sampleModuleName:categories'
+    }
 }
+
diff --git a/csit/tests/cps-data/cps-data.robot b/csit/tests/cps-data/cps-data.robot
index 55667c3..844b5d5 100644
--- a/csit/tests/cps-data/cps-data.robot
+++ b/csit/tests/cps-data/cps-data.robot
@@ -1,6 +1,7 @@
 # ============LICENSE_START=======================================================
 # Copyright (c) 2021 Pantheon.tech.
 # Modifications Copyright (C) 2022 Bell Canada.
+# Modifications Copyright (C) 2022 Nordix Foundation.
 # ================================================================================
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -46,7 +47,7 @@
     ${params}=          Create Dictionary   xpath=/test-tree/branch[@name='Left']/nest
     ${headers}=         Create Dictionary   Authorization=${auth}
     ${response}=        Get On Session      CPS_URL   ${uri}   params=${params}   headers=${headers}   expected_status=200
-    ${responseJson}=    Set Variable        ${response.json()['nest']}
+    ${responseJson}=    Set Variable        ${response.json()['test-tree:nest']}
     Should Be Equal As Strings              ${responseJson['name']}   Small