aboutsummaryrefslogtreecommitdiffstats
path: root/cps-ri/src
diff options
context:
space:
mode:
authorToineSiebelink <toine.siebelink@est.tech>2022-12-19 14:19:29 +0000
committerToineSiebelink <toine.siebelink@est.tech>2022-12-19 16:12:32 +0000
commite52d0cbf970f1de982fb64f1a052646457b81f52 (patch)
tree86452d641b55bd3c365470d5ff21f32a6ce9c8ec /cps-ri/src
parentb344f764a93e03545dc8984a4974329d6811b859 (diff)
Fix Delete uses case with '/' in path
-Extend and use cpsPath parser (util) classes instead of regex Issue-ID: CPS-1409 Signed-off-by: ToineSiebelink <toine.siebelink@est.tech> Change-Id: I230c9eb71cc34264983830b39149511b95c4b4a6
Diffstat (limited to 'cps-ri/src')
-rw-r--r--cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java10
-rwxr-xr-xcps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceIntegrationSpec.groovy36
2 files changed, 33 insertions, 13 deletions
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 b7da66e467..82bcea2f1a 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
@@ -79,9 +79,6 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
private final SessionManager sessionManager;
private static final String REG_EX_FOR_OPTIONAL_LIST_INDEX = "(\\[@[\\s\\S]+?]){0,1})";
- private static final Pattern REG_EX_PATTERN_FOR_LIST_ELEMENT_KEY_PREDICATE =
- Pattern.compile("\\[(\\@([^\\/]{0,9999}))\\]$");
- private static final String TOP_LEVEL_MODULE_PREFIX_PROPERTY_NAME = "topLevelModulePrefix";
@Override
public void addChildDataNode(final String dataspaceName, final String anchorName, final String parentNodeXpath,
@@ -550,13 +547,10 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
if (isRootContainerNodeXpath(targetXpath)) {
parentNodeXpath = targetXpath;
} else {
- parentNodeXpath = targetXpath.substring(0, targetXpath.lastIndexOf('/'));
+ parentNodeXpath = CpsPathUtil.getNormalizedParentXpath(targetXpath);
}
parentFragmentEntity = getFragmentWithoutDescendantsByXpath(dataspaceName, anchorName, parentNodeXpath);
- final String lastXpathElement = targetXpath.substring(targetXpath.lastIndexOf('/'));
- final boolean isListElement = REG_EX_PATTERN_FOR_LIST_ELEMENT_KEY_PREDICATE
- .matcher(lastXpathElement).find();
- if (isListElement) {
+ if (CpsPathUtil.isPathToListElement(targetXpath)) {
targetDeleted = deleteDataNode(parentFragmentEntity, targetXpath);
} else {
targetDeleted = deleteAllListElements(parentFragmentEntity, targetXpath);
diff --git a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceIntegrationSpec.groovy b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceIntegrationSpec.groovy
index 12585eb5a9..cc2369d50e 100755
--- a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceIntegrationSpec.groovy
+++ b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceIntegrationSpec.groovy
@@ -38,6 +38,7 @@ import org.onap.cps.spi.model.DataNodeBuilder
import org.onap.cps.utils.JsonObjectMapper
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.test.context.jdbc.Sql
+
import javax.validation.ConstraintViolationException
import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS
@@ -68,6 +69,10 @@ class CpsDataPersistenceServiceIntegrationSpec extends CpsPersistenceSpecBase {
static Collection<DataNode> existingDataNodes = [createDataNodeTree(XPATH_DATA_NODE_WITH_DESCENDANTS)]
static Collection<DataNode> existingChildDataNodes = [createDataNodeTree('/parent-1/child-1')]
+ def static deleteTestParentXPath = '/parent-200'
+ def static deleteTestChildXpath = "${deleteTestParentXPath}/child-with-slash[@key='a/b']"
+ def static deleteTestGrandChildXPath = "${deleteTestChildXpath}/grandChild"
+
def expectedLeavesByXpathMap = [
'/parent-207' : ['parent-leaf': 'parent-leaf value'],
'/parent-207/child-001' : ['first-child-leaf': 'first-child-leaf value'],
@@ -286,7 +291,8 @@ class CpsDataPersistenceServiceIntegrationSpec extends CpsPersistenceSpecBase {
scenario | dataspaceName | anchorName | xpath || expectedException
'non-existing dataspace' | 'NO DATASPACE' | 'not relevant' | '/not relevant' || DataspaceNotFoundException
'non-existing anchor' | DATASPACE_NAME | 'NO ANCHOR' | '/not relevant' || AnchorNotFoundException
- 'non-existing xpath' | DATASPACE_NAME | ANCHOR_FOR_DATA_NODES_WITH_LEAVES | '/NO XPATH' || DataNodeNotFoundException
+ 'non-existing xpath' | DATASPACE_NAME | ANCHOR_FOR_DATA_NODES_WITH_LEAVES | '/NO-XPATH' || DataNodeNotFoundException
+ 'invalid xpath' | DATASPACE_NAME | ANCHOR_FOR_DATA_NODES_WITH_LEAVES | 'INVALID XPATH' || CpsPathException
}
@Sql([CLEAR_DATA, SET_DATA])
@@ -316,7 +322,7 @@ class CpsDataPersistenceServiceIntegrationSpec extends CpsPersistenceSpecBase {
scenario | dataspaceName | anchorName | xpath || expectedException
'non-existing dataspace' | 'NO DATASPACE' | 'not relevant' | '/not relevant' || DataspaceNotFoundException
'non-existing anchor' | DATASPACE_NAME | 'NO ANCHOR' | '/not relevant' || AnchorNotFoundException
- 'non-existing xpath' | DATASPACE_NAME | ANCHOR_FOR_DATA_NODES_WITH_LEAVES | '/NON-EXISTING XPATH' || DataNodeNotFoundException
+ 'non-existing xpath' | DATASPACE_NAME | ANCHOR_FOR_DATA_NODES_WITH_LEAVES | '/NON-EXISTING-XPATH' || DataNodeNotFoundException
}
@Sql([CLEAR_DATA, SET_DATA])
@@ -410,7 +416,8 @@ class CpsDataPersistenceServiceIntegrationSpec extends CpsPersistenceSpecBase {
scenario | dataspaceName | anchorName | xpath || expectedException
'non-existing dataspace' | 'NO DATASPACE' | 'not relevant' | '/not relevant' || DataspaceNotFoundException
'non-existing anchor' | DATASPACE_NAME | 'NO ANCHOR' | '/not relevant' || AnchorNotFoundException
- 'non-existing xpath' | DATASPACE_NAME | ANCHOR_FOR_DATA_NODES_WITH_LEAVES | '/NON-EXISTING XPATH' || DataNodeNotFoundException
+ 'non-existing xpath' | DATASPACE_NAME | ANCHOR_FOR_DATA_NODES_WITH_LEAVES | '/NON-EXISTING-XPATH' || DataNodeNotFoundException
+ 'invalid xpath' | DATASPACE_NAME | ANCHOR_FOR_DATA_NODES_WITH_LEAVES | 'INVALID XPATH' || CpsPathException
}
@Sql([CLEAR_DATA, SET_DATA])
@@ -523,6 +530,25 @@ class CpsDataPersistenceServiceIntegrationSpec extends CpsPersistenceSpecBase {
}
@Sql([CLEAR_DATA, SET_DATA])
+ def 'Delete data nodes with "/"-token in list key value: #scenario. (CPS-1409)'() {
+ given: 'a data nodes with list-element child with "/" in index value (and grandchild)'
+ def grandChild = new DataNodeBuilder().withXpath(deleteTestGrandChildXPath).build()
+ def child = new DataNodeBuilder().withXpath(deleteTestChildXpath).withChildDataNodes([grandChild]).build()
+ objectUnderTest.addChildDataNode(DATASPACE_NAME, ANCHOR_NAME3, deleteTestParentXPath, child)
+ and: 'number of children before delete is stored'
+ def numberOfChildrenBeforeDelete = objectUnderTest.getDataNode(DATASPACE_NAME, ANCHOR_NAME3, pathToParentOfDeletedNode, INCLUDE_ALL_DESCENDANTS).childDataNodes.size()
+ when: 'target node is deleted'
+ objectUnderTest.deleteDataNode(DATASPACE_NAME, ANCHOR_NAME3, deleteTarget)
+ then: 'one child has been deleted'
+ def numberOfChildrenAfterDelete = objectUnderTest.getDataNode(DATASPACE_NAME, ANCHOR_NAME3, pathToParentOfDeletedNode, INCLUDE_ALL_DESCENDANTS).childDataNodes.size()
+ assert numberOfChildrenAfterDelete == numberOfChildrenBeforeDelete - 1
+ where:
+ scenario | deleteTarget | pathToParentOfDeletedNode
+ 'list element with /' | deleteTestChildXpath | deleteTestParentXPath
+ 'child of list element' | deleteTestGrandChildXPath | deleteTestChildXpath
+ }
+
+ @Sql([CLEAR_DATA, SET_DATA])
def 'Delete list error scenario: #scenario.'() {
when: 'attempting to delete scenario: #scenario.'
objectUnderTest.deleteListDataNode(DATASPACE_NAME, ANCHOR_NAME3, targetXpaths)
@@ -539,7 +565,7 @@ class CpsDataPersistenceServiceIntegrationSpec extends CpsPersistenceSpecBase {
}
@Sql([CLEAR_DATA, SET_DATA])
- def 'Confirm deletion of #scenario.'() {
+ def 'Delete data node by xpath #scenario.'() {
given: 'a valid data node'
def dataNode
and: 'data nodes are deleted'
@@ -564,7 +590,7 @@ class CpsDataPersistenceServiceIntegrationSpec extends CpsPersistenceSpecBase {
}
@Sql([CLEAR_DATA, SET_DATA])
- def 'Delete data node with #scenario.'() {
+ def 'Delete data node error scenario: #scenario.'() {
when: 'data node is deleted'
objectUnderTest.deleteDataNode(DATASPACE_NAME, ANCHOR_NAME3, datanodeXpath)
then: 'a #expectedException is thrown'