...
Table of Contents |
---|
...
References
Jira | ||||||
---|---|---|---|---|---|---|
|
Issues & Decisions
...
#
...
Issue
...
Notes
...
Decision
...
Query data node using cps-path
...
Adding OR operator to the antlr grammer file
PATH : cps-path-parser/src/main/antlr4/org/onap/cps/cpspath/parser/antlr4/CpsPath.g4
Solution : listElementRef : OB leafCondition ( ( KW_AND | KW_OR) leafCondition)* CB
multipleLeafConditions : OB leafCondition ( ( KW_AND | KW_OR) leafCondition)* CB
It is tested by antlr test
1.Using AND condition
In query of data node, when we can combine two leaf elements using “AND” condition this would give result only if both leaf values are under same list. Below are the examples:
- Here cps-path //books[@pub_year=1994 and @price=895]
- Since, pub_year=1994 and price=895 are under same list it gives the response
- Similarly when cps-path //books[@pub_year=1994 and @price=1099]
- Since, pub_year=1994 and price=1099 are under different list it gives the empty response
2.Using OR condition
In order to search across the Json data here with multiple attributes under different lists OR condition is used.
we can combine two leaf elements using “OR” condition this would give result. Below are the examples:
- Here cps-path //books[@pub_year=1994 or @price=1099]]
- pub_year=1994 and price=1099 are under different list it gives the required response
- Here cps-path //books[@pub_year=1994 or @price=895 or @title="Far Horizons"]
- multiple attributes pub_year=1994 and price=895 and title=Far Horizons are under different list it gives the required response
- Also cps-path //books[@price=895 or @title="xyz"]
- attribute has non-json value price=895 and title="
//books[@pub_year=1994 or @price=895 or @title="Far Horizons"]
Implementation of OR Operator
1.Update antlr parser to recognize OR in leaf-condition
2.Implement required (native) query
3.Add Integration tests for
a.filter on mix of string and integer leaf-values
b.filter on non-json data
c.filter on combination of multiple AND's as well as OR's
4.Update documentation
5.demo to team
Query used : SELECT * FROM FRAGMENT WHERE anchor_id = :anchorId AND xpath ~ :xpathRegex AND ( attributes @> '{"price":895}' or attributes @> '{"title":"Far Horizons"}')
Limitations
1.Since leaf are stored in Hashmap same keys are not supported, unique keys only supports.
2.Only leaves can be used, leaf-list are not supported
3.Only string and integer values are supported, boolean and float values are not supported.
4.Multiple attributes can only be combined using AND, OR , multiple AND's , multiple OR's and bracketing is not supported.
5.Also the order of leaf elements in the map is not preserved , so combination of And/Or would not give expected result. Currently working on the ordering of leaf elements to give proper support for combination of and/or CPS-1629.
...
Code changes made to recognise the operatoe i.e., and ,or
PATH:cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathBuilder.java
Solution:
String parent = ctx.getParent().getText();
String payload = ctx.getPayload().getText();
payloads.add(payload);
String operator = findOperator(parent, payloads);
appendCondition(normalizedXpathBuilder, ctx.leafName().getText(), comparisonValue, operator);
if (processingAncestorAxis) {
appendCondition(normalizedAncestorPathBuilder, ctx.leafName().getText(), comparisonValue, operator);
}
}
private String findOperator(String parent, List<String> payloads) {
StringBuilder parentStringBuilder = new StringBuilder(parent);
try {
payloads.forEach(payload -> parentStringBuilder.delete(parentStringBuilder.indexOf(payload), parentStringBuilder.indexOf(payload) + payload.length()));
parentStringBuilder.delete(0, parentStringBuilder.indexOf("[") + 1);
return parentStringBuilder.toString().trim();
} catch (RuntimeException e) {
return null;
}
}
private void appendCondition(final StringBuilder currentNormalizedPathBuilder, final String name,
final Object value, String operator) {
final char lastCharacter = currentNormalizedPathBuilder.charAt(currentNormalizedPathBuilder.length() - 1);
currentNormalizedPathBuilder.append(lastCharacter == '[' ? "" : " " + operator + " ");
currentNormalizedPathBuilder.append("@");
currentNormalizedPathBuilder.append(name);
currentNormalizedPathBuilder.append("='");
currentNormalizedPathBuilder.append(value);
currentNormalizedPathBuilder.append("'");
}
}
...
PATH:cps-path-parser/src/test/groovy/org/onap/cps/cpspath/parser/CpsPathQuerySpec.groovy
1. def 'Parse cps path having OR operator containing #scenario.'() {
when: 'the given cps path is parsed'
def result = CpsPathUtil.getCpsPathQuery(cpsPath)
then: 'the query has the right normalized xpath type'
assert result.normalizedXpath == expectedNormalizedXPath
where: 'the following data is used'
scenario | cpsPath || expectedNormalizedXPath
'parent & child with more than one attribute' | '/parent/child[@key1=1 or @key2="abc"]/child2' || "/parent/child[@key1='1' or @key2='abc']/child2"
}
...