aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorputhuparambil.aditya <aditya.puthuparambil@bell.ca>2021-04-28 16:39:32 +0100
committerputhuparambil.aditya <aditya.puthuparambil@bell.ca>2021-04-30 10:45:53 +0100
commita4cc3554804540b49d9b778f75b158d6c1ec5899 (patch)
treee352e909ac9f098e6c6bdc98c668f750e6d2d235
parent6da081cc0667795cd7872582a8795cf0bbd56c17 (diff)
Fix Get descendent to support xpaths that end in list values
Issue-ID: CPS-367 Signed-off-by: puthuparambil.aditya <aditya.puthuparambil@bell.ca> Change-Id: I3234afd8b8b69c5a3c87db1669d9b304f9fcaa49
-rwxr-xr-xcps-ri/src/main/java/org/onap/cps/spi/repository/FragmentRepository.java5
-rw-r--r--cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceQueryDataNodeSpec.groovy44
-rwxr-xr-xcps-ri/src/test/resources/data/fragment.sql4
3 files changed, 36 insertions, 17 deletions
diff --git a/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentRepository.java b/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentRepository.java
index 74d04613d9..b9874484c0 100755
--- a/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentRepository.java
+++ b/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentRepository.java
@@ -76,8 +76,9 @@ public interface FragmentRepository extends JpaRepository<FragmentEntity, Long>
List<FragmentEntity> getByAnchorAndXpathEndsInDescendantName(@Param("anchor") int anchorId,
@Param("descendantName") String descendantName);
- @Query(value = "SELECT * FROM FRAGMENT WHERE anchor_id = :anchor AND xpath LIKE CONCAT('%/',:descendantName) "
- + "AND attributes @> :leafDataAsJson\\:\\:jsonb", nativeQuery = true)
+ @Query(value = "SELECT * FROM FRAGMENT WHERE anchor_id = :anchor AND (xpath LIKE CONCAT('%/',:descendantName) OR "
+ + "xpath LIKE CONCAT('%/', :descendantName,'\\[@%]')) AND attributes @> :leafDataAsJson\\:\\:jsonb",
+ nativeQuery = true)
// Above query will match the anchor id, last descendant name and all parameters passed into leafDataASJson with the
// attribute values of the requested data node eg: {"leaf_name":"value", "another_leaf_name":"another value"}​​​​​​
List<FragmentEntity> getByAnchorAndDescendentNameAndLeafValues(@Param("anchor") int anchorId,
diff --git a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceQueryDataNodeSpec.groovy b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceQueryDataNodeSpec.groovy
index bfc088db2a..8acfe783da 100644
--- a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceQueryDataNodeSpec.groovy
+++ b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceQueryDataNodeSpec.groovy
@@ -76,7 +76,6 @@ class CpsDataPersistenceQueryDataNodeSpec extends CpsPersistenceSpecBase {
return flatMap
}
-
@Sql([CLEAR_DATA, SET_DATA])
def 'Cps Path query for single leaf value with type: #type.'() {
when: 'a query is executed to get a data node by the given cps path'
@@ -120,14 +119,14 @@ class CpsDataPersistenceQueryDataNodeSpec extends CpsPersistenceSpecBase {
}
@Sql([CLEAR_DATA, SET_DATA])
- def 'Cps Path query using descendant anywhere with %scenario '() {
+ def 'Cps Path query using descendant anywhere with #scenario '() {
when: 'a query is executed to get a data node by the given cps path'
def result = objectUnderTest.queryDataNodes(DATASPACE_NAME, ANCHOR_FOR_DATA_NODES_WITH_LEAVES, cpsPath, OMIT_DESCENDANTS)
then: 'the correct number of data nodes are retrieved'
result.size() == expectedXPaths.size()
and: 'xpaths of the retrieved data nodes are as expected'
for(int i = 0; i<result.size(); i++) {
- result[i].getXpath() == expectedXPaths[i]
+ assert result[i].getXpath() == expectedXPaths[i]
}
where: 'the following data is used'
scenario | cpsPath || expectedXPaths
@@ -136,32 +135,49 @@ class CpsDataPersistenceQueryDataNodeSpec extends CpsPersistenceSpecBase {
}
@Sql([CLEAR_DATA, SET_DATA])
- def 'Cps Path query using descendant anywhere ends with yang list containing %scenario '() {
+ def 'Cps Path query using descendant anywhere with #scenario condition(s) for a container element.'() {
when: 'a query is executed to get a data node by the given cps path'
def result = objectUnderTest.queryDataNodes(DATASPACE_NAME, ANCHOR_FOR_DATA_NODES_WITH_LEAVES, cpsPath, OMIT_DESCENDANTS)
then: 'the correct number of data nodes are retrieved'
result.size() == expectedXPaths.size()
and: 'xpaths of the retrieved data nodes are as expected'
for(int i = 0; i<result.size(); i++) {
- result[i].getXpath() == expectedXPaths[i]
+ assert result[i].getXpath() == expectedXPaths[i]
}
where: 'the following data is used'
- scenario | cpsPath || expectedXPaths
- 'one attribute' | '//child-202[@common-leaf-name-int=5]' || ['/parent-200/child-202','/parent-201/child-202']
- 'trailing "and" is ignored' | '//child-202[@common-leaf-name-int=5 and]' || ['/parent-200/child-202','/parent-201/child-202']
- 'more than one attribute' | '//child-202[@common-leaf-name-int=5 and @common-leaf-name="common-leaf value"]' || ['/parent-200/child-202']
- 'attributes reversed in order' | '//child-202[@common-leaf-name="common-leaf value" and @common-leaf-name-int=5]' || ['/parent-200/child-202']
+ scenario | cpsPath || expectedXPaths
+ 'one leaf' | '//child-202[@common-leaf-name-int=5]' || ['/parent-200/child-202','/parent-201/child-202']
+ 'trailing "and" is ignored' | '//child-202[@common-leaf-name-int=5 and]' || ['/parent-200/child-202','/parent-201/child-202']
+ 'more than one leaf' | '//child-202[@common-leaf-name-int=5 and @common-leaf-name="common-leaf value"]' || ['/parent-200/child-202']
+ 'leaves reversed in order' | '//child-202[@common-leaf-name="common-leaf value" and @common-leaf-name-int=5]' || ['/parent-200/child-202']
}
@Sql([CLEAR_DATA, SET_DATA])
- def 'Cps Path query error scenario using descendant anywhere ends with yang list containing %scenario '() {
+ def 'Cps Path query using descendant anywhere with #scenario condition(s) for a list element.'() {
when: 'a query is executed to get a data node by the given cps path'
def result = objectUnderTest.queryDataNodes(DATASPACE_NAME, ANCHOR_FOR_DATA_NODES_WITH_LEAVES, cpsPath, OMIT_DESCENDANTS)
+ then: 'the correct number of data nodes are retrieved'
+ result.size() == expectedXPaths.size()
+ and: 'xpaths of the retrieved data nodes are as expected'
+ for(int i = 0; i<result.size(); i++) {
+ assert result[i].getXpath() == expectedXPaths[i]
+ }
+ where: 'the following data is used'
+ scenario | cpsPath || expectedXPaths
+ 'one partial key leaf' | '//child-203[@key1="A"]' || ['/parent-201/child-203[@key1="A" and @key2=1]','/parent-201/child-203[@key1="A" and @key2=2]']
+ 'one non key leaf' | '//child-203[@other-leaf="other value"]' || ['/parent-201/child-203[@key1="A" and @key2=2]']
+ 'mix of partial key and non key leaf' | '//child-203[@key1="A" and @other-leaf="leaf value"]' || ['/parent-201/child-203[@key1="A" and @key2=1]']
+ }
+
+ @Sql([CLEAR_DATA, SET_DATA])
+ def 'Cps Path query error scenario using descendant anywhere ends with yang list containing %scenario '() {
+ when: 'a query is executed to get a data node by the given cps path'
+ objectUnderTest.queryDataNodes(DATASPACE_NAME, ANCHOR_FOR_DATA_NODES_WITH_LEAVES, cpsPath, OMIT_DESCENDANTS)
then: 'exception is thrown'
thrown(CpsPathException)
where: 'the following data is used'
- scenario | cpsPath
- 'one of the attributes without value' | '//child-202[@common-leaf-name-int=5 and @another-attribute"]'
- 'more than one attribute separated by or' | '//child-202[@common-leaf-name-int=5 or @common-leaf-name="common-leaf value"]'
+ scenario | cpsPath
+ 'one of the leaf without value' | '//child-202[@common-leaf-name-int=5 and @another-attribute"]'
+ 'more than one leaf separated by or' | '//child-202[@common-leaf-name-int=5 or @common-leaf-name="common-leaf value"]'
}
}
diff --git a/cps-ri/src/test/resources/data/fragment.sql b/cps-ri/src/test/resources/data/fragment.sql
index d252fbbb59..3e2ae8157e 100755
--- a/cps-ri/src/test/resources/data/fragment.sql
+++ b/cps-ri/src/test/resources/data/fragment.sql
@@ -29,4 +29,6 @@ INSERT INTO FRAGMENT (ID, DATASPACE_ID, ANCHOR_ID, PARENT_ID, XPATH, ATTRIBUTES)
(4204, 1001, 3003, 4201, '/parent-200/child-202', '{"common-leaf-name": "common-leaf value", "common-leaf-name-int" : 5}'),
(4205, 1001, 3003, 4204, '/parent-200/child-202/grand-child-202', '{"common-leaf-name": "common-leaf value", "common-leaf-name-int" : 5}'),
(4206, 1001, 3003, null, '/parent-201', '{"leaf-value": "original"}'),
- (4207, 1001, 3003, 4201, '/parent-201/child-202', '{"common-leaf-name": "common-leaf other value", "common-leaf-name-int" : 5}'); \ No newline at end of file
+ (4207, 1001, 3003, 4206, '/parent-201/child-202', '{"common-leaf-name": "common-leaf other value", "common-leaf-name-int" : 5}'),
+ (4208, 1001, 3003, 4206, '/parent-201/child-203[@key1="A" and @key2=1]', '{"key1": "A", "key2" : 1, "other-leaf" : "leaf value"}'),
+ (4209, 1001, 3003, 4206, '/parent-201/child-203[@key1="A" and @key2=2]', '{"key1": "A", "key2" : 2, "other-leaf" : "other value"}'); \ No newline at end of file