aboutsummaryrefslogtreecommitdiffstats
path: root/cps-path-parser
diff options
context:
space:
mode:
Diffstat (limited to 'cps-path-parser')
-rw-r--r--cps-path-parser/pom.xml2
-rw-r--r--cps-path-parser/src/main/antlr4/org/onap/cps/cpspath/parser/antlr4/CpsPath.g427
-rw-r--r--cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathBuilder.java78
-rw-r--r--cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathQuery.java18
-rw-r--r--cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathUtil.java8
-rw-r--r--cps-path-parser/src/test/groovy/org/onap/cps/cpspath/parser/CpsPathQuerySpec.groovy27
-rw-r--r--cps-path-parser/src/test/groovy/org/onap/cps/cpspath/parser/CpsPathUtilSpec.groovy59
7 files changed, 108 insertions, 111 deletions
diff --git a/cps-path-parser/pom.xml b/cps-path-parser/pom.xml
index 633ec6bb80..57b1e6b247 100644
--- a/cps-path-parser/pom.xml
+++ b/cps-path-parser/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.onap.cps</groupId>
<artifactId>cps-parent</artifactId>
- <version>3.5.1-SNAPSHOT</version>
+ <version>3.5.5-SNAPSHOT</version>
<relativePath>../cps-parent/pom.xml</relativePath>
</parent>
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..74b99feb33 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,23 +27,23 @@
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 ;
+slash : SLASH ;
-ancestorPath : yangElement ( SLASH yangElement)* ;
+ancestorAxis : KW_ANCESTOR_AXIS_PREFIX ancestorPath ;
-textFunctionCondition : SLASH leafName OB KW_TEXT_FUNCTION EQ StringLiteral CB ;
+ancestorPath : yangElement ( slash yangElement)* ;
-containsFunctionCondition : OB KW_CONTAINS_FUNCTION OP AT leafName COMMA StringLiteral CP CB ;
+textFunctionCondition : slash leafName OB KW_TEXT_FUNCTION EQ StringLiteral CB ;
-parent : ( SLASH yangElement)* ;
+containsFunctionCondition : OB KW_CONTAINS_FUNCTION OP AT leafName COMMA StringLiteral CP CB ;
-prefix : parent SLASH containerName ;
+parent : ( slash yangElement)* ;
-descendant : SLASH prefix ;
+prefix : parent slash containerName ;
-incorrectPrefix : SLASH SLASH SLASH+ ;
+descendant : slash prefix ;
yangElement : containerName listElementRef? ;
@@ -61,8 +61,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
@@ -89,10 +87,11 @@ KW_ANCESTOR : 'ancestor' ;
KW_AND : 'and' ;
KW_TEXT_FUNCTION: 'text()' ;
KW_OR : 'or' ;
-KW_CONTAINS_FUNCTION: 'contains' ;
+KW_CONTAINS_FUNCTION : 'contains' ;
+KW_ANCESTOR_AXIS_PREFIX : SLASH KW_ANCESTOR COLONCOLON ;
IntegerLiteral : FragDigits ;
-// Add below type definitions for leafvalue comparision in https://jira.onap.org/browse/CPS-440
+// Add below type definitions for leafvalue comparision in https://lf-onap.atlassian.net/CPS-440
DecimalLiteral : ('.' FragDigits) | (FragDigits '.' [0-9]*) ;
DoubleLiteral : (('.' FragDigits) | (FragDigits ('.' [0-9]*)?)) [eE] [+-]? FragDigits ;
StringLiteral : '"' (~["] | FragEscapeQuot)* '"' | '\'' (~['] | FragEscapeApos)* '\'' ;
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 de261e64b3..ed7dbecc18 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;
@@ -37,17 +36,19 @@ import org.onap.cps.cpspath.parser.antlr4.CpsPathParser.TextFunctionConditionCon
public class CpsPathBuilder extends CpsPathBaseListener {
+ private static final String NO_PARENT_PATH = "";
+
private static final String OPEN_BRACKET = "[";
private static final String CLOSE_BRACKET = "]";
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();
- private final StringBuilder normalizedAncestorPathBuilder = new StringBuilder();
+ private int startIndexOfAncestorSchemaNodeIdentifier = 0;
private boolean processingAncestorAxis = false;
@@ -55,11 +56,9 @@ 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());
+ public void exitSlash(final CpsPathParser.SlashContext ctx) {
+ normalizedXpathBuilder.append("/");
}
@Override
@@ -69,16 +68,19 @@ public class CpsPathBuilder extends CpsPathBaseListener {
@Override
public void exitParent(final CpsPathParser.ParentContext ctx) {
- cpsPathQuery.setNormalizedParentPath(normalizedXpathBuilder.toString());
- }
-
- @Override
- public void exitIncorrectPrefix(final IncorrectPrefixContext ctx) {
- throw new PathParsingException("CPS path can only start with one or two slashes (/)");
+ final String normalizedParentPath;
+ if (normalizedXpathBuilder.toString().equals("/")) {
+ normalizedParentPath = NO_PARENT_PATH;
+ } else {
+ normalizedParentPath = normalizedXpathBuilder.toString();
+ }
+ cpsPathQuery.setNormalizedParentPath(normalizedParentPath);
}
@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 +89,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,40 +98,36 @@ 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));
- normalizedXpathBuilder.insert(0, "/");
+ cpsPathQuery.setDescendantName(normalizedXpathBuilder.substring(2));
}
@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
public void enterAncestorAxis(final AncestorAxisContext ctx) {
processingAncestorAxis = true;
+ normalizedXpathBuilder.append("/ancestor::");
+ startIndexOfAncestorSchemaNodeIdentifier = normalizedXpathBuilder.length();
}
@Override
public void exitAncestorAxis(final AncestorAxisContext ctx) {
- cpsPathQuery.setAncestorSchemaNodeIdentifier(normalizedAncestorPathBuilder.substring(1));
processingAncestorAxis = false;
+ cpsPathQuery.setAncestorSchemaNodeIdentifier(
+ normalizedXpathBuilder.substring(startIndexOfAncestorSchemaNodeIdentifier));
}
@Override
@@ -147,48 +145,36 @@ public class CpsPathBuilder extends CpsPathBaseListener {
@Override
public void enterListElementRef(final CpsPathParser.ListElementRefContext ctx) {
normalizedXpathBuilder.append(OPEN_BRACKET);
- if (processingAncestorAxis) {
- normalizedAncestorPathBuilder.append(OPEN_BRACKET);
- }
}
@Override
public void exitListElementRef(final CpsPathParser.ListElementRefContext ctx) {
normalizedXpathBuilder.append(CLOSE_BRACKET);
- if (processingAncestorAxis) {
- normalizedAncestorPathBuilder.append(CLOSE_BRACKET);
- }
}
CpsPathQuery build() {
cpsPathQuery.setNormalizedXpath(normalizedXpathBuilder.toString());
cpsPathQuery.setContainerNames(containerNames);
cpsPathQuery.setBooleanOperators(booleanOperators);
- cpsPathQuery.setComparativeOperators(comparativeOperators);
return cpsPathQuery;
}
@Override
public void exitContainerName(final CpsPathParser.ContainerNameContext ctx) {
final String containerName = ctx.getText();
- normalizedXpathBuilder.append("/")
- .append(containerName);
- containerNames.add(containerName);
- if (processingAncestorAxis) {
- normalizedAncestorPathBuilder.append("/").append(containerName);
+ normalizedXpathBuilder.append(containerName);
+ if (!processingAncestorAxis) {
+ containerNames.add(containerName);
}
}
- private void leafContext(final CpsPathParser.LeafNameContext ctx, final Object comparisonValue) {
- leavesData.add(new CpsPathQuery.DataLeaf(ctx.getText(), comparisonValue));
- appendCondition(normalizedXpathBuilder, ctx.getText(), comparisonValue);
- if (processingAncestorAxis) {
- appendCondition(normalizedAncestorPathBuilder, 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);
}
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) {
@@ -196,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/main/java/org/onap/cps/cpspath/parser/CpsPathUtil.java b/cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathUtil.java
index bde9b0638f..4ede0d9c90 100644
--- a/cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathUtil.java
+++ b/cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathUtil.java
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2022-2023 Nordix Foundation
+ * Copyright (C) 2022-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.
@@ -59,12 +59,10 @@ public class CpsPathUtil {
return getCpsPathBuilder(xpathSource).build().getNormalizedParentPath();
}
- public static String[] getXpathNodeIdSequence(final String xpathSource) {
- final List<String> containerNames = getCpsPathBuilder(xpathSource).build().getContainerNames();
- return containerNames.toArray(new String[containerNames.size()]);
+ public static List<String> getXpathNodeIdSequence(final String xpathSource) {
+ return getCpsPathBuilder(xpathSource).build().getContainerNames();
}
-
/**
* Returns boolean indicating xpath is an absolute path to a list element.
*
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 ae7ee598ab..16430d2fa5 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
@@ -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");
@@ -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'
@@ -91,13 +91,14 @@ class CpsPathQuerySpec extends Specification {
'descendant with leaf condition has "<" operator' | '//cps-path[@key<10]' || "//cps-path[@key<'10']"
'descendant with leaf condition has ">=" operator' | '//cps-path[@key>=8]' || "//cps-path[@key>='8']"
'descendant with leaf condition has "<=" operator' | '//cps-path[@key<=12]' || "//cps-path[@key<='12']"
- 'descendant with leaf value and ancestor' | '//cps-path[@key=1]/ancestor:parent[@key=1]' || "//cps-path[@key='1']/ancestor:parent[@key='1']"
+ 'descendant with leaf value and ancestor' | '//cps-path[@key=1]/ancestor::parent[@key=1]' || "//cps-path[@key='1']/ancestor::parent[@key='1']"
'parent & child' | '/parent/child' || '/parent/child'
'parent leaf of type Integer & child' | '/parent/child[@code=1]/child2' || "/parent/child[@code='1']/child2"
'parent leaf with double quotes' | '/parent/child[@code="1"]/child2' || "/parent/child[@code='1']/child2"
'parent leaf with double quotes inside single quotes' | '/parent/child[@code=\'"1"\']/child2' || "/parent/child[@code='\"1\"']/child2"
'parent leaf with single quotes inside double quotes' | '/parent/child[@code="\'1\'"]/child2' || "/parent/child[@code='''1''']/child2"
'leaf with single quotes inside double quotes' | '/parent/child[@code="\'1\'"]' || "/parent/child[@code='''1''']"
+ 'leaf with single quotes inside single quotes' | "/parent/child[@code='I''m quoted']" || "/parent/child[@code='I''m quoted']"
'leaf with more than one attribute' | '/parent/child[@key1=1 and @key2="abc"]' || "/parent/child[@key1='1' and @key2='abc']"
'parent & child with more than one attribute' | '/parent/child[@key1=1 and @key2="abc"]/child2' || "/parent/child[@key1='1' and @key2='abc']/child2"
'leaf with more than one attribute has OR operator' | '/parent/child[@key1=1 or @key2="abc"]' || "/parent/child[@key1='1' or @key2='abc']"
@@ -123,11 +124,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 +235,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-path-parser/src/test/groovy/org/onap/cps/cpspath/parser/CpsPathUtilSpec.groovy b/cps-path-parser/src/test/groovy/org/onap/cps/cpspath/parser/CpsPathUtilSpec.groovy
index d62f337b75..29bb3c7b58 100644
--- a/cps-path-parser/src/test/groovy/org/onap/cps/cpspath/parser/CpsPathUtilSpec.groovy
+++ b/cps-path-parser/src/test/groovy/org/onap/cps/cpspath/parser/CpsPathUtilSpec.groovy
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2022 Nordix Foundation
+ * Copyright (C) 2022-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.
@@ -36,21 +36,40 @@ class CpsPathUtilSpec extends Specification {
'single quotes' | "/parent/child[@common-leaf-name='123']"
}
- def 'Normalized parent xpaths'() {
- when: 'a given xpath with #scenario is parsed'
- def result = CpsPathUtil.getNormalizedParentXpath(xpath)
+ def 'Normalized parent paths of absolute paths'() {
+ when: 'a given cps path is parsed'
+ def result = CpsPathUtil.getNormalizedParentXpath(cpsPath)
then: 'the result is the expected parent path'
assert result == expectedParentPath
- where: 'the following xpaths are used'
- scenario | xpath || expectedParentPath
- 'no child' | '/parent' || ''
- 'child and parent' | '/parent/child' || '/parent'
- 'grand child' | '/parent/child/grandChild' || '/parent/child'
- 'parent & top is list element' | '/parent[@id=1]/child' || "/parent[@id='1']"
- 'parent is list element' | '/parent/child[@id=1]/grandChild' || "/parent/child[@id='1']"
- 'parent is list element with /' | "/parent/child[@id='a/b']/grandChild" || "/parent/child[@id='a/b']"
- 'parent is list element with [' | "/parent/child[@id='a[b']/grandChild" || "/parent/child[@id='a[b']"
- 'parent is list element using "' | '/parent/child[@id="x"]/grandChild' || "/parent/child[@id='x']"
+ where: 'the following absolute cps paths are used'
+ cpsPath || expectedParentPath
+ '/parent' || ''
+ '/parent/child' || '/parent'
+ '/parent/child/grandChild' || '/parent/child'
+ '/parent[@id=1]/child' || "/parent[@id='1']"
+ '/parent/child[@id=1]/grandChild' || "/parent/child[@id='1']"
+ '/parent/child/grandChild[@id="x"]' || "/parent/child"
+ '/parent/ancestor::grandparent' || ''
+ '/parent/child/ancestor::grandparent' || '/parent'
+ '/parent/child/name[text()="value"]' || '/parent'
+ }
+
+ def 'Normalized parent paths of descendant paths'() {
+ when: 'a given cps path is parsed'
+ def result = CpsPathUtil.getNormalizedParentXpath(cpsPath)
+ then: 'the result is the expected parent path'
+ assert result == expectedParentPath
+ where: 'the following descendant cps paths are used'
+ cpsPath || expectedParentPath
+ '//parent' || ''
+ '//parent/child' || '//parent'
+ '//parent/child/grandChild' || '//parent/child'
+ '//parent[@id=1]/child' || "//parent[@id='1']"
+ '//parent/child[@id=1]/grandChild' || "//parent/child[@id='1']"
+ '//parent/child/grandChild[@id="x"]' || "//parent/child"
+ '//parent/ancestor::grandparent' || ''
+ '//parent/child/ancestor::grandparent' || '//parent'
+ '//parent/child/name[text()="value"]' || '//parent'
}
def 'Get node ID sequence for given xpath'() {
@@ -67,17 +86,19 @@ class CpsPathUtilSpec extends Specification {
'parent is list element' | '/parent/child[@id=1]/grandChild' || ["parent","child","grandChild"]
'parent is list element with /' | "/parent/child[@id='a/b']/grandChild" || ["parent","child","grandChild"]
'parent is list element with [' | "/parent/child[@id='a[b']/grandChild" || ["parent","child","grandChild"]
+ 'does not include ancestor node' | '/parent/child/ancestor::grandparent' || ["parent","child"]
}
def 'Recognizing (absolute) xpaths to List elements'() {
expect: 'check for list returns the correct values'
assert CpsPathUtil.isPathToListElement(xpath) == expectList
where: 'the following xpaths are used'
- xpath || expectList
- '/parent[@id=1]' || true
- '/parent[@id=1]/child' || false
- '/parent/child[@id=1]' || true
- '//child[@id=1]' || false
+ xpath || expectList
+ '/parent[@id=1]' || true
+ '/parent[@id=1]/child' || false
+ '/parent/child[@id=1]' || true
+ '//child[@id=1]' || false
+ '/parent/ancestor::grandparent[@id=1]' || false
}
def 'Parsing Exception'() {