Versions Compared

Key

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


Issues & Decisions

...

#

...

Notes 

...

Decision

...

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 

It is tested by antlr test

...

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

...

Table of Contents

References

CPS-1273

Query data node using cps-path

Comparative Operators Condition

In query of data node, when we can query using <,>,>=,<= comparative operators . Also we can combine  “AND/OR” conditions with comparative operators . Below are the some examples


#
cps-path

Output

1

Using "<" condition

cps-path : //books[@price<15]


Code Block
titleJson Response
collapsetrue
[
    {
        "book-store:books": {
            "lang": "English",
            "price": 10,
            "title": "Matilda",
            "authors": [
                "Roald Dahl"
            ],
            "editions": [
                1988,
                2000
            ]
        }
    },
    {
        "book-store:books": {
            "lang": "English",
            "price": 14,
            "title": "The Light Fantastic",
            "authors": [
                "Terry Pratchett"
            ],
            "editions": [
                1986
            ]
        }
    },
    {
        "book-store:books": {
            "lang": "English",
            "price": 12,
            "title": "The Colour of Magic",
            "authors": [
                "Terry Pratchett"
            ],
            "editions": [
                1983
            ]
        }
    },
    {
        "book-store:books": {
            "lang": "English",
            "price": 13,
            "title": "Good Omens",
            "authors": [
                "Terry Pratchett",
                "Neil Gaiman"
            ],
            "editions": [
                2006
            ]
        }
    },
    {
        "book-store:books": {
            "lang": "N/A",
            "price": 11,
            "title": "Logarithm tables",
            "authors": [
                "Joe Bloggs"
            ],
            "editions": [
                2009
            ]
        }
    }
]
            
2

Using "<" with OR condition

cps-path : //books[@price<10 or @lang="German"]


Code Block
titleJson Response
collapsetrue
[
    {
        "book-store:books": {
            "lang": "German",
            "price": 39,
            "title": "Debian GNU/Linux",
            "authors": [
                "Peter H. Ganten",
                "Wulf Alex"
            ],
            "editions": [
                2013,
                2021,
                2007
            ]
        }
    }
]
            
3

Using ">" with AND condition

cps-path : //books[@price>13 and @title="A Book with No Language"]


Code Block
titleJson Response
collapsetrue
 [
    {
        "book-store:books": {
            "lang": "",
            "price": 20,
            "title": "A Book with No Language",
            "authors": [
                "Joe Bloggs"
            ],
            "editions": [
                2023
            ]
        }
    }
]                                 
 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


4

Using ">=" with combination of OR/AND condition

cps-path : //books[@price>=13 or @lang="Spanish" and @title="Good Omens"]


Code Block
titleJson Response
collapsetrue
[
    {
        "book-store:books": {
            "lang": "English",
            "price": 15,
            "title": "The Gruffalo",
            "authors": [
                "Julia Donaldson"
            ],
            "editions": [
                1999
            ]
        }
    },
    {
        "book-store:books": {
            "lang": "English",
            "price": 15,
            "title": "Annihilation",
            "authors": [
                "Jeff VanderMeer"
            ],
            "editions": [
                2014
            ]
        }
    },
    {
        "book-store:books": {
            "lang": "English",
            "price": 14,
            "title": "The Light Fantastic",
            "authors": [
                "Terry Pratchett"
            ],
            "editions": [
                1986
            ]
        }
    },
    {
        "book-store:books": {
            "lang": "English",
            "price": 13,
            "title": "Good Omens",
            "authors": [
                "Terry Pratchett",
                "Neil Gaiman"
            ],
            "editions": [
                2006
            ]
        }
    },
    {
        "book-store:books": {
            "lang": "",
            "price": 20,
            "title": "A Book with No Language",
            "authors": [
                "Joe Bloggs"
            ],
            "editions": [
                2023
            ]
        }
    },
    {
        "book-store:books": {
            "lang": "German",
            "price": 39,
            "title": "Debian GNU/Linux",
            "authors": [
                "Peter H. Ganten",
                "Wulf Alex"
            ],
            "editions": [
                2013,
                2021,
                2007
            ]
        }
    }
]    


5

Using "<="  with combination of AND/OR condition

cps-path : //books[@price<=15 and @title="Annihilation" or @lang="Spanish"]


Code Block
titleJson Response
collapsetrue
[
    {
        "book-store:books": {
            "lang": "English",
            "price": 15,
     
|
 
cpsPath
      "title": "Annihilation",
            "authors": [
                "Jeff VanderMeer"
       
||
 
expectedXPaths
    
'more
],
than
 
one
 
leaf'
       
|
 
'//author[@FirstName="Joe"
 
or
 
@title=
"
title"]'
editions": [
            
||
 
["/shops/shop[@id='1']/categories[@code='1']/book/author[@FirstName='Joe'
 
or @Surname='Bloggs']"]
  2014
    
'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

...

   }
    }
]          



Implementation of Comparative Operator

1.Update antlr parser to recognize <,>,<=,>=  in leaf-condition
2.Implement required (native) query
3.Add Integration tests for comparative operators
4.Update documentation
5.demo to team 

Query used  : SELECT * FROM fragment WHERE anchor_id = :anchorId  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

Would like to get help with it((attributes ->> 'price')\:\:int > '13' and  attributes @> '{"title":"A Book with No Language"}')

Limitations

1.Using comparative operators with string values will lead to an error at runtime. This error can't be validated earlier as the datatype is unknown until the execution phase.