Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Add OR operator to cps-path

  steps to be followed :

  1. Antlr grammer file changes should be made to recognise OR
  2. Implement the code logic in order to add OR functionality
  3. Add test cases
  4. Update documentation
  5. Demo to team

Here following are the antlr changes which made to recognise the OR

So, Cps has and condition which is applied with leaf condition ,similarly we have added or to the antlr

path

Issues & Decisions

#

Issue

Notes 

Decision

1

Antlr changes to be made to recognize OR as input in 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 

The problem is we are unable to find the logic how and condition has been implemented , like is there any query written for it.

...

It is tested by antlr test


2

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("'");
    }
}



3Test Case written to test code changes

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"
    }

 2.   def 'Parse cps path that ends with a yang list containing #scenario and having or operator '() {
        when: 'the given cps path is parsed'
        def result = CpsPathQuery.createFrom(cpsPath)
        then: 'the query has the right xpath type'
        result.cpsPathPrefixType == DESCENDANT
        and: 'the right parameters are set'
        result.descendantName == "child"
        result.leavesData.size() == expectedNumberOfLeaves
        where: 'the following data is used'
        scenario                  | cpsPath                                            || expectedNumberOfLeaves
        'more than one attribute' | '//child[@int-leaf=5 or @leaf-name="leaf value"]'  || 2
    }


4

Testcases in 

CpsDataPersistenceQueryDataNodeSpec.groovy

@Sql([CLEAR_DATA, SET_DATA])
def 'Cps Path query using descendant anywhere with #scenario OR condition(s) for a container element.'() {
when: 'a query is executed to get a data node by the given cps path'
def result = objectUnderTest.queryDataNodes(DATASPACE_NAME, ANCHOR_FOR_SHOP_EXAMPLE, cpsPath, OMIT_DESCENDANTS)
then: 'the correct number of data nodes are retrieved'
result.size() == expectedXPaths.size()
and: 'xpaths of the retrieved data nodes are as expected'
for (int i = 0; i < result.size(); i++) {
assert result[i].getXpath() == expectedXPaths[i]
}
where: 'the following data is used'
scenario | cpsPath || expectedXPaths
'more than one leaf' | '//author[@FirstName="Joe" or @title="title"]' || ["/shops/shop[@id='1']/categories[@code='1']/book/author[@FirstName='Joe' or @Surname='Bloggs']"]
'leaves has OR condition' | '//author[@FirstName="Joe" or @Firstname="Jane"]' || ["/shops/shop[@id=''1'']/categories[@code=''1'']/book/author[@FirstName='Joe']", "/shops/shop[@id=''1'']/categories[@code=''2'']/book/author[@FirstName=''Jane'']"]
}


So, this groovy testcase is based on the Query where it as

"SELECT * FROM FRAGMENT WHERE anchor_id = :anchorId  AND xpath ~ :xpathRegex AND attributes @> :leafDataAsJson\\:\\:jsonb

The problem is we are unable to find the logic how AND condition has been implemented , Also OR works as AND

In this query they are passing anchor id,xpatRegex,Attributes but no where we see either of two operators(i.e, and/or).

Here we had analysis that whatever the attributes having  jsondata is taking  as graphdatabase  that inbuilt  functions as AND

So, would like to get help with it.

to-do:
Need to implement the logic for OR Operation

But there are few doubts regarding this to be discussed