diff options
14 files changed, 105 insertions, 131 deletions
diff --git a/cps-ncmp-rest/docs/openapi/ncmp.yml b/cps-ncmp-rest/docs/openapi/ncmp.yml index 446b17c4d2..adb2419c8a 100755 --- a/cps-ncmp-rest/docs/openapi/ncmp.yml +++ b/cps-ncmp-rest/docs/openapi/ncmp.yml @@ -264,7 +264,7 @@ fetchModuleReferencesByCmHandle: summary: Fetch all module references (name and revision) for a given cm handle operationId: getModuleReferencesByCmHandle parameters: - - $ref: 'components.yaml#/components/parameters/cmHandleInPath' + - $ref: 'components.yaml#/components/parameters/cmHandleReferenceInPath' responses: 200: description: OK @@ -289,7 +289,7 @@ getModuleDefinitions: description: Get module definitions (module name, revision, yang resource) with options to filter on module name and revision operationId: getModuleDefinitions parameters: - - $ref: 'components.yaml#/components/parameters/cmHandleInPath' + - $ref: 'components.yaml#/components/parameters/cmHandleReferenceInPath' - $ref: 'components.yaml#/components/parameters/moduleNameInQuery' - $ref: 'components.yaml#/components/parameters/revisionInQuery' responses: diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java index 6657a3a3c7..42f709dcf5 100755 --- a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java +++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java @@ -334,21 +334,23 @@ public class NetworkCmProxyController implements NetworkCmProxyApi { /** * Return module definitions. * - * @param cmHandleId cm-handle identifier - * @param moduleName module name - * @param revision the revision of the module + * @param cmHandleReference cm handle or alternate id identifier + * @param moduleName module name + * @param revision the revision of the module * @return list of module definitions (module name, revision, yang resource content) */ @Override - public ResponseEntity<List<RestModuleDefinition>> getModuleDefinitions(final String cmHandleId, + public ResponseEntity<List<RestModuleDefinition>> getModuleDefinitions(final String cmHandleReference, final String moduleName, final String revision) { final Collection<ModuleDefinition> moduleDefinitions; if (StringUtils.hasText(moduleName)) { moduleDefinitions = - networkCmProxyInventoryFacade.getModuleDefinitionsByCmHandleAndModule(cmHandleId, moduleName, revision); + networkCmProxyInventoryFacade.getModuleDefinitionsByCmHandleAndModule(cmHandleReference, + moduleName, revision); } else { - moduleDefinitions = networkCmProxyInventoryFacade.getModuleDefinitionsByCmHandleId(cmHandleId); + moduleDefinitions = + networkCmProxyInventoryFacade.getModuleDefinitionsByCmHandleReference(cmHandleReference); if (StringUtils.hasText(revision)) { log.warn("Ignoring revision filter as no module name is provided"); } @@ -363,12 +365,12 @@ public class NetworkCmProxyController implements NetworkCmProxyApi { /** * Return module references for a cm handle. * - * @param cmHandle the cm handle + * @param cmHandleReference cm handle or alternate id identifier * @return module references for cm handle. Namespace will be always blank because restConf does not include this. */ - public ResponseEntity<List<RestModuleReference>> getModuleReferencesByCmHandle(final String cmHandle) { + public ResponseEntity<List<RestModuleReference>> getModuleReferencesByCmHandle(final String cmHandleReference) { final List<RestModuleReference> restModuleReferences = - networkCmProxyInventoryFacade.getYangResourcesModuleReferences(cmHandle).stream() + networkCmProxyInventoryFacade.getYangResourcesModuleReferences(cmHandleReference).stream() .map(ncmpRestInputMapper::toRestModuleReference) .collect(Collectors.toList()); return new ResponseEntity<>(restModuleReferences, HttpStatus.OK); diff --git a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy index 361167e569..43403fa890 100644 --- a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy +++ b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy @@ -416,12 +416,12 @@ class NetworkCmProxyControllerSpec extends Specification { def 'Getting module definitions filtering on #scenario'() { when: 'get module definition request is performed' def response = mvc.perform( - get("$ncmpBasePathV1/ch/some-cmhandle/modules/definitions?module-name=" + moduleName + "&revision=" + revision)) + get("$ncmpBasePathV1/ch/some-cmhandle-reference/modules/definitions?module-name=" + moduleName + "&revision=" + revision)) .andReturn().response - then: 'ncmp service method to get definitions by cm handle is invoked when needed' - numberOfCallsToByCmHandleId * mockNetworkCmProxyInventoryFacade.getModuleDefinitionsByCmHandleId('some-cmhandle') >> [] + then: 'ncmp service method to get definitions by cm handle reference is invoked when needed' + numberOfCallsToByCmHandleId * mockNetworkCmProxyInventoryFacade.getModuleDefinitionsByCmHandleReference('some-cmhandle-reference') >> [] and: 'ncmp service method to get definitions by module is invoked when needed' - numberOfCallsToByModule * mockNetworkCmProxyInventoryFacade.getModuleDefinitionsByCmHandleAndModule('some-cmhandle', moduleName, revision) >> [] + numberOfCallsToByModule * mockNetworkCmProxyInventoryFacade.getModuleDefinitionsByCmHandleAndModule('some-cmhandle-reference', moduleName, revision) >> [] and: 'response returns an OK http code' response.status == HttpStatus.OK.value() and: 'the correct message is logged when needed' diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/NetworkCmProxyInventoryFacade.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/NetworkCmProxyInventoryFacade.java index 07c1a8b257..cde4eacbf2 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/NetworkCmProxyInventoryFacade.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/NetworkCmProxyInventoryFacade.java @@ -101,36 +101,39 @@ public class NetworkCmProxyInventoryFacade { /** - * Retrieve module references for the given cm handle. + * Retrieve module references for the given cm handle reference. * - * @param cmHandleId cm handle identifier + * @param cmHandleReference cm handle or alternate id identifier * @return a collection of modules names and revisions */ - public Collection<ModuleReference> getYangResourcesModuleReferences(final String cmHandleId) { + public Collection<ModuleReference> getYangResourcesModuleReferences(final String cmHandleReference) { + final String cmHandleId = alternateIdMatcher.getCmHandleId(cmHandleReference); return inventoryPersistence.getYangResourcesModuleReferences(cmHandleId); } /** * Retrieve module definitions for the given cm handle. * - * @param cmHandleId cm handle identifier + * @param cmHandleReference cm handle or alternate id identifier * @return a collection of module definition (moduleName, revision and yang resource content) */ - public Collection<ModuleDefinition> getModuleDefinitionsByCmHandleId(final String cmHandleId) { + public Collection<ModuleDefinition> getModuleDefinitionsByCmHandleReference(final String cmHandleReference) { + final String cmHandleId = alternateIdMatcher.getCmHandleId(cmHandleReference); return inventoryPersistence.getModuleDefinitionsByCmHandleId(cmHandleId); } /** * Get module definitions for the given parameters. * - * @param cmHandleId cm-handle identifier - * @param moduleName module name - * @param moduleRevision the revision of the module + * @param cmHandleReference cm handle or alternate id identifier + * @param moduleName module name + * @param moduleRevision the revision of the module * @return list of module definitions (module name, revision, yang resource content) */ - public Collection<ModuleDefinition> getModuleDefinitionsByCmHandleAndModule(final String cmHandleId, + public Collection<ModuleDefinition> getModuleDefinitionsByCmHandleAndModule(final String cmHandleReference, final String moduleName, final String moduleRevision) { + final String cmHandleId = alternateIdMatcher.getCmHandleId(cmHandleReference); return inventoryPersistence.getModuleDefinitionsByCmHandleAndModule(cmHandleId, moduleName, moduleRevision); } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManager.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManager.java index 33310b955e..aff0e19981 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManager.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManager.java @@ -145,17 +145,13 @@ public class TrustLevelManager { } /** - * Remove cm handle trust level from the cache and publish notification for trust level of cmHandles - * if it is COMPLETE. + * Remove cm handle trust level from the cache. * * @param cmHandleIds cm handle ids to be removed from the cache */ public void removeCmHandles(final Collection<String> cmHandleIds) { for (final String cmHandleId : cmHandleIds) { - if (trustLevelPerCmHandle.containsKey(cmHandleId)) { - final TrustLevel oldTrustLevel = trustLevelPerCmHandle.remove(cmHandleId); - sendAvcNotificationIfRequired(cmHandleId, oldTrustLevel, TrustLevel.NONE); - } else { + if (trustLevelPerCmHandle.remove(cmHandleId) == null) { log.debug("Removed Cm handle: {} is not in trust level cache", cmHandleId); } } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/NetworkCmProxyInventoryFacadeSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/NetworkCmProxyInventoryFacadeSpec.groovy index 165704618c..9e07de48bf 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/NetworkCmProxyInventoryFacadeSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/NetworkCmProxyInventoryFacadeSpec.groovy @@ -51,7 +51,6 @@ class NetworkCmProxyInventoryFacadeSpec extends Specification { def mockTrustLevelManager = Mock(TrustLevelManager) def mockAlternateIdMatcher = Mock(AlternateIdMatcher) def objectUnderTest = new NetworkCmProxyInventoryFacade(mockCmHandleRegistrationService, mockCmHandleQueryService, mockParameterizedCmHandleQueryService, mockInventoryPersistence, spiedJsonObjectMapper, mockTrustLevelManager, mockAlternateIdMatcher) - def trustLevelPerCmHandle = [:] def 'Update DMI Registration'() { given: 'an (updated) dmi plugin registration' @@ -90,11 +89,17 @@ class NetworkCmProxyInventoryFacadeSpec extends Specification { assert result.containsAll('cm-handle-1','cm-handle-2') } - def 'Getting Yang Resources.'() { + def 'Getting Yang Resources for a given #scenario'() { when: 'yang resources is called' - objectUnderTest.getYangResourcesModuleReferences('some-cm-handle') - then: 'CPS module services is invoked for the correct dataspace and cm handle' + objectUnderTest.getYangResourcesModuleReferences(cmHandleRef) + then: 'alternate id matcher is called' + mockAlternateIdMatcher.getCmHandleId(cmHandleRef) >> 'some-cm-handle' + and: 'CPS module services is invoked for the correct cm handle' 1 * mockInventoryPersistence.getYangResourcesModuleReferences('some-cm-handle') + where: 'following cm handle reference is used' + scenario | cmHandleRef + 'Cm Handle Reference as cm handle-id' | 'some-cm-handle' + 'Cm Handle Reference as alternate-id' | 'some-alternate-id' } def 'Get a cm handle details using #scenario'() { @@ -203,18 +208,30 @@ class NetworkCmProxyInventoryFacadeSpec extends Specification { assert result == ['cm-handle-id-1'] } - def 'Getting module definitions by module'() { - when: 'get module definitions is performed with module name' - objectUnderTest.getModuleDefinitionsByCmHandleAndModule('some-cm-handle', 'some-module', '2021-08-04') - then: 'ncmp inventory persistence service is invoked once with correct parameters' + def 'Getting module definitions by module for a given #scenario'() { + when: 'get module definitions is performed with module name and cm handle reference' + objectUnderTest.getModuleDefinitionsByCmHandleAndModule(cmHandleRef, 'some-module', '2021-08-04') + then: 'alternate id matcher returns some cm handle id for a given cm handle reference' + mockAlternateIdMatcher.getCmHandleId(cmHandleRef) >> 'some-cm-handle' + and: 'ncmp inventory persistence service is invoked once with correct parameters' 1 * mockInventoryPersistence.getModuleDefinitionsByCmHandleAndModule('some-cm-handle', 'some-module', '2021-08-04') + where: 'following cm handle reference is used' + scenario | cmHandleRef + 'Cm Handle Reference as cm handle-id' | 'some-cm-handle' + 'Cm Handle Reference as alternate-id' | 'some-alternate-id' } - def 'Getting module definitions by cm handle id'() { - when: 'get module definitions is performed with cm handle id' - objectUnderTest.getModuleDefinitionsByCmHandleId('some-cm-handle') + def 'Getting module definitions for a given #scenario'() { + when: 'get module definitions is performed with cm handle reference' + objectUnderTest.getModuleDefinitionsByCmHandleReference(cmHandleRef) + then: 'alternate id matcher returns some cm handle id for a given cm handle reference' + mockAlternateIdMatcher.getCmHandleId(cmHandleRef) >> 'some-cm-handle' then: 'ncmp inventory persistence service is invoked once with correct parameter' 1 * mockInventoryPersistence.getModuleDefinitionsByCmHandleId('some-cm-handle') + where: 'following cm handle reference is used' + scenario | cmHandleRef + 'Cm Handle Reference as cm handle-id' | 'some-cm-handle' + 'Cm Handle Reference as alternate-id' | 'some-alternate-id' } def 'Execute cm handle search'() { diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManagerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManagerSpec.groovy index 84d93e0b7f..7dc9602e46 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManagerSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManagerSpec.groovy @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2023 Nordix Foundation + * Copyright (C) 2023-2024 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -146,26 +146,13 @@ class TrustLevelManagerSpec extends Specification { assert effectiveTrustLevel == TrustLevel.NONE } - def 'CmHandle trust level (COMPLETE) removed'() { - given: 'a trusted cm handle' + def 'CmHandle trust level removed'() { + given: 'a cm handle' trustLevelPerCmHandle.put('ch-1', TrustLevel.COMPLETE) when: 'the remove is handled' objectUnderTest.removeCmHandles(['ch-1']) then: 'cm handle removed from the cache' assert trustLevelPerCmHandle.get('ch-1') == null - and: 'notification is sent' - 1 * mockAttributeValueChangeEventPublisher.publishAvcEvent(_,'trustLevel','COMPLETE','NONE') - } - - def 'CmHandle trust level (NONE) removed'() { - given: 'a non-trusted cm handle' - trustLevelPerCmHandle.put('ch-1', TrustLevel.NONE) - when: 'the remove is handled' - objectUnderTest.removeCmHandles(['ch-1']) - then: 'cm handle removed from the cache' - assert trustLevelPerCmHandle.get('ch-1') == null - and: 'no notification is sent' - 0 * mockAttributeValueChangeEventPublisher.publishAvcEvent(*_) } } diff --git a/cps-path-parser/src/main/antlr4/org/onap/cps/cpspath/parser/antlr4/CpsPath.g4 b/cps-path-parser/src/main/antlr4/org/onap/cps/cpspath/parser/antlr4/CpsPath.g4 index 3aef120fed..be8d968fcb 100644 --- a/cps-path-parser/src/main/antlr4/org/onap/cps/cpspath/parser/antlr4/CpsPath.g4 +++ b/cps-path-parser/src/main/antlr4/org/onap/cps/cpspath/parser/antlr4/CpsPath.g4 @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2021-2023 Nordix Foundation + * Copyright (C) 2021-2024 Nordix Foundation * Modifications Copyright (C) 2023 TechMahindra Ltd * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -27,7 +27,7 @@ grammar CpsPath ; -cpsPath : ( prefix | descendant | incorrectPrefix ) multipleLeafConditions? textFunctionCondition? containsFunctionCondition? ancestorAxis? invalidPostFix?; +cpsPath : ( prefix | descendant ) multipleLeafConditions? textFunctionCondition? containsFunctionCondition? ancestorAxis? EOF ; ancestorAxis : SLASH KW_ANCESTOR COLONCOLON ancestorPath ; @@ -43,8 +43,6 @@ prefix : parent SLASH containerName ; descendant : SLASH prefix ; -incorrectPrefix : SLASH SLASH SLASH+ ; - yangElement : containerName listElementRef? ; containerName : QName ; @@ -61,8 +59,6 @@ booleanOperators : ( KW_AND | KW_OR ) ; comparativeOperators : ( EQ | GT | LT | GE | LE ) ; -invalidPostFix : (AT | CB | COLONCOLON | comparativeOperators ).+ ; - /* * Lexer Rules * Most of the lexer rules below are inspired by 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 0bb09235ff..0325bdcacb 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 @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2021-2023 Nordix Foundation + * Copyright (C) 2021-2024 Nordix Foundation * Modifications Copyright (C) 2023 TechMahindra Ltd * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -29,7 +29,6 @@ import org.onap.cps.cpspath.parser.antlr4.CpsPathBaseListener; import org.onap.cps.cpspath.parser.antlr4.CpsPathParser; import org.onap.cps.cpspath.parser.antlr4.CpsPathParser.AncestorAxisContext; import org.onap.cps.cpspath.parser.antlr4.CpsPathParser.DescendantContext; -import org.onap.cps.cpspath.parser.antlr4.CpsPathParser.IncorrectPrefixContext; import org.onap.cps.cpspath.parser.antlr4.CpsPathParser.LeafConditionContext; import org.onap.cps.cpspath.parser.antlr4.CpsPathParser.MultipleLeafConditionsContext; import org.onap.cps.cpspath.parser.antlr4.CpsPathParser.PrefixContext; @@ -43,7 +42,7 @@ public class CpsPathBuilder extends CpsPathBaseListener { private final CpsPathQuery cpsPathQuery = new CpsPathQuery(); - private final List<CpsPathQuery.DataLeaf> leavesData = new ArrayList<>(); + private final List<CpsPathQuery.LeafCondition> leafConditions = new ArrayList<>(); private final StringBuilder normalizedXpathBuilder = new StringBuilder(); @@ -55,13 +54,6 @@ public class CpsPathBuilder extends CpsPathBaseListener { private final List<String> booleanOperators = new ArrayList<>(); - private final List<String> comparativeOperators = new ArrayList<>(); - - @Override - public void exitInvalidPostFix(final CpsPathParser.InvalidPostFixContext ctx) { - throw new PathParsingException(ctx.getText()); - } - @Override public void exitPrefix(final PrefixContext ctx) { cpsPathQuery.setXpathPrefix(normalizedXpathBuilder.toString()); @@ -73,12 +65,9 @@ public class CpsPathBuilder extends CpsPathBaseListener { } @Override - public void exitIncorrectPrefix(final IncorrectPrefixContext ctx) { - throw new PathParsingException("CPS path can only start with one or two slashes (/)"); - } - - @Override public void exitLeafCondition(final LeafConditionContext ctx) { + final String leafName = ctx.leafName().getText(); + final String operator = ctx.comparativeOperators().getText(); final Object comparisonValue; if (ctx.IntegerLiteral() != null) { comparisonValue = Integer.valueOf(ctx.IntegerLiteral().getText()); @@ -87,7 +76,7 @@ public class CpsPathBuilder extends CpsPathBaseListener { } else { throw new PathParsingException("Unsupported comparison value encountered in expression" + ctx.getText()); } - leafContext(ctx.leafName(), comparisonValue); + leafContext(leafName, operator, comparisonValue); } @Override @@ -96,11 +85,6 @@ public class CpsPathBuilder extends CpsPathBaseListener { } @Override - public void exitComparativeOperators(final CpsPathParser.ComparativeOperatorsContext ctx) { - comparativeOperators.add(ctx.getText()); - } - - @Override public void exitDescendant(final DescendantContext ctx) { cpsPathQuery.setCpsPathPrefixType(DESCENDANT); cpsPathQuery.setDescendantName(normalizedXpathBuilder.substring(1)); @@ -110,15 +94,14 @@ public class CpsPathBuilder extends CpsPathBaseListener { @Override public void enterMultipleLeafConditions(final MultipleLeafConditionsContext ctx) { normalizedXpathBuilder.append(OPEN_BRACKET); - leavesData.clear(); + leafConditions.clear(); booleanOperators.clear(); - comparativeOperators.clear(); } @Override public void exitMultipleLeafConditions(final MultipleLeafConditionsContext ctx) { normalizedXpathBuilder.append(CLOSE_BRACKET); - cpsPathQuery.setLeavesData(leavesData); + cpsPathQuery.setLeafConditions(leafConditions); } @Override @@ -164,7 +147,6 @@ public class CpsPathBuilder extends CpsPathBaseListener { cpsPathQuery.setNormalizedXpath(normalizedXpathBuilder.toString()); cpsPathQuery.setContainerNames(containerNames); cpsPathQuery.setBooleanOperators(booleanOperators); - cpsPathQuery.setComparativeOperators(comparativeOperators); if (cpsPathQuery.hasAncestorAxis() && cpsPathQuery.getXpathPrefix() .endsWith("/" + cpsPathQuery.getAncestorSchemaNodeIdentifier())) { cpsPathQuery.setAncestorSchemaNodeIdentifier(""); @@ -183,16 +165,16 @@ public class CpsPathBuilder extends CpsPathBaseListener { } } - private void leafContext(final CpsPathParser.LeafNameContext ctx, final Object comparisonValue) { - leavesData.add(new CpsPathQuery.DataLeaf(ctx.getText(), comparisonValue)); - appendCondition(normalizedXpathBuilder, ctx.getText(), comparisonValue); + private void leafContext(final String leafName, final String operator, final Object comparisonValue) { + leafConditions.add(new CpsPathQuery.LeafCondition(leafName, operator, comparisonValue)); + appendCondition(normalizedXpathBuilder, leafName, operator, comparisonValue); if (processingAncestorAxis) { - appendCondition(normalizedAncestorPathBuilder, ctx.getText(), comparisonValue); + appendCondition(normalizedAncestorPathBuilder, leafName, operator, comparisonValue); } } private void appendCondition(final StringBuilder currentNormalizedPathBuilder, final String name, - final Object value) { + final String operator, final Object value) { final char lastCharacter = currentNormalizedPathBuilder.charAt(currentNormalizedPathBuilder.length() - 1); final boolean isStartOfExpression = lastCharacter == '['; if (!isStartOfExpression) { @@ -200,7 +182,7 @@ public class CpsPathBuilder extends CpsPathBaseListener { } currentNormalizedPathBuilder.append("@") .append(name) - .append(getLastElement(comparativeOperators)) + .append(operator) .append("'") .append(value.toString().replace("'", "''")) .append("'"); diff --git a/cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathQuery.java b/cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathQuery.java index f98df05a28..03602b64f6 100644 --- a/cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathQuery.java +++ b/cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathQuery.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2021-2023 Nordix Foundation + * Copyright (C) 2021-2024 Nordix Foundation * Modifications Copyright (C) 2023 TechMahindra Ltd * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,8 +25,6 @@ import static org.onap.cps.cpspath.parser.CpsPathPrefixType.ABSOLUTE; import java.util.List; import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; @@ -40,12 +38,11 @@ public class CpsPathQuery { private List<String> containerNames; private CpsPathPrefixType cpsPathPrefixType = ABSOLUTE; private String descendantName; - private List<DataLeaf> leavesData; + private List<LeafCondition> leafConditions; private String ancestorSchemaNodeIdentifier = ""; private String textFunctionConditionLeafName; private String textFunctionConditionValue; private List<String> booleanOperators; - private List<String> comparativeOperators; private String containsFunctionConditionLeafName; private String containsFunctionConditionValue; @@ -74,7 +71,7 @@ public class CpsPathQuery { * @return boolean value. */ public boolean hasLeafConditions() { - return leavesData != null; + return leafConditions != null; } /** @@ -104,11 +101,6 @@ public class CpsPathQuery { return cpsPathPrefixType == ABSOLUTE && hasLeafConditions(); } - @Getter - @EqualsAndHashCode - @AllArgsConstructor - public static class DataLeaf { - private final String name; - private final Object value; - } + public record LeafCondition(String name, String operator, Object value) { } + } 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 15f6b11823..730c826332 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 @@ -48,8 +48,8 @@ class CpsPathQuerySpec extends Specification { and: 'the right query parameters are set' assert result.xpathPrefix == expectedXpathPrefix assert result.hasLeafConditions() - assert result.leavesData[0].name == expectedLeafName - assert result.leavesData[0].value == expectedLeafValue + assert result.leafConditions[0].name() == expectedLeafName + assert result.leafConditions[0].value() == expectedLeafValue where: 'the following data is used' scenario | cpsPath || expectedXpathPrefix | expectedLeafName | expectedLeafValue 'leaf of type String' | '/parent/child[@common-leaf-name="common-leaf-value"]' || '/parent/child' | 'common-leaf-name' | 'common-leaf-value' @@ -123,11 +123,11 @@ class CpsPathQuerySpec extends Specification { when: 'the given cps path is parsed' def result = CpsPathQuery.createFrom(cpsPath) then: 'the expected number of leaves are returned' - result.leavesData.size() == expectedNumberOfLeaves + result.leafConditions.size() == expectedNumberOfLeaves and: 'the given operator(s) returns in the correct order' result.booleanOperators == expectedOperators and: 'the given comparativeOperator(s) returns in the correct order' - result.comparativeOperators == expectedComparativeOperator + result.leafConditions.operator == expectedComparativeOperator where: 'the following data is used' cpsPath || expectedNumberOfLeaves || expectedOperators || expectedComparativeOperator '/parent[@code=1]/child[@common-leaf-name-int=5]' || 1 || [] || ['='] @@ -234,19 +234,19 @@ class CpsPathQuerySpec extends Specification { when: 'the given cps path is parsed using multiple conditions on same leaf' def result = CpsPathQuery.createFrom('/test[@same-name="value1" or @same-name="value2"]') then: 'two leaves are present with correct values' - assert result.leavesData.size() == 2 - assert result.leavesData[0].name == "same-name" - assert result.leavesData[0].value == "value1" - assert result.leavesData[1].name == "same-name" - assert result.leavesData[1].value == "value2" + assert result.leafConditions.size() == 2 + assert result.leafConditions[0].name == "same-name" + assert result.leafConditions[0].value == "value1" + assert result.leafConditions[1].name == "same-name" + assert result.leafConditions[1].value == "value2" } def 'Ordering of data leaves is preserved.'() { when: 'the given cps path is parsed' def result = CpsPathQuery.createFrom(cpsPath) then: 'the order of the data leaves is preserved' - assert result.leavesData[0].name == expectedFirstLeafName - assert result.leavesData[1].name == expectedSecondLeafName + assert result.leafConditions[0].name == expectedFirstLeafName + assert result.leafConditions[1].name == expectedSecondLeafName where: 'the following data is used' cpsPath || expectedFirstLeafName | expectedSecondLeafName '/test[@name1="value1" and @name2="value2"]' || 'name1' | 'name2' diff --git a/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentQueryBuilder.java b/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentQueryBuilder.java index b2014757d7..8171bbe621 100644 --- a/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentQueryBuilder.java +++ b/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentQueryBuilder.java @@ -194,22 +194,20 @@ public class FragmentQueryBuilder { private void queryLeafConditions(final CpsPathQuery cpsPathQuery, final StringBuilder sqlStringBuilder) { sqlStringBuilder.append(" AND ("); final Queue<String> booleanOperatorsQueue = new LinkedList<>(cpsPathQuery.getBooleanOperators()); - final Queue<String> comparativeOperatorQueue = new LinkedList<>(cpsPathQuery.getComparativeOperators()); - cpsPathQuery.getLeavesData().forEach(leaf -> { - final String nextComparativeOperator = comparativeOperatorQueue.poll(); - if (leaf.getValue() instanceof Integer) { - sqlStringBuilder.append("(attributes ->> '").append(leaf.getName()).append("')\\:\\:int"); - sqlStringBuilder.append(nextComparativeOperator); - sqlStringBuilder.append(leaf.getValue()); + cpsPathQuery.getLeafConditions().forEach(leafCondition -> { + if (leafCondition.value() instanceof Integer) { + sqlStringBuilder.append("(attributes ->> '").append(leafCondition.name()).append("')\\:\\:int"); + sqlStringBuilder.append(leafCondition.operator()); + sqlStringBuilder.append(leafCondition.value()); } else { - if ("=".equals(nextComparativeOperator)) { - final String leafValueAsText = leaf.getValue().toString(); - sqlStringBuilder.append("attributes ->> '").append(leaf.getName()).append("'"); + if ("=".equals(leafCondition.operator())) { + final String leafValueAsText = leafCondition.value().toString(); + sqlStringBuilder.append("attributes ->> '").append(leafCondition.name()).append("'"); sqlStringBuilder.append(" = '"); sqlStringBuilder.append(EscapeUtils.escapeForSqlStringLiteral(leafValueAsText)); sqlStringBuilder.append("'"); } else { - throw new CpsPathException(" can use only " + nextComparativeOperator + " with integer "); + throw new CpsPathException(" can use only " + leafCondition.operator() + " with integer "); } } if (!booleanOperatorsQueue.isEmpty()) { diff --git a/csit/tests/cps-trust-level/cps-trust-level.robot b/csit/tests/cps-trust-level/cps-trust-level.robot index 4db0115871..810bcf4d12 100644 --- a/csit/tests/cps-trust-level/cps-trust-level.robot +++ b/csit/tests/cps-trust-level/cps-trust-level.robot @@ -36,7 +36,7 @@ ${ncmpBasePath} /ncmp/v1 ${dmiUrl} http://${DMI_HOST}:${DMI_PORT} ${jsonCreateCmHandles} {"dmiPlugin":"${dmiUrl}","dmiDataPlugin":"","dmiModelPlugin":"","createdCmHandles":[{"trustLevel":"COMPLETE","cmHandle":"CH-1"},{"trustLevel":"COMPLETE","cmHandle":"CH-2"},{"cmHandle":"CH-3"},{"trustLevel":"NONE","cmHandle":"CH-4"}]} ${jsonTrustLevelPropertyQueryParameters} {"cmHandleQueryParameters": [{"conditionName": "cmHandleWithTrustLevel", "conditionParameters": [ {"trustLevel": "COMPLETE"} ] }]} -${jsonTrustLevelEventPayload} {"data":{"attributeValueChange":[{"attributeName":"trustLevel","oldAttributeValue":"COMPLETE","newAttributeValue":"NONE"}]}} +${jsonTrustLevelEventPayload} {"data":{"attributeValueChange":[{"attributeName":"trustLevel","newAttributeValue":"NONE"}]}} *** Test Cases *** Register data node @@ -55,7 +55,7 @@ Verify notification Compare Header Values ${header_key_value_pair[0]} ${header_key_value_pair[1]} "ce_specversion" "1.0" Compare Header Values ${header_key_value_pair[0]} ${header_key_value_pair[1]} "ce_source" "NCMP" Compare Header Values ${header_key_value_pair[0]} ${header_key_value_pair[1]} "ce_type" "org.onap.cps.ncmp.events.avc.ncmp_to_client.AvcEvent" - Compare Header Values ${header_key_value_pair[0]} ${header_key_value_pair[1]} "ce_correlationid" "CmHandleForDelete" + Compare Header Values ${header_key_value_pair[0]} ${header_key_value_pair[1]} "ce_correlationid" "CH-4" END Should Be Equal As Strings ${payload} ${jsonTrustLevelEventPayload} [Teardown] Basic Teardown ${group_id} diff --git a/docker-compose/docker-compose.yml b/docker-compose/docker-compose.yml index 6b372c189c..f79c03dbab 100644 --- a/docker-compose/docker-compose.yml +++ b/docker-compose/docker-compose.yml @@ -139,6 +139,7 @@ services: KAFKA_BOOTSTRAP_SERVER: kafka:29092 NCMP_CONSUMER_GROUP_ID: ncmp-group NCMP_ASYNC_M2M_TOPIC: ncmp-async-m2m + MODULE_INITIAL_PROCESSING_DELAY_MS: 0 MODULE_REFERENCES_DELAY_MS: 100 MODULE_RESOURCES_DELAY_MS: 1000 READ_DATA_FOR_CM_HANDLE_DELAY_MS: 300 |