From: danielhanrahan Date: Wed, 12 Jul 2023 15:11:07 +0000 (+0100) Subject: Fix handling of special characters in prefix names X-Git-Tag: 3.3.4~6 X-Git-Url: https://gerrit.onap.org/r/gitweb?a=commitdiff_plain;h=d45fe759ba6d693fcaa9247f89d28c6a3162b2c0;p=cps.git Fix handling of special characters in prefix names This fixes issues with special characters like square brackets - Make PrefixResolver use CpsPathParser instead of regex - Make DataMapUtils use CpsPathParser instead of String parsing Issue-ID: CPS-1758 Signed-off-by: danielhanrahan Change-Id: I6dd66eee398a46a69c0229059195f5096ab6fdec --- 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 b0e109baf..b4d5a0944 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-2022 Nordix Foundation + * Modifications (C) 2021-2023 Nordix Foundation * Modifications Copyright (C) 2022 Bell Canada * Modifications Copyright (C) 2022-2023 TechMahindra Ltd. * ================================================================================ @@ -33,6 +33,8 @@ import java.util.Collections; import java.util.Map; import lombok.AccessLevel; import lombok.NoArgsConstructor; +import org.onap.cps.cpspath.parser.CpsPathQuery; +import org.onap.cps.cpspath.parser.CpsPathUtil; import org.onap.cps.spi.model.DataNode; @NoArgsConstructor(access = AccessLevel.PRIVATE) @@ -106,8 +108,9 @@ public class DataMapUtils { } private static String getNodeIdentifier(String xpath) { - if (xpath.endsWith("]")) { - xpath = xpath.substring(0, xpath.lastIndexOf('[')); + final CpsPathQuery cpsPathQuery = CpsPathUtil.getCpsPathQuery(xpath); + if (cpsPathQuery.isPathToListElement()) { + xpath = cpsPathQuery.getXpathPrefix(); } final int fromIndex = xpath.lastIndexOf('/') + 1; return xpath.substring(fromIndex); diff --git a/cps-service/src/main/java/org/onap/cps/utils/PrefixResolver.java b/cps-service/src/main/java/org/onap/cps/utils/PrefixResolver.java index 58b239c34..d58ddf4fa 100644 --- a/cps-service/src/main/java/org/onap/cps/utils/PrefixResolver.java +++ b/cps-service/src/main/java/org/onap/cps/utils/PrefixResolver.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022 Nordix Foundation. + * Copyright (C) 2022-2023 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,12 +25,13 @@ import java.io.Serializable; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import lombok.RequiredArgsConstructor; import org.onap.cps.api.CpsAdminService; import org.onap.cps.api.impl.YangTextSchemaSourceSetCache; import org.onap.cps.cache.AnchorDataCacheEntry; +import org.onap.cps.cpspath.parser.CpsPathPrefixType; +import org.onap.cps.cpspath.parser.CpsPathQuery; +import org.onap.cps.cpspath.parser.CpsPathUtil; import org.onap.cps.spi.model.Anchor; import org.onap.cps.yang.YangTextSchemaSourceSet; import org.opendaylight.yangtools.yang.common.QNameModule; @@ -53,9 +54,6 @@ public class PrefixResolver { private final IMap anchorDataCache; - private static final Pattern TOP_LEVEL_NODE_NAME_FINDER - = Pattern.compile("\\/([\\w-]*)(\\[@(?!.*\\[).*?])?(\\/.*)?"); //NOSONAR - /** * Get the module prefix for the given xpath for a dataspace and anchor name. * @@ -93,9 +91,9 @@ public class PrefixResolver { private String getPrefixForTopContainer(final Map prefixPerContainerName, final String xpath) { - final Matcher matcher = TOP_LEVEL_NODE_NAME_FINDER.matcher(xpath); - if (matcher.matches()) { - final String topLevelContainerName = matcher.group(1); + final CpsPathQuery cpsPathQuery = CpsPathUtil.getCpsPathQuery(xpath); + if (cpsPathQuery.getCpsPathPrefixType() == CpsPathPrefixType.ABSOLUTE) { + final String topLevelContainerName = cpsPathQuery.getContainerNames().get(0); if (prefixPerContainerName.containsKey(topLevelContainerName)) { return prefixPerContainerName.get(topLevelContainerName); } 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 c636f4b5f..29085a9c7 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 @@ -68,8 +68,8 @@ class DataMapUtilsSpec extends Specification { scenario | xPath | expectedNodeIdentifier 'container xpath' | '/bookstore' | 'sampleModuleName:bookstore' 'xpath contains list attribute' | '/bookstore/categories[@code=1]' | 'sampleModuleName:categories' - 'xpath contains list attributes with /' | '/bookstore/categories[@code=1/2]' | 'sampleModuleName:categories' - + 'xpath contains list attributes with /' | '/bookstore/categories[@code="1/2"]' | 'sampleModuleName:categories' + 'xpath contains list attributes with [' | '/bookstore/categories[@code="[1]"]' | 'sampleModuleName:categories' } def 'Data node structure with anchor name conversion to map with root node identifier.'() { @@ -98,7 +98,7 @@ class DataMapUtilsSpec extends Specification { def dataNode = buildDataNode( "/parent",[parentLeaf:'parentLeafValue', parentLeafList:['parentLeafListEntry1','parentLeafListEntry2']],[ - buildDataNode('/parent/child-list[@id=1/2]',[listElementLeaf:'listElement1leafValue'],noChildren), + buildDataNode('/parent/child-list[@id="1/2"]',[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)] @@ -107,7 +107,7 @@ class DataMapUtilsSpec extends Specification { def dataNodeWithAnchor = buildDataNodeWithAnchor( "/parent", 'anchor01',[parentLeaf:'parentLeafValue', parentLeafList:['parentLeafListEntry1','parentLeafListEntry2']],[ - buildDataNode('/parent/child-list[@id=1/2]',[listElementLeaf:'listElement1leafValue'],noChildren), + buildDataNode('/parent/child-list[@id="1/2"]',[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)] diff --git a/cps-service/src/test/groovy/org/onap/cps/utils/PrefixResolverSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/utils/PrefixResolverSpec.groovy index 4c1b89116..ff6ab346f 100644 --- a/cps-service/src/test/groovy/org/onap/cps/utils/PrefixResolverSpec.groovy +++ b/cps-service/src/test/groovy/org/onap/cps/utils/PrefixResolverSpec.groovy @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2021-2022 Nordix Foundation + * Copyright (C) 2021-2023 Nordix Foundation * Modifications Copyright (C) 2021 Pantheon.tech * Modifications Copyright (C) 2021-2022 Bell Canada. * ================================================================================ @@ -77,8 +77,9 @@ class PrefixResolverSpec extends Specification { '/test-tree/with/descendants' || 'tree' '/test-tree[@id=1]' || 'tree' '/test-tree[@id=1]/child' || 'tree' + '/test-tree[@id="[1]"]/child' || 'tree' + '//test-tree' || '' '/not-defined' || '' - 'invalid-xpath' || '' } def 'get prefix with populated anchor data cache with #scenario cache entry'() {