diff options
author | danielhanrahan <daniel.hanrahan@est.tech> | 2024-08-29 20:00:40 +0100 |
---|---|---|
committer | danielhanrahan <daniel.hanrahan@est.tech> | 2024-09-04 17:21:40 +0100 |
commit | 0f225618ab5a5d918c6b1d58afcad17c99d7aad8 (patch) | |
tree | 1d1092a596a7150044b39567137f89f570c98111 | |
parent | d196932c3ed2edbc3f0a0ce0fb097b40715ad0bb (diff) |
[Cps Path Parser] Move NCMP-specific logic to NCMP
Some special case code to disable ancestor-axis was added for
CM-handle search (see CPS-2308). It is now relocated to NCMP.
This makes other needed improvements of Cps Path Parser easier.
- Move special case code into NCMP
- Add integration test to ensure CM-handle search works
Issue-ID: CPS-2365
Signed-off-by: danielhanrahan <daniel.hanrahan@est.tech>
Change-Id: I168d6156be559166f115aa42e21cd987d98b7d41
6 files changed, 44 insertions, 27 deletions
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImpl.java index e36477f8c8..a07954d5a9 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImpl.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImpl.java @@ -34,6 +34,7 @@ import java.util.List; import java.util.Map; import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; +import org.onap.cps.cpspath.parser.CpsPathUtil; import org.onap.cps.ncmp.api.inventory.models.TrustLevel; import org.onap.cps.ncmp.impl.inventory.models.CmHandleState; import org.onap.cps.ncmp.impl.inventory.models.ModelledDmiServiceLeaves; @@ -96,6 +97,9 @@ public class CmHandleQueryServiceImpl implements CmHandleQueryService { @Override public List<DataNode> queryCmHandleAncestorsByCpsPath(final String cpsPath, final FetchDescendantsOption fetchDescendantsOption) { + if (CpsPathUtil.getCpsPathQuery(cpsPath).getXpathPrefix().endsWith("/cm-handles")) { + return queryNcmpRegistryByCpsPath(cpsPath, fetchDescendantsOption); + } return queryNcmpRegistryByCpsPath(cpsPath + ANCESTOR_CM_HANDLES, fetchDescendantsOption); } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImplSpec.groovy index 36fd755774..e3847fa94b 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImplSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImplSpec.groovy @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022-2023 Nordix Foundation + * Copyright (C) 2022-2024 Nordix Foundation * Modifications Copyright (C) 2023 TechMahindra Ltd. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -167,9 +167,9 @@ class CmHandleQueryServiceImplSpec extends Specification { def 'Retrieve cm handle by cps path '() { given: 'a cm handle state to query based on the cps path' - def cmHandleDataNode = new DataNode(xpath: 'xpath', leaves: ['cm-handle-state': 'LOCKED']) - def cpsPath = '//cps-path' - and: 'cps data service returns a valid data node' + def cmHandleDataNode = new DataNode(xpath: "/dmi-registry/cm-handles[@id='ch-1']", leaves: ['id': 'ch-1']) + def cpsPath = "//state[@cm-handle-state='LOCKED']" + and: 'cps data service returns a valid data node for cm handle ancestor' mockCpsDataPersistenceService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, cpsPath + '/ancestor::cm-handles', INCLUDE_ALL_DESCENDANTS) >> Arrays.asList(cmHandleDataNode) @@ -179,6 +179,20 @@ class CmHandleQueryServiceImplSpec extends Specification { assert result.contains(cmHandleDataNode) } + def 'Retrieve cm handle by cps path querying cm handle directly'() { + given: 'a cm handle to query based on the cps path' + def cmHandleDataNode = new DataNode(xpath: "/dmi-registry/cm-handles[@id='ch-2']", leaves: ['id': 'ch-2']) + def cpsPath = "//cm-handles[@alternate-id='1']" + and: 'cps data service returns a valid data node' + mockCpsDataPersistenceService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, + cpsPath, INCLUDE_ALL_DESCENDANTS) + >> Arrays.asList(cmHandleDataNode) + when: 'get cm handles by cps path is invoked' + def result = objectUnderTest.queryCmHandleAncestorsByCpsPath(cpsPath, INCLUDE_ALL_DESCENDANTS) + then: 'the returned result is a list of data nodes returned by cps data service' + assert result.contains(cmHandleDataNode) + } + def 'Get all cm handles by dmi plugin identifier'() { given: 'the DataNodes queried for a given cpsPath are returned from the persistence service.' mockResponses() diff --git a/cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathBuilder.java b/cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathBuilder.java index 0325bdcacb..ac535f5efc 100644 --- a/cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathBuilder.java +++ b/cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathBuilder.java @@ -147,10 +147,6 @@ public class CpsPathBuilder extends CpsPathBaseListener { cpsPathQuery.setNormalizedXpath(normalizedXpathBuilder.toString()); cpsPathQuery.setContainerNames(containerNames); cpsPathQuery.setBooleanOperators(booleanOperators); - if (cpsPathQuery.hasAncestorAxis() && cpsPathQuery.getXpathPrefix() - .endsWith("/" + cpsPathQuery.getAncestorSchemaNodeIdentifier())) { - cpsPathQuery.setAncestorSchemaNodeIdentifier(""); - } return cpsPathQuery; } diff --git a/cps-path-parser/src/test/groovy/org/onap/cps/cpspath/parser/CpsPathQuerySpec.groovy b/cps-path-parser/src/test/groovy/org/onap/cps/cpspath/parser/CpsPathQuerySpec.groovy index 730c826332..d0df3c745a 100644 --- a/cps-path-parser/src/test/groovy/org/onap/cps/cpspath/parser/CpsPathQuerySpec.groovy +++ b/cps-path-parser/src/test/groovy/org/onap/cps/cpspath/parser/CpsPathQuerySpec.groovy @@ -253,21 +253,4 @@ class CpsPathQuerySpec extends Specification { '/test[@name2="value2" and @name1="value1"]' || 'name2' | 'name1' } - def 'Ancestor axis matching prefix'() { - when: 'building a cps path query' - def result = parseXPathAndBuild(xpath) - then: 'ancestor axis is removed when same as prefix' - assert result.hasAncestorAxis() == expectAncestorAxis - where: 'the following xpaths are used' - xpath || expectAncestorAxis - '//abc/def/ancestor::abc' || true - '//abc/def/ancestor::def' || false - '//abc/def/ancestor::ef' || true - } - - def parseXPathAndBuild(xpath) { - def cpsPathBuilder = CpsPathUtil.getCpsPathBuilder(xpath) - cpsPathBuilder.build() - } - } diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/QueryServiceIntegrationSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/QueryServiceIntegrationSpec.groovy index 69598a0604..5c2a4fc665 100644 --- a/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/QueryServiceIntegrationSpec.groovy +++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/QueryServiceIntegrationSpec.groovy @@ -271,7 +271,6 @@ class QueryServiceIntegrationSpec extends FunctionalSpecBase { 'ancestor with parent list' | '//books/ancestor::bookstore/categories' || ["/bookstore/categories[@code='1']", "/bookstore/categories[@code='2']", "/bookstore/categories[@code='3']", "/bookstore/categories[@code='4']", "/bookstore/categories[@code='5']"] 'ancestor with parent list element' | '//books/ancestor::bookstore/categories[@code="2"]' || ["/bookstore/categories[@code='2']"] 'ancestor combined with text condition' | '//books/title[text()="Matilda"]/ancestor::bookstore' || ["/bookstore"] - 'ancestor same as target type' | '//books/title[text()="Matilda"]/ancestor::books' || ["/bookstore/categories[@code='1']/books[@title='Matilda']"] } def 'Cps Path query across anchors with #scenario descendants.'() { diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/RestApiSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/RestApiSpec.groovy index 33973e547b..1e1af556f1 100644 --- a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/RestApiSpec.groovy +++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/RestApiSpec.groovy @@ -41,7 +41,7 @@ class RestApiSpec extends CpsIntegrationSpecBase { 'ch-3': ['M1', 'M3'] ] when: 'a POST request is made to register the CM Handles' - def requestBody = '{"dmiPlugin":"'+DMI1_URL+'","createdCmHandles":[{"cmHandle":"ch-1"},{"cmHandle":"ch-2"},{"cmHandle":"ch-3"}]}' + def requestBody = '{"dmiPlugin":"'+DMI1_URL+'","createdCmHandles":[{"cmHandle":"ch-1","alternateId":"alt-1"},{"cmHandle":"ch-2","alternateId":"alt-2"},{"cmHandle":"ch-3","alternateId":"alt-3"}]}' mvc.perform(post('/ncmpInventory/v1/ch').contentType(MediaType.APPLICATION_JSON).content(requestBody)) .andExpect(status().is2xxSuccessful()) then: 'CM-handles go to READY state' @@ -76,6 +76,27 @@ class RestApiSpec extends CpsIntegrationSpecBase { 'M3' || ['ch-3'] } + def 'Search for CM Handles using Cps Path Query.'() { + given: 'a JSON request body containing search parameter' + def requestBodyWithSearchCondition = """{ + "cmHandleQueryParameters": [ + { + "conditionName": "cmHandleWithCpsPath", + "conditionParameters": [ {"cpsPath" : "%s"} ] + } + ] + }""".formatted(cpsPath) + expect: "a search for cps path ${cpsPath} returns expected CM handles" + mvc.perform(post('/ncmp/v1/ch/id-searches').contentType(MediaType.APPLICATION_JSON).content(requestBodyWithSearchCondition)) + .andExpect(status().is2xxSuccessful()) + .andExpect(jsonPath('$[*]', containsInAnyOrder(expectedCmHandles.toArray()))) + .andExpect(jsonPath('$', hasSize(expectedCmHandles.size()))); + where: + scenario | cpsPath || expectedCmHandles + 'All Ready CM handles' | "//state[@cm-handle-state='READY']" || ['ch-1', 'ch-2', 'ch-3'] + 'Having Alternate ID alt-3' | "//cm-handles[@alternate-id='alt-3']" || ['ch-3'] + } + def 'De-register CM handles using REST API.'() { when: 'a POST request is made to deregister the CM Handle' def requestBody = '{"dmiPlugin":"'+DMI1_URL+'", "removedCmHandles": ["ch-1", "ch-2", "ch-3"]}' |