You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by ch...@apache.org on 2016/01/07 14:08:18 UTC
[1/6] olingo-odata4 git commit: [OLINGO-834] $expand parser in Java +
clean-up
Repository: olingo-odata4
Updated Branches:
refs/heads/OLINGO-834_Filter_Parser 8919d3ef1 -> 8925274c0
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestLexer.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestLexer.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestLexer.java
index 6df6759..6102fd8 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestLexer.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestLexer.java
@@ -18,16 +18,22 @@
*/
package org.apache.olingo.server.core.uri.antlr;
-import org.antlr.v4.runtime.Lexer;
-import org.apache.olingo.server.core.uri.testutil.TokenValidator;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.olingo.server.core.uri.parser.UriTokenizer;
+import org.apache.olingo.server.core.uri.parser.UriTokenizer.TokenKind;
import org.junit.Test;
+/**
+ * Tests originally written for the ANTLR lexer.
+ */
public class TestLexer {
private TokenValidator test = null;
- private static final String cPCT_ENCODED = "%45%46%47" + "%22" + "%5C";// last two chars are not in
- // cPCT_ENCODED_UNESCAPED
+ // The last two chars are not in cPCT_ENCODED_UNESCAPED.
+ private static final String cPCT_ENCODED = "%45%46%47" + "%22" + "%5C";
private static final String cUNRESERVED = "ABCabc123-._~";
private static final String cOTHER_DELIMS = "!()*+,;";
private static final String cSUB_DELIMS = "$&'=" + cOTHER_DELIMS;
@@ -39,265 +45,279 @@ public class TestLexer {
}
@Test
- public void test() {
-
- // test.log(1).run("ESAllPrim?$orderby=PropertyDouble eq 3.5E+38");
+ public void unary() {
+ test.run("-a eq a").has(TokenKind.MinusOperator, TokenKind.ODataIdentifier, TokenKind.EqualsOperator,
+ TokenKind.ODataIdentifier).isInput();
}
- // ;------------------------------------------------------------------------------
- // ; 0. URI
- // ;------------------------------------------------------------------------------
-
@Test
- public void testUnary() {
- test.run("- a eq a").isAllInput();
+ public void uriTokens() {
+// test.run("#").isType(TokenKind.FRAGMENT).isInput();
+ test.run("$count").has(TokenKind.COUNT).isInput();
+ test.run("$ref").has(TokenKind.REF).isInput();
+ test.run("$value").has(TokenKind.VALUE).isInput();
}
@Test
- public void testUriTokens() {
- test.globalMode(UriLexer.MODE_QUERY);
- test.run("#").isText("#").isType(UriLexer.FRAGMENT);
- test.run("$count").isText("$count").isType(UriLexer.COUNT);
- test.run("$ref").isText("$ref").isType(UriLexer.REF);
- test.run("$value").isText("$value").isType(UriLexer.VALUE);
+ public void queryOptionsTokens() {
+ test.run("$skip=1").has(TokenKind.SKIP, TokenKind.EQ, TokenKind.IntegerValue).isInput();
+ test.run("$skip=2").has(TokenKind.SKIP, TokenKind.EQ, TokenKind.IntegerValue).isInput();
+ test.run("$skip=123").has(TokenKind.SKIP, TokenKind.EQ, TokenKind.IntegerValue).isInput();
+
+ test.run("$top=1").has(TokenKind.TOP, TokenKind.EQ, TokenKind.IntegerValue).isInput();
+ test.run("$top=2").has(TokenKind.TOP, TokenKind.EQ, TokenKind.IntegerValue).isInput();
+ test.run("$top=123").has(TokenKind.TOP, TokenKind.EQ, TokenKind.IntegerValue).isInput();
+
+ test.run("$levels=1").has(TokenKind.LEVELS, TokenKind.EQ, TokenKind.IntegerValue).isInput();
+ test.run("$levels=2").has(TokenKind.LEVELS, TokenKind.EQ, TokenKind.IntegerValue).isInput();
+ test.run("$levels=123").has(TokenKind.LEVELS, TokenKind.EQ, TokenKind.IntegerValue).isInput();
+ test.run("$levels=max").has(TokenKind.LEVELS, TokenKind.EQ, TokenKind.MAX).isInput();
+
+// test.run("$format=atom").has(TokenKind.FORMAT, TokenKind.EQ, TokenKind.ODataIdentifier).isInput();
+// test.run("$format=json").has(TokenKind.FORMAT, TokenKind.EQ, TokenKind.ODataIdentifier).isInput();
+// test.run("$format=xml").has(TokenKind.FORMAT,, TokenKind.EQ, TokenKind.ODataIdentifier).isInput();
+// test.run("$format=abc/def").has(TokenKind.FORMAT, TokenKind.EQ,
+// TokenKind.ODataIdentifier, TokenKind.SLASH, TokenKind.ODataIdentifier).isInput();
+
+// test.run("$id=123").has(TokenKind.ID, TokenKind.EQ, TokenKind.IntegerValue).isInput();
+// test.run("$id=ABC").has(TokenKind.ID, TokenKind.EQ, TokenKind.ODataIdentifier).isInput();
+
+// test.run("$skiptoken=ABC").has(TokenKind.SKIPTOKEN, TokenKind.EQ, TokenKind.ODataIdentifier).isInput();
+// test.run("$skiptoken=ABC").has(TokenKind.SKIPTOKEN, TokenKind.EQ, TokenKind.ODataIdentifier).isInput();
+
+ test.run("$search=\"ABC\"").has(TokenKind.SEARCH, TokenKind.EQ, TokenKind.Phrase).isInput();
+ test.run("$search=ABC").has(TokenKind.SEARCH, TokenKind.EQ, TokenKind.Word).isInput();
+ test.run("$search=\"A%20B%20C\"").has(TokenKind.SEARCH, TokenKind.EQ, TokenKind.Phrase).isInput();
+ test.run("$search=Test Test").has(TokenKind.SEARCH, TokenKind.EQ, TokenKind.Word,
+ TokenKind.AndOperatorSearch, TokenKind.Word).isInput();
+ test.run("$search=Test&$filter=ABC eq 1").has(TokenKind.SEARCH, TokenKind.EQ, TokenKind.Word);
}
- // ;------------------------------------------------------------------------------
- // ; 2. Query Options
- // ;------------------------------------------------------------------------------
@Test
- public void testQueryOptionsTokens() {
-
- test.globalMode(UriLexer.MODE_QUERY);
- test.run("$skip=1").isAllText("$skip=1").isType(UriLexer.SKIP_QO);
- test.run("$skip=2").isAllText("$skip=2").isType(UriLexer.SKIP_QO);
- test.run("$skip=123").isAllText("$skip=123").isType(UriLexer.SKIP_QO);
-
- test.run("$top=1").isAllText("$top=1").isType(UriLexer.TOP);
- test.run("$top=2").isAllText("$top=2").isType(UriLexer.TOP);
- test.run("$top=123").isAllText("$top=123").isType(UriLexer.TOP);
-
- test.run("$levels=1").isAllText("$levels=1").isType(UriLexer.LEVELS);
- test.run("$levels=2").isAllText("$levels=2").isType(UriLexer.LEVELS);
- test.run("$levels=123").isAllText("$levels=123").isType(UriLexer.LEVELS);
- test.run("$levels=max").isAllText("$levels=max").isType(UriLexer.LEVELS);
-
- test.run("$format=atom").isAllText("$format=atom").isType(UriLexer.FORMAT);
- test.run("$format=json").isAllText("$format=json").isType(UriLexer.FORMAT);
- test.run("$format=xml").isAllText("$format=xml").isType(UriLexer.FORMAT);
- test.run("$format=abc/def").isAllText("$format=abc/def").isType(UriLexer.FORMAT);
-
- test.run("$id=123").isAllText("$id=123").isType(UriLexer.ID);
- test.run("$id=ABC").isAllText("$id=ABC").isType(UriLexer.ID);
-
- test.run("$skiptoken=ABC").isAllText("$skiptoken=ABC").isType(UriLexer.SKIPTOKEN);
- test.run("$skiptoken=ABC").isAllText("$skiptoken=ABC").isType(UriLexer.SKIPTOKEN);
-
- test.run("$search=\"ABC\"").isAllText("$search=\"ABC\"").isType(UriLexer.SEARCH);
- test.run("$search=ABC").isAllText("$search=ABC").isType(UriLexer.SEARCH);
- test.run("$search=\"A%20B%20C\"").isAllText("$search=\"A%20B%20C\"").isType(UriLexer.SEARCH);
- test.run("$search=Test Test").isAllText("$search=Test Test").isType(UriLexer.SEARCH);
- test.run("$search=Test&$filter=ABC eq 1").isAllText("$search=Test&$filter=ABC eq 1").isType(UriLexer.SEARCH);
- }
-
- @Test
- public void testQueryOptionsDefaultMode() {
- // First set query mode, than use expand(switches to default mode) and use nested system query options
- test.globalMode(UriLexer.MODE_QUERY);
- test.run("$expand=ABC($skip=1)").isAllText("$expand=ABC($skip=1)").at(4).isType(UriLexer.SKIP_QO);
- test.run("$expand=ABC($skip=2)").isAllText("$expand=ABC($skip=2)").at(4).isType(UriLexer.SKIP_QO);
- test.run("$expand=ABC($skip=123)").isAllText("$expand=ABC($skip=123)").at(4).isType(UriLexer.SKIP_QO);
- test.run("$expand=ABC($search=abc)").isAllText("$expand=ABC($search=abc)").at(4).isType(UriLexer.SEARCH_INLINE);
- test.run("$expand=ABC($search=\"123\")").isAllText("$expand=ABC($search=\"123\")")
- .at(4).isType(UriLexer.SEARCH_INLINE)
- .at(6).isType(UriLexer.SEARCHPHRASE);
- test.run("$expand=ABC($top=1)").isAllText("$expand=ABC($top=1)").at(4).isType(UriLexer.TOP);
- test.run("$expand=ABC($top=2)").isAllText("$expand=ABC($top=2)").at(4).isType(UriLexer.TOP);
- test.run("$expand=ABC($top=123)").isAllText("$expand=ABC($top=123)").at(4).isType(UriLexer.TOP);
-
- test.run("$expand=ABC($expand=DEF($skip=1))").isAllText("$expand=ABC($expand=DEF($skip=1))")
- .at(8).isType(UriLexer.SKIP_QO);
- test.run("$expand=ABC($expand=DEF($skip=2))").isAllText("$expand=ABC($expand=DEF($skip=2))")
- .at(8).isType(UriLexer.SKIP_QO);
- test.run("$expand=ABC($expand=DEF($skip=123))").isAllText("$expand=ABC($expand=DEF($skip=123))")
- .at(8).isType(UriLexer.SKIP_QO);
-
- test.run("$expand=ABC($expand=DEF($top=1))").isAllText("$expand=ABC($expand=DEF($top=1))")
- .at(8).isType(UriLexer.TOP);
- test.run("$expand=ABC($expand=DEF($top=2))").isAllText("$expand=ABC($expand=DEF($top=2))")
- .at(8).isType(UriLexer.TOP);
- test.run("$expand=ABC($expand=DEF($top=123))").isAllText("$expand=ABC($expand=DEF($top=123))")
- .at(8).isType(UriLexer.TOP);
- test.run("$expand=ABC($expand=DEF($search=Test Test))").isAllText("$expand=ABC($expand=DEF($search=Test Test))")
- .at(8).isType(UriLexer.SEARCH_INLINE)
- .at(10).isType(UriLexer.SEARCHWORD)
- .at(12).isType(UriLexer.SEARCHWORD);
+ public void queryOptionsDefaultMode() {
+ test.run("$expand=ABC($skip=1)").has(TokenKind.EXPAND, TokenKind.EQ, TokenKind.ODataIdentifier,
+ TokenKind.OPEN, TokenKind.SKIP, TokenKind.EQ, TokenKind.IntegerValue, TokenKind.CLOSE).isInput();
+ test.run("$expand=ABC($skip=123)").has(TokenKind.EXPAND, TokenKind.EQ, TokenKind.ODataIdentifier,
+ TokenKind.OPEN, TokenKind.SKIP, TokenKind.EQ, TokenKind.IntegerValue, TokenKind.CLOSE).isInput();
+ test.run("$expand=ABC($search=abc)").has(TokenKind.EXPAND, TokenKind.EQ, TokenKind.ODataIdentifier,
+ TokenKind.OPEN, TokenKind.SEARCH, TokenKind.EQ, TokenKind.Word, TokenKind.CLOSE).isInput();
+ test.run("$expand=ABC($search=\"123\")").has(TokenKind.EXPAND, TokenKind.EQ, TokenKind.ODataIdentifier,
+ TokenKind.OPEN, TokenKind.SEARCH, TokenKind.EQ, TokenKind.Phrase, TokenKind.CLOSE).isInput();
+ test.run("$expand=ABC($top=1)").has(TokenKind.EXPAND, TokenKind.EQ, TokenKind.ODataIdentifier,
+ TokenKind.OPEN, TokenKind.TOP, TokenKind.EQ, TokenKind.IntegerValue, TokenKind.CLOSE).isInput();
+ test.run("$expand=ABC($top=123)").has(TokenKind.EXPAND, TokenKind.EQ, TokenKind.ODataIdentifier,
+ TokenKind.OPEN, TokenKind.TOP, TokenKind.EQ, TokenKind.IntegerValue, TokenKind.CLOSE).isInput();
+
+ test.run("$expand=ABC($expand=DEF($skip=1))").has(TokenKind.EXPAND, TokenKind.EQ, TokenKind.ODataIdentifier,
+ TokenKind.OPEN, TokenKind.EXPAND, TokenKind.EQ, TokenKind.ODataIdentifier,
+ TokenKind.OPEN, TokenKind.SKIP, TokenKind.EQ, TokenKind.IntegerValue, TokenKind.CLOSE, TokenKind.CLOSE)
+ .isInput();
+ test.run("$expand=ABC($expand=DEF($skip=123))").has(TokenKind.EXPAND, TokenKind.EQ, TokenKind.ODataIdentifier,
+ TokenKind.OPEN, TokenKind.EXPAND, TokenKind.EQ, TokenKind.ODataIdentifier,
+ TokenKind.OPEN, TokenKind.SKIP, TokenKind.EQ, TokenKind.IntegerValue, TokenKind.CLOSE, TokenKind.CLOSE)
+ .isInput();
+
+ test.run("$expand=ABC($expand=DEF($top=1))").has(TokenKind.EXPAND, TokenKind.EQ, TokenKind.ODataIdentifier,
+ TokenKind.OPEN, TokenKind.EXPAND, TokenKind.EQ, TokenKind.ODataIdentifier,
+ TokenKind.OPEN, TokenKind.TOP, TokenKind.EQ, TokenKind.IntegerValue, TokenKind.CLOSE, TokenKind.CLOSE)
+ .isInput();
+ test.run("$expand=ABC($expand=DEF($top=123))").has(TokenKind.EXPAND, TokenKind.EQ, TokenKind.ODataIdentifier,
+ TokenKind.OPEN, TokenKind.EXPAND, TokenKind.EQ, TokenKind.ODataIdentifier,
+ TokenKind.OPEN, TokenKind.TOP, TokenKind.EQ, TokenKind.IntegerValue, TokenKind.CLOSE, TokenKind.CLOSE)
+ .isInput();
+
+ test.run("$expand=ABC($expand=DEF($search=Test Test))")
+ .has(TokenKind.EXPAND, TokenKind.EQ, TokenKind.ODataIdentifier,
+ TokenKind.OPEN, TokenKind.EXPAND, TokenKind.EQ, TokenKind.ODataIdentifier,
+ TokenKind.OPEN, TokenKind.SEARCH, TokenKind.EQ, TokenKind.Word,
+ TokenKind.AndOperatorSearch, TokenKind.Word, TokenKind.CLOSE, TokenKind.CLOSE)
+ .isInput();
test.run("$expand=ABC($expand=DEF($search=\"Test\" \"Test\"))")
- .isAllText("$expand=ABC($expand=DEF($search=\"Test\" \"Test\"))")
- .at(8).isType(UriLexer.SEARCH_INLINE)
- .at(10).isType(UriLexer.SEARCHPHRASE)
- .at(12).isType(UriLexer.SEARCHPHRASE);
+ .has(TokenKind.EXPAND, TokenKind.EQ, TokenKind.ODataIdentifier,
+ TokenKind.OPEN, TokenKind.EXPAND, TokenKind.EQ, TokenKind.ODataIdentifier,
+ TokenKind.OPEN, TokenKind.SEARCH, TokenKind.EQ, TokenKind.Phrase,
+ TokenKind.AndOperatorSearch, TokenKind.Phrase, TokenKind.CLOSE, TokenKind.CLOSE)
+ .isInput();
test.run("$expand=ABC($expand=DEF($search=\"Test\" \"Test\";$filter=PropertyInt16 eq 0;$orderby=PropertyInt16))")
- .isAllText("$expand=ABC($expand=DEF($search=\"Test\" \"Test\";$filter=PropertyInt16 " +
- "eq 0;$orderby=PropertyInt16))")
- .at(8).isType(UriLexer.SEARCH_INLINE)
- .at(10).isType(UriLexer.SEARCHPHRASE)
- .at(12).isType(UriLexer.SEARCHPHRASE)
- .at(13).isType(UriLexer.SEMI)
- .at(14).isType(UriLexer.FILTER)
- .at(22).isType(UriLexer.ORDERBY);
+ .has(TokenKind.EXPAND, TokenKind.EQ, TokenKind.ODataIdentifier,
+ TokenKind.OPEN, TokenKind.EXPAND, TokenKind.EQ, TokenKind.ODataIdentifier,
+ TokenKind.OPEN, TokenKind.SEARCH, TokenKind.EQ, TokenKind.Phrase,
+ TokenKind.AndOperatorSearch, TokenKind.Phrase, TokenKind.SEMI,
+ TokenKind.FILTER, TokenKind.EQ, TokenKind.ODataIdentifier, TokenKind.EqualsOperator,
+ TokenKind.IntegerValue, TokenKind.SEMI,
+ TokenKind.ORDERBY, TokenKind.EQ, TokenKind.ODataIdentifier, TokenKind.CLOSE, TokenKind.CLOSE)
+ .isInput();
}
-
- // ;------------------------------------------------------------------------------
- // ; 4. Expressions
- // ;------------------------------------------------------------------------------
- @Test
- public void testQueryExpressions() {
- test.globalMode(Lexer.DEFAULT_MODE);
-
- test.run("$it").isText("$it").isType(UriLexer.IT);
-
- test.run("$filter=contains(").at(2).isText("contains(").isType(UriLexer.CONTAINS_WORD);
-
- test.run("$filter=containsabc").at(2).isText("containsabc")
- .isType(UriLexer.ODATAIDENTIFIER); // test that this is a ODI
-
- test.run("$filter=startswith(").at(2).isText("startswith(").isType(UriLexer.STARTSWITH_WORD);
- test.run("$filter=endswith(").at(2).isText("endswith(").isType(UriLexer.ENDSWITH_WORD);
- test.run("$filter=length(").at(2).isText("length(").isType(UriLexer.LENGTH_WORD);
- test.run("$filter=indexof(").at(2).isText("indexof(").isType(UriLexer.INDEXOF_WORD);
- test.run("$filter=substring(").at(2).isText("substring(").isType(UriLexer.SUBSTRING_WORD);
- test.run("$filter=tolower(").at(2).isText("tolower(").isType(UriLexer.TOLOWER_WORD);
- test.run("$filter=toupper(").at(2).isText("toupper(").isType(UriLexer.TOUPPER_WORD);
- test.run("$filter=trim(").at(2).isText("trim(").isType(UriLexer.TRIM_WORD);
- test.run("$filter=concat(").at(2).isText("concat(").isType(UriLexer.CONCAT_WORD);
+ @Test
+ public void queryExpressions() {
+ test.run("$it").has(TokenKind.IT).isText("$it");
+
+ test.run("$filter=contains(").has(TokenKind.FILTER, TokenKind.EQ, TokenKind.ContainsMethod).isText("contains(");
+
+ test.run("$filter=containsabc").has(TokenKind.FILTER, TokenKind.EQ, TokenKind.ODataIdentifier)
+ .isText("containsabc");
+
+ test.run("$filter=startswith(").has(TokenKind.FILTER, TokenKind.EQ, TokenKind.StartswithMethod)
+ .isText("startswith(");
+ test.run("$filter=endswith(").has(TokenKind.FILTER, TokenKind.EQ, TokenKind.EndswithMethod).isText("endswith(");
+ test.run("$filter=length(").has(TokenKind.FILTER, TokenKind.EQ, TokenKind.LengthMethod).isText("length(");
+ test.run("$filter=indexof(").has(TokenKind.FILTER, TokenKind.EQ, TokenKind.IndexofMethod).isText("indexof(");
+ test.run("$filter=substring(").has(TokenKind.FILTER, TokenKind.EQ, TokenKind.SubstringMethod).isText("substring(");
+ test.run("$filter=tolower(").has(TokenKind.FILTER, TokenKind.EQ, TokenKind.TolowerMethod).isText("tolower(");
+ test.run("$filter=toupper(").has(TokenKind.FILTER, TokenKind.EQ, TokenKind.ToupperMethod).isText("toupper(");
+ test.run("$filter=trim(").has(TokenKind.FILTER, TokenKind.EQ, TokenKind.TrimMethod).isText("trim(");
+ test.run("$filter=concat(").has(TokenKind.FILTER, TokenKind.EQ, TokenKind.ConcatMethod).isText("concat(");
}
- // ;------------------------------------------------------------------------------
- // ; 7. Literal Data Values
- // ;------------------------------------------------------------------------------
-
@Test
- public void testLiteralDataValues() {
- test.globalMode(Lexer.DEFAULT_MODE);
+ public void literalDataValues() {
// null
- test.run("null").isInput().isType(UriLexer.NULLVALUE);
+ test.run("null").has(TokenKind.NULL).isInput();
// binary
- test.run("binary'ABCD'").isInput().isType(UriLexer.BINARY);
- test.run("BiNaRy'ABCD'").isInput().isType(UriLexer.BINARY);
+ test.run("binary'ABCD'").has(TokenKind.BinaryValue).isInput();
+ test.run("BiNaRy'ABCD'").has(TokenKind.BinaryValue).isInput();
// boolean
- test.run("true").isInput().isType(UriLexer.TRUE);
- test.run("false").isInput().isType(UriLexer.FALSE);
- test.run("TrUe").isInput().isType(UriLexer.BOOLEAN);
- test.run("FaLsE").isInput().isType(UriLexer.BOOLEAN);
+ test.run("true").has(TokenKind.BooleanValue).isInput();
+ test.run("false").has(TokenKind.BooleanValue).isInput();
+ test.run("TrUe").has(TokenKind.BooleanValue).isInput();
+ test.run("FaLsE").has(TokenKind.BooleanValue).isInput();
// Lexer rule INT
- test.run("123").isInput().isType(UriLexer.INT);
- test.run("123456789").isInput().isType(UriLexer.INT);
- test.run("+123").isInput().isType(UriLexer.INT);
- test.run("+123456789").isInput().isType(UriLexer.INT);
- test.run("-123").isInput().isType(UriLexer.INT);
- test.run("-123456789").isInput().isType(UriLexer.INT);
+ test.run("123").has(TokenKind.IntegerValue).isInput();
+ test.run("123456789").has(TokenKind.IntegerValue).isInput();
+ test.run("+123").has(TokenKind.IntegerValue).isInput();
+ test.run("+123456789").has(TokenKind.IntegerValue).isInput();
+ test.run("-123").has(TokenKind.IntegerValue).isInput();
+ test.run("-123456789").has(TokenKind.IntegerValue).isInput();
// Lexer rule DECIMAL
- test.run("0.1").isInput().isType(UriLexer.DECIMAL);
- test.run("1.1").isInput().isType(UriLexer.DECIMAL);
- test.run("+0.1").isInput().isType(UriLexer.DECIMAL);
- test.run("+1.1").isInput().isType(UriLexer.DECIMAL);
- test.run("-0.1").isInput().isType(UriLexer.DECIMAL);
- test.run("-1.1").isInput().isType(UriLexer.DECIMAL);
+ test.run("0.1").has(TokenKind.DecimalValue).isInput();
+ test.run("1.1").has(TokenKind.DecimalValue).isInput();
+ test.run("+0.1").has(TokenKind.DecimalValue).isInput();
+ test.run("+1.1").has(TokenKind.DecimalValue).isInput();
+ test.run("-0.1").has(TokenKind.DecimalValue).isInput();
+ test.run("-1.1").has(TokenKind.DecimalValue).isInput();
// Lexer rule EXP
- test.run("1.1e+1").isInput().isType(UriLexer.DECIMAL);
- test.run("1.1e-1").isInput().isType(UriLexer.DECIMAL);
+ test.run("1.1e+1").has(TokenKind.DoubleValue).isInput();
+ test.run("1.1e-1").has(TokenKind.DoubleValue).isInput();
- test.run("NaN").isInput().isType(UriLexer.NANINFINITY);
- test.run("-INF").isInput().isType(UriLexer.NANINFINITY);
- test.run("INF").isInput().isType(UriLexer.NANINFINITY);
+ test.run("NaN").has(TokenKind.DoubleValue).isInput();
+ test.run("-INF").has(TokenKind.DoubleValue).isInput();
+ test.run("INF").has(TokenKind.DoubleValue).isInput();
// Lexer rule GUID
- test.run("1234ABCD-12AB-23CD-45EF-123456780ABC").isInput().isType(UriLexer.GUID);
- test.run("1234ABCD-12AB-23CD-45EF-123456780ABC").isInput().isType(UriLexer.GUID);
+ test.run("1234ABCD-12AB-23CD-45EF-123456780ABC").has(TokenKind.GuidValue).isInput();
+ test.run("1234ABCD-12AB-23CD-45EF-123456780ABC").has(TokenKind.GuidValue).isInput();
// Lexer rule DATE
- test.run("2013-11-15").isInput().isType(UriLexer.DATE);
+ test.run("2013-11-15").has(TokenKind.DateValue).isInput();
// Lexer rule DATETIMEOFFSET
- test.run("2013-11-15T13:35Z").isInput().isType(UriLexer.DATETIMEOFFSET);
- test.run("2013-11-15T13:35:10Z").isInput().isType(UriLexer.DATETIMEOFFSET);
- test.run("2013-11-15T13:35:10.1234Z").isInput().isType(UriLexer.DATETIMEOFFSET);
+ test.run("2013-11-15T13:35Z").has(TokenKind.DateTimeOffsetValue).isInput();
+ test.run("2013-11-15T13:35:10Z").has(TokenKind.DateTimeOffsetValue).isInput();
+ test.run("2013-11-15T13:35:10.1234Z").has(TokenKind.DateTimeOffsetValue).isInput();
- test.run("2013-11-15T13:35:10.1234+01:30").isInput().isType(UriLexer.DATETIMEOFFSET);
- test.run("2013-11-15T13:35:10.1234-01:12").isInput().isType(UriLexer.DATETIMEOFFSET);
+ test.run("2013-11-15T13:35:10.1234+01:30").has(TokenKind.DateTimeOffsetValue).isInput();
+ test.run("2013-11-15T13:35:10.1234-01:12").has(TokenKind.DateTimeOffsetValue).isInput();
- test.run("2013-11-15T13:35Z").isInput().isType(UriLexer.DATETIMEOFFSET);
+ test.run("2013-11-15T13:35Z").has(TokenKind.DateTimeOffsetValue).isInput();
// Lexer rule DURATION
- test.run("duration'PT67S'").isInput().isType(UriLexer.DURATION);
- test.run("duration'PT67.89S'").isInput().isType(UriLexer.DURATION);
-
- test.run("duration'PT5M'").isInput().isType(UriLexer.DURATION);
- test.run("duration'PT5M67S'").isInput().isType(UriLexer.DURATION);
- test.run("duration'PT5M67.89S'").isInput().isType(UriLexer.DURATION);
-
- test.run("duration'PT4H'").isInput().isType(UriLexer.DURATION);
- test.run("duration'PT4H67S'").isInput().isType(UriLexer.DURATION);
- test.run("duration'PT4H67.89S'").isInput().isType(UriLexer.DURATION);
- test.run("duration'PT4H5M'").isInput().isType(UriLexer.DURATION);
- test.run("duration'PT4H5M67S'").isInput().isType(UriLexer.DURATION);
- test.run("duration'PT4H5M67.89S'").isInput().isType(UriLexer.DURATION);
-
- test.run("duration'P3D'");
- test.run("duration'P3DT67S'").isInput().isType(UriLexer.DURATION);
- test.run("duration'P3DT67.89S'").isInput().isType(UriLexer.DURATION);
- test.run("duration'P3DT5M'").isInput().isType(UriLexer.DURATION);
- test.run("duration'P3DT5M67S'").isInput().isType(UriLexer.DURATION);
- test.run("duration'P3DT5M67.89S'").isInput().isType(UriLexer.DURATION);
- test.run("duration'P3DT4H'").isInput().isType(UriLexer.DURATION);
- test.run("duration'P3DT4H67S'").isInput().isType(UriLexer.DURATION);
- test.run("duration'P3DT4H67.89S'").isInput().isType(UriLexer.DURATION);
- test.run("duration'P3DT4H5M'").isInput().isType(UriLexer.DURATION);
- test.run("duration'P3DT4H5M67S'").isInput().isType(UriLexer.DURATION);
- test.run("duration'P3DT4H5M67.89S'").isInput().isType(UriLexer.DURATION);
-
- test.run("DuRaTiOn'P3DT4H5M67.89S'").isInput().isType(UriLexer.DURATION);
- test.run("DuRaTiOn'-P3DT4H5M67.89S'").isInput().isType(UriLexer.DURATION);
-
- test.run("20:00").isInput().isType(UriLexer.TIMEOFDAY);
- test.run("20:15:01").isInput().isType(UriLexer.TIMEOFDAY);
- test.run("20:15:01.02").isInput().isType(UriLexer.TIMEOFDAY);
-
- test.run("20:15:01.02").isInput().isType(UriLexer.TIMEOFDAY);
+ test.run("duration'PT67S'").has(TokenKind.DurationValue).isInput();
+ test.run("duration'PT67.89S'").has(TokenKind.DurationValue).isInput();
+
+ test.run("duration'PT5M'").has(TokenKind.DurationValue).isInput();
+ test.run("duration'PT5M67S'").has(TokenKind.DurationValue).isInput();
+ test.run("duration'PT5M67.89S'").has(TokenKind.DurationValue).isInput();
+
+ test.run("duration'PT4H'").has(TokenKind.DurationValue).isInput();
+ test.run("duration'PT4H67S'").has(TokenKind.DurationValue).isInput();
+ test.run("duration'PT4H67.89S'").has(TokenKind.DurationValue).isInput();
+ test.run("duration'PT4H5M'").has(TokenKind.DurationValue).isInput();
+ test.run("duration'PT4H5M67S'").has(TokenKind.DurationValue).isInput();
+ test.run("duration'PT4H5M67.89S'").has(TokenKind.DurationValue).isInput();
+
+ test.run("duration'P3D'").has(TokenKind.DurationValue).isInput();
+ test.run("duration'P3DT67S'").has(TokenKind.DurationValue).isInput();
+ test.run("duration'P3DT67.89S'").has(TokenKind.DurationValue).isInput();
+ test.run("duration'P3DT5M'").has(TokenKind.DurationValue).isInput();
+ test.run("duration'P3DT5M67S'").has(TokenKind.DurationValue).isInput();
+ test.run("duration'P3DT5M67.89S'").has(TokenKind.DurationValue).isInput();
+ test.run("duration'P3DT4H'").has(TokenKind.DurationValue).isInput();
+ test.run("duration'P3DT4H67S'").has(TokenKind.DurationValue).isInput();
+ test.run("duration'P3DT4H67.89S'").has(TokenKind.DurationValue).isInput();
+ test.run("duration'P3DT4H5M'").has(TokenKind.DurationValue).isInput();
+ test.run("duration'P3DT4H5M67S'").has(TokenKind.DurationValue).isInput();
+ test.run("duration'P3DT4H5M67.89S'").has(TokenKind.DurationValue).isInput();
+
+ test.run("DuRaTiOn'P3DT4H5M67.89S'").has(TokenKind.DurationValue).isInput();
+ test.run("DuRaTiOn'-P3DT4H5M67.89S'").has(TokenKind.DurationValue).isInput();
+
+ test.run("20:00").has(TokenKind.TimeOfDayValue).isInput();
+ test.run("20:15:01").has(TokenKind.TimeOfDayValue).isInput();
+ test.run("20:15:01.02").has(TokenKind.TimeOfDayValue).isInput();
+
+ test.run("20:15:01.02").has(TokenKind.TimeOfDayValue).isInput();
// String
- test.run("'ABC'").isText("'ABC'").isType(UriLexer.STRING);
- test.run("'A%20C'").isInput().isType(UriLexer.STRING);
- test.run("'%20%20%20ABC'").isInput().isType(UriLexer.STRING);
-
+ test.run("'ABC'").has(TokenKind.StringValue).isInput();
+ test.run("'A%20C'").has(TokenKind.StringValue).isInput();
+ test.run("'%20%20%20ABC'").has(TokenKind.StringValue).isInput();
}
@Test
- public void testDelims() {
- String reserved = "/";
- test.globalMode(UriLexer.MODE_QUERY);
+ public void delims() {
+ final String reserved = "/";
// Test lexer rule UNRESERVED
- test.run("$format=A/" + cUNRESERVED).isAllInput().isType(UriLexer.FORMAT);
- test.run("$format=A/" + cUNRESERVED + reserved).isType(UriLexer.FORMAT).at(4).isText(cUNRESERVED);
+// test.run("$format=A/" + cUNRESERVED).has(TokenKind.FORMAT).isInput();
+// test.run("$format=A/" + cUNRESERVED + reserved).has(TokenKind.FORMAT).isText(cUNRESERVED);
// Test lexer rule PCT_ENCODED
- test.run("$format=A/" + cPCT_ENCODED).isAllInput().isType(UriLexer.FORMAT);
- test.run("$format=A/" + cPCT_ENCODED + reserved).isType(UriLexer.FORMAT).at(4).isText(cPCT_ENCODED);
+// test.run("$format=A/" + cPCT_ENCODED).has(TokenKind.FORMAT).isInput();
+// test.run("$format=A/" + cPCT_ENCODED + reserved).has(TokenKind.FORMAT).isText(cPCT_ENCODED);
// Test lexer rule SUB_DELIMS
- test.run("$format=A/" + cSUB_DELIMS).isAllInput().isType(UriLexer.FORMAT);
- test.run("$format=A/" + cSUB_DELIMS + reserved).isType(UriLexer.FORMAT).at(4).isText("$");
+// test.run("$format=A/" + cSUB_DELIMS).has(TokenKind.FORMAT).isInput();
+// test.run("$format=A/" + cSUB_DELIMS + reserved).has(TokenKind.FORMAT).isText("$");
// Test lexer rule PCHAR rest
- test.run("$format=A/:@").isAllText("$format=A/:@").isType(UriLexer.FORMAT);
- test.run("$format=A/:@" + reserved).isType(UriLexer.FORMAT).at(4).isText(":@");
+// test.run("$format=A/:@").has(TokenKind.FORMAT).isInput();
+// test.run("$format=A/:@" + reserved).has(TokenKind.FORMAT).isText(":@");
// Test lexer rule PCHAR all
- test.run("$format=" + cPCHAR + "/" + cPCHAR).isAllInput().isType(UriLexer.FORMAT);
-
+// test.run("$format=" + cPCHAR + "/" + cPCHAR).has(TokenKind.FORMAT).isInput();
}
+ public class TokenValidator {
+
+ private String input = null;
+ private UriTokenizer tokenizer = null;
+ private String curText = null;
+
+ public TokenValidator run(final String uri) {
+ input = uri;
+ tokenizer = new UriTokenizer(uri);
+ curText = "";
+ return this;
+ }
+
+ public TokenValidator has(final TokenKind... expected) {
+ for (final TokenKind kind : expected) {
+ assertTrue(tokenizer.next(kind));
+ curText += tokenizer.getText();
+ }
+ return this;
+ }
+
+ public TokenValidator isText(final String expected) {
+ assertEquals(expected, tokenizer.getText());
+ return this;
+ }
+
+ public TokenValidator isInput() {
+ assertEquals(input, curText);
+ assertTrue(tokenizer.next(TokenKind.EOF));
+ return this;
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestUriParserImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestUriParserImpl.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestUriParserImpl.java
index 8790766..dd517f9 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestUriParserImpl.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestUriParserImpl.java
@@ -27,7 +27,7 @@ import org.apache.olingo.server.api.edmx.EdmxReference;
import org.apache.olingo.server.api.uri.UriInfoKind;
import org.apache.olingo.server.api.uri.UriResourceKind;
import org.apache.olingo.server.api.uri.queryoption.expression.MethodKind;
-import org.apache.olingo.server.core.uri.parser.UriParserSyntaxException;
+import org.apache.olingo.server.core.uri.parser.UriParserSemanticException;
import org.apache.olingo.server.core.uri.testutil.FilterValidator;
import org.apache.olingo.server.core.uri.testutil.ResourceValidator;
import org.apache.olingo.server.core.uri.testutil.TestUriValidator;
@@ -67,8 +67,7 @@ public class TestUriParserImpl {
+ "," + PropertyDateTimeOffset + "," + PropertyDuration + "," + PropertyGuid + "," + PropertyTimeOfDay;
@Test
- public void testBoundFunctionImport_VarParameters() {
-
+ public void boundFunctionImport_VarParameters() {
// no input
testRes.run("ESKeyNav(1)/olingo.odata.test1.BFCETKeyNavRTETKeyNav()")
.at(0).isUriPathInfoKind(UriResourceKind.entitySet)
@@ -89,9 +88,8 @@ public class TestUriParserImpl {
}
@Test
- public void testFunctionBound_varReturnType() {
-
- String esTwoKeyNav = "ESTwoKeyNav(PropertyInt16=1,PropertyString='ABC')";
+ public void functionBound_varReturnType() {
+ final String esTwoKeyNav = "ESTwoKeyNav(PropertyInt16=1,PropertyString='ABC')";
// returning primitive
testRes.run("ESTwoKeyNav/olingo.odata.test1.BFCESTwoKeyNavRTString()")
@@ -151,8 +149,7 @@ public class TestUriParserImpl {
}
@Test
- public void runActionImport_VarReturnType() {
-
+ public void actionImport_VarReturnType() {
testRes.run(ContainerProvider.AIRT_STRING).isKind(UriInfoKind.resource)
.first()
.isActionImport(ContainerProvider.AIRT_STRING)
@@ -189,7 +186,6 @@ public class TestUriParserImpl {
@Test
public void count() {
-
// count entity set
testRes.run("ESAllPrim/$count")
.at(0)
@@ -216,7 +212,7 @@ public class TestUriParserImpl {
}
@Test
- public void runCrossJoin() throws Exception {
+ public void crossJoin() throws Exception {
testUri.run("$crossjoin(ESAllKey)")
.isKind(UriInfoKind.crossjoin)
.isCrossJoinEntityList(Arrays.asList("ESAllKey"));
@@ -226,29 +222,15 @@ public class TestUriParserImpl {
.isCrossJoinEntityList(Arrays.asList("ESAllKey", "ESTwoPrim"));
}
- @Test(expected = UriValidationException.class)
- public void testEntityFailOnValidation1() throws Exception {
+ @Test
+ public void entityFailOnValidation() throws Exception {
// simple entity set; with qualifiedentityTypeName; with filter
- testUri.run("$entity/olingo.odata.test1.ETTwoPrim", "$filter=PropertyInt16 eq 123&$id=ESAllKey")
- .isIdText("ESAllKey")
- .goFilter().is("<<PropertyInt16> eq <123>>");
- }
-
- @Test(expected = UriParserSyntaxException.class)
- public void testEntityFailOnValidation2() throws Exception {
- // simple entity set; with qualifiedentityTypeName; with 2xformat(before and after), expand, filter
- testUri.run("$entity/olingo.odata.test1.ETTwoPrim",
- "$format=xml&$expand=*&abc=123&$id=ESBase&xyz=987&$filter=PropertyInt16 eq 123&$format=atom&$select=*")
- .isFormatText("atom")
- .isCustomParameter(0, "abc", "123")
- .isIdText("ESBase")
- .isCustomParameter(1, "xyz", "987")
- .isSelectItemStar(0);
+ testUri.runEx("$entity/olingo.odata.test1.ETTwoPrim", "$filter=PropertyInt16 eq 123&$id=ESAllKey")
+ .isExValidation(UriValidationException.MessageKeys.SYSTEM_QUERY_OPTION_NOT_ALLOWED);
}
@Test
- public void testEntity() throws Exception {
-
+ public void entity() throws Exception {
// simple entity set
testUri.run("$entity", "$id=ESAllPrim").isKind(UriInfoKind.entityId)
.isKind(UriInfoKind.entityId)
@@ -311,14 +293,11 @@ public class TestUriParserImpl {
.isKind(UriInfoKind.entityId)
.isEntityType(EntityTypeProvider.nameETBase)
.isIdText("ESTwoPrim")
- .isExpandText("*")
.goExpand().first().isSegmentStar();
-
}
@Test
public void entitySet() throws Exception {
-
// plain entity set
testRes.run("ESAllPrim")
.isEntitySet("ESAllPrim")
@@ -342,7 +321,7 @@ public class TestUriParserImpl {
.isKeyPredicate(1, "PropertyString", "'ABC'");
// with all keys
- testRes.run("ESAllKey(" + encode(allKeys) + ")")
+ testRes.run("ESAllKey(" + allKeys + ")")
.isEntitySet("ESAllKey")
.isKeyPredicate(0, "PropertyString", "'ABC'")
.isKeyPredicate(1, "PropertyInt16", "1")
@@ -360,10 +339,7 @@ public class TestUriParserImpl {
}
@Test
- public void testEntitySet_NavigationProperty() {
-
- // plain entity set ...
-
+ public void entitySet_NavigationProperty() {
// with navigation property
testRes.run("ESKeyNav(1)/NavPropertyETTwoKeyNavOne")
.at(0)
@@ -467,10 +443,7 @@ public class TestUriParserImpl {
}
@Test
- public void testEntitySet_Property() {
-
- // plain entity set ...
-
+ public void entitySet_Property() {
// with property
testRes.run("ESAllPrim(1)/PropertyString")
.at(0)
@@ -499,8 +472,7 @@ public class TestUriParserImpl {
}
@Test
- public void testEntitySet_TypeFilter() {
-
+ public void entitySet_TypeFilter() {
// filter
testRes.run("ESTwoPrim/olingo.odata.test1.ETBase")
.at(0)
@@ -556,57 +528,53 @@ public class TestUriParserImpl {
.at(1)
.isPrimitiveProperty("AdditionalPropertyString_5", PropertyProvider.nameString, false)
.isType(PropertyProvider.nameString);
-
}
@Test
public void unary() throws Exception {
- testFilter.runOnETAllPrim("not PropertyBoolean").isCompr("<not <PropertyBoolean>>");
- testFilter.runOnETAllPrim("-PropertyInt16 eq PropertyInt16").isCompr("<<- <PropertyInt16>> eq <PropertyInt16>>");
+ testFilter.runOnETAllPrim("not PropertyBoolean").is("<not <PropertyBoolean>>");
+ testFilter.runOnETAllPrim("-PropertyInt16 eq PropertyInt16").is("<<- <PropertyInt16>> eq <PropertyInt16>>");
}
- // TODO: Use correct types.
@Test
- @Ignore
public void filterComplexMixedPriority() throws Exception {
- testFilter.runOnETAllPrim("PropertyInt16 or PropertyInt32 and PropertyInt64")
- .isCompr("<<PropertyInt16> or <<PropertyInt32> and <PropertyInt64>>>");
- testFilter.runOnETAllPrim("PropertyInt16 or PropertyInt32 and PropertyInt64 eq PropertyByte")
- .isCompr("<<PropertyInt16> or <<PropertyInt32> and <<PropertyInt64> eq <PropertyByte>>>>");
- testFilter.runOnETAllPrim("PropertyInt16 or PropertyInt32 eq PropertyInt64 and PropertyByte")
- .isCompr("<<PropertyInt16> or <<<PropertyInt32> eq <PropertyInt64>> and <PropertyByte>>>");
- testFilter.runOnETAllPrim("PropertyInt16 or PropertyInt32 eq PropertyInt64 and PropertyByte eq PropertySByte")
- .isCompr("<<PropertyInt16> or <<<PropertyInt32> eq <PropertyInt64>> "
+ testFilter.runOnETAllPrim("PropertyBoolean or true and false")
+ .is("<<PropertyBoolean> or <<true> and <false>>>");
+ testFilter.runOnETAllPrim("PropertyBoolean or true and PropertyInt64 eq PropertyByte")
+ .is("<<PropertyBoolean> or <<true> and <<PropertyInt64> eq <PropertyByte>>>>");
+ testFilter.runOnETAllPrim("PropertyBoolean or PropertyInt32 eq PropertyInt64 and true")
+ .is("<<PropertyBoolean> or <<<PropertyInt32> eq <PropertyInt64>> and <true>>>");
+ testFilter.runOnETAllPrim("PropertyBoolean or PropertyInt32 eq PropertyInt64 and PropertyByte eq PropertySByte")
+ .is("<<PropertyBoolean> or <<<PropertyInt32> eq <PropertyInt64>> "
+ "and <<PropertyByte> eq <PropertySByte>>>>");
- testFilter.runOnETAllPrim("PropertyInt16 eq PropertyInt32 or PropertyInt64 and PropertyByte")
- .isCompr("<<<PropertyInt16> eq <PropertyInt32>> or <<PropertyInt64> and <PropertyByte>>>");
- testFilter.runOnETAllPrim("PropertyInt16 eq PropertyInt32 or PropertyInt64 and PropertyByte eq PropertySByte")
- .isCompr("<<<PropertyInt16> eq <PropertyInt32>> "
- + "or <<PropertyInt64> and <<PropertyByte> eq <PropertySByte>>>>");
- testFilter.runOnETAllPrim("PropertyInt16 eq PropertyInt32 or PropertyInt64 eq PropertyByte and PropertySByte")
- .isCompr("<<<PropertyInt16> eq <PropertyInt32>> "
- + "or <<<PropertyInt64> eq <PropertyByte>> and <PropertySByte>>>");
+ testFilter.runOnETAllPrim("PropertyInt16 eq PropertyInt32 or PropertyBoolean and true")
+ .is("<<<PropertyInt16> eq <PropertyInt32>> or <<PropertyBoolean> and <true>>>");
+ testFilter.runOnETAllPrim("PropertyInt16 eq PropertyInt32 or PropertyBoolean and PropertyByte eq PropertySByte")
+ .is("<<<PropertyInt16> eq <PropertyInt32>> "
+ + "or <<PropertyBoolean> and <<PropertyByte> eq <PropertySByte>>>>");
+ testFilter.runOnETAllPrim("PropertyInt16 eq PropertyInt32 or PropertyInt64 eq PropertyByte and PropertyBoolean")
+ .is("<<<PropertyInt16> eq <PropertyInt32>> "
+ + "or <<<PropertyInt64> eq <PropertyByte>> and <PropertyBoolean>>>");
testFilter.runOnETAllPrim("PropertyInt16 eq PropertyInt32 or PropertyInt64 eq PropertyByte "
+ "and PropertySByte eq PropertyDecimal")
- .isCompr("<<<PropertyInt16> eq <PropertyInt32>> or <<<PropertyInt64> eq <PropertyByte>> "
+ .is("<<<PropertyInt16> eq <PropertyInt32>> or <<<PropertyInt64> eq <PropertyByte>> "
+ "and <<PropertySByte> eq <PropertyDecimal>>>>");
}
@Test
public void filterSimpleSameBinaryBinaryBinaryPriority() throws Exception {
- testFilter.runOnETAllPrim("1 add 2 add 3 add 4").isCompr("<<< <1> add <2>> add <3>> add <4>>");
- testFilter.runOnETAllPrim("1 add 2 add 3 div 4").isCompr("<< <1> add <2>> add <<3> div <4>>>");
- testFilter.runOnETAllPrim("1 add 2 div 3 add 4").isCompr("<< <1> add <<2> div <3>>> add <4>>");
- testFilter.runOnETAllPrim("1 add 2 div 3 div 4").isCompr("< <1> add <<<2> div <3>> div <4>>>");
- testFilter.runOnETAllPrim("1 div 2 add 3 add 4").isCompr("<<< <1> div <2>> add <3>> add <4>>");
- testFilter.runOnETAllPrim("1 div 2 add 3 div 4").isCompr("<< <1> div <2>> add <<3> div <4>>>");
- testFilter.runOnETAllPrim("1 div 2 div 3 add 4").isCompr("<<< <1> div <2>> div <3>> add <4>>");
- testFilter.runOnETAllPrim("1 div 2 div 3 div 4").isCompr("<<< <1> div <2>> div <3>> div <4>>");
+ testFilter.runOnETAllPrim("1 add 2 add 3 add 4 ge 0").isCompr("<<<< <1> add <2>> add <3>> add <4>> ge <0>>");
+ testFilter.runOnETAllPrim("1 add 2 add 3 div 4 ge 0").isCompr("<<< <1> add <2>> add <<3> div <4>>> ge <0>>");
+ testFilter.runOnETAllPrim("1 add 2 div 3 add 4 ge 0").isCompr("<<< <1> add <<2> div <3>>> add <4>> ge <0>>");
+ testFilter.runOnETAllPrim("1 add 2 div 3 div 4 ge 0").isCompr("<< <1> add <<<2> div <3>> div <4>>> ge <0>>");
+ testFilter.runOnETAllPrim("1 div 2 add 3 add 4 ge 0").isCompr("<<<< <1> div <2>> add <3>> add <4>> ge <0>>");
+ testFilter.runOnETAllPrim("1 div 2 add 3 div 4 ge 0").isCompr("<<< <1> div <2>> add <<3> div <4>>> ge <0>>");
+ testFilter.runOnETAllPrim("1 div 2 div 3 add 4 ge 0").isCompr("<<<< <1> div <2>> div <3>> add <4>> ge <0>>");
+ testFilter.runOnETAllPrim("1 div 2 div 3 div 4 ge 0").isCompr("<<<< <1> div <2>> div <3>> div <4>> ge <0>>");
}
@Test
- public void testFunctionImport_VarParameters() {
-
+ public void functionImport_VarParameters() {
// no input
testRes.run("FINRTInt16()")
.isFunctionImport("FINRTInt16")
@@ -627,7 +595,7 @@ public class TestUriParserImpl {
}
@Test
- public void testFunctionImport_VarReturning() {
+ public void functionImport_VarReturning() {
// returning primitive
testRes.run("FINRTInt16()")
.isFunctionImport("FINRTInt16")
@@ -666,8 +634,7 @@ public class TestUriParserImpl {
}
@Test
- public void testFunctionImportChain() {
-
+ public void functionImportChain() {
// test chain; returning single complex
testRes.run("FICRTCTAllPrimTwoParam(ParameterString='ABC',ParameterInt16=1)/PropertyInt16")
.at(0)
@@ -710,12 +677,10 @@ public class TestUriParserImpl {
.isKeyPredicate(1, "PropertyString", "'ABC'")
.at(1)
.isPrimitiveProperty("PropertyInt16", PropertyProvider.nameInt16, false);
-
}
@Test
- public void testMetaData() throws Exception {
-
+ public void metaData() throws Exception {
// Parsing the fragment may be used if a uri has to be parsed on the consumer side.
// On the producer side this feature is currently not supported, so the context fragment
// part is only available as text.
@@ -879,12 +844,12 @@ public class TestUriParserImpl {
}
@Test
- public void testRef() throws Exception {
+ public void ref() throws Exception {
testUri.run("ESKeyNav(1)/NavPropertyETTwoKeyNavOne/$ref");
}
@Test
- public void testSingleton() {
+ public void singleton() {
// plain singleton
testRes.run("SINav")
.isSingleton("SINav")
@@ -892,10 +857,7 @@ public class TestUriParserImpl {
}
@Test
- public void testNavigationProperty() {
-
- // plain entity set ...
-
+ public void navigationProperty() {
// with navigation property
testRes.run("ESKeyNav(1)/NavPropertyETTwoKeyNavOne")
.at(0).isEntitySet("ESKeyNav")
@@ -969,10 +931,7 @@ public class TestUriParserImpl {
}
@Test
- public void testSingleton_Property() {
-
- // plain singleton ...
-
+ public void singleton_Property() {
// with property
testRes.run("SINav/PropertyInt16")
.at(0)
@@ -1002,72 +961,51 @@ public class TestUriParserImpl {
}
@Test
- public void testValue() throws Exception {
+ public void value() throws Exception {
testUri.run("ESAllPrim(1)/PropertyString/$value");
}
- @Test(expected = UriValidationException.class)
- public void testMemberStartingWithCastFailOnValidation1() throws Exception {
+ @Test
+ public void memberStartingWithCastFailOnValidation1() throws Exception {
// on EntityType entry
- testUri.run("ESTwoKeyNav(ParameterInt16=1,PropertyString='ABC')",
+ testUri.runEx("ESTwoKeyNav(Property16=1,PropertyString='ABC')",
"$filter=olingo.odata.test1.ETBaseTwoKeyNav/PropertyDate")
- .goFilter().root().isMember()
- .isMemberStartType(EntityTypeProvider.nameETBaseTwoKeyNav).goPath()
- // .at(0)
- // .isUriPathInfoKind(UriResourceKind.startingTypeFilter)
- // .isType(EntityTypeProvider.nameETTwoKeyNav, false)
- // .isTypeFilterOnEntry(EntityTypeProvider.nameETBaseTwoKeyNav)
- .at(0).isType(PropertyProvider.nameDate);
+ .isExValidation(UriValidationException.MessageKeys.INVALID_KEY_PROPERTY);
}
- @Test(expected = UriValidationException.class)
- public void testMemberStartingWithCastFailOnValidation2() throws Exception {
- testUri.run("FICRTCTTwoPrimTwoParam(ParameterInt16=1,ParameterString='2')",
+ @Test
+ public void memberStartingWithCastFailOnValidation2() throws Exception {
+ testUri.runEx("FICRTCTTwoPrimTwoParam(ParameterInt16=1,ParameterString='2')",
"$filter=olingo.odata.test1.CTBase/AdditionalPropString")
- .goFilter().root().isMember()
- .isMemberStartType(ComplexTypeProvider.nameCTBase).goPath()
- // .at(0)
- // .isUriPathInfoKind(UriResourceKind.startingTypeFilter)
- // .isType(ComplexTypeProvider.nameCTTwoPrim, false)
- // .isTypeFilterOnEntry(ComplexTypeProvider.nameCTBase)
- .at(0).isType(PropertyProvider.nameString);
+ .isExSemantic(UriParserSemanticException.MessageKeys.TYPES_NOT_COMPATIBLE);
}
@Test
- public void testMemberStartingWithCast() throws Exception {
-
+ public void memberStartingWithCast() throws Exception {
// on EntityType collection
- testUri.run("ESTwoKeyNav", "$filter=olingo.odata.test1.ETBaseTwoKeyNav/PropertyDate")
- .goFilter().root().isMember()
+ testFilter.runOnETTwoKeyNav("olingo.odata.test1.ETBaseTwoKeyNav/PropertyDate eq null")
+ .left()
+ .isMember()
.isMemberStartType(EntityTypeProvider.nameETBaseTwoKeyNav).goPath()
- // .at(0)
- // .isUriPathInfoKind(UriResourceKind.startingTypeFilter)
- // .isType(EntityTypeProvider.nameETTwoKeyNav, true)
- // .isTypeFilterOnCollection(EntityTypeProvider.nameETBaseTwoKeyNav)
.at(0).isType(PropertyProvider.nameDate);
// on Complex collection
testUri.run("FICRTCollCTTwoPrimTwoParam(ParameterInt16=1,ParameterString='2')",
- "$filter=olingo.odata.test1.CTBase/AdditionalPropString")
- .goFilter().root().isMember()
+ "$filter=olingo.odata.test1.CTBase/AdditionalPropString eq null")
+ .goFilter().left().isMember()
.isMemberStartType(ComplexTypeProvider.nameCTBase).goPath()
- // .at(0)
- // .isUriPathInfoKind(UriResourceKind.startingTypeFilter)
- // .isType(ComplexTypeProvider.nameCTTwoPrim, true)
- // .isTypeFilterOnCollection(ComplexTypeProvider.nameCTBase)
.at(0).isType(PropertyProvider.nameString);
-
}
@Test
- public void testComplexTypeCastFollowingAsCollection() throws Exception {
+ public void complexTypeCastFollowingAsCollection() throws Exception {
testUri.run("FICRTCollCTTwoPrimTwoParam(ParameterInt16=1,ParameterString='2')/olingo.odata.test1.CTBase");
}
@Test
- public void testAlias() throws Exception {
- testUri.run("ESAllPrim", "$filter=PropertyInt16 eq @p1&@p1=1")
- .goFilter().is("<<PropertyInt16> eq <@p1>>");
+ public void alias() throws Exception {
+ testFilter.runOnETAllPrim("PropertyInt16 eq @p1&@p1=1")
+ .is("<<PropertyInt16> eq <@p1>>");
}
@Test
@@ -1087,26 +1025,22 @@ public class TestUriParserImpl {
@Test
public void customQueryOption() throws Exception {
testUri.run("ESTwoKeyNav", "custom")
- .isCustomParameter(0, "custom", "");
+ .isCustomParameter(0, "custom", "");
testUri.run("ESTwoKeyNav", "custom=ABC")
- .isCustomParameter(0, "custom", "ABC");
+ .isCustomParameter(0, "custom", "ABC");
}
@Test
@Ignore("Geo types are not supported yet.")
public void geo() throws Exception {
testFilter.runOnETAllPrim("geo.distance(PropertySByte,PropertySByte)")
- .is("<geo.distance(<PropertySByte>,<PropertySByte>)>")
- .isMethod(MethodKind.GEODISTANCE, 2);
+ .is("<geo.distance(<PropertySByte>,<PropertySByte>)>")
+ .isMethod(MethodKind.GEODISTANCE, 2);
testFilter.runOnETAllPrim("geo.length(PropertySByte)")
- .is("<geo.length(<PropertySByte>)>")
- .isMethod(MethodKind.GEOLENGTH, 1);
+ .is("<geo.length(<PropertySByte>)>")
+ .isMethod(MethodKind.GEOLENGTH, 1);
testFilter.runOnETAllPrim("geo.intersects(PropertySByte,PropertySByte)")
- .is("<geo.intersects(<PropertySByte>,<PropertySByte>)>")
- .isMethod(MethodKind.GEOINTERSECTS, 2);
- }
-
- private final String encode(final String uriPart) {
- return uriPart.replaceAll(":", "%3A");
+ .is("<geo.intersects(<PropertySByte>,<PropertySByte>)>")
+ .isMethod(MethodKind.GEOINTERSECTS, 2);
}
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/parser/ParserTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/parser/ParserTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/parser/ParserTest.java
index f54ad04..af523aa 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/parser/ParserTest.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/parser/ParserTest.java
@@ -18,12 +18,18 @@
*/
package org.apache.olingo.server.core.uri.parser;
+import java.util.Collections;
+
import org.apache.olingo.commons.api.edm.Edm;
import org.apache.olingo.commons.api.edm.EdmEntityContainer;
import org.apache.olingo.commons.api.edm.EdmEntitySet;
import org.apache.olingo.commons.api.edm.EdmEntityType;
+import org.apache.olingo.commons.api.edm.EdmKeyPropertyRef;
import org.apache.olingo.commons.api.edm.EdmNavigationProperty;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
+import org.apache.olingo.commons.api.edm.EdmProperty;
import org.apache.olingo.commons.api.edm.FullQualifiedName;
+import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.uri.UriInfoKind;
import org.apache.olingo.server.core.uri.testutil.TestUriValidator;
import org.junit.Test;
@@ -33,17 +39,57 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
/**
- * All Tests which involves the <code>Parser</code> implementation
- * (and with that also the <code>UriParseTreeVisitor</code>).
+ * Tests of the <code>Parser</code> implementation that require mocking of the EDM.
*/
public class ParserTest {
+ @Test
+ public void navPropertySameNameAsEntitySet() throws Exception {
+ final String namespace = "namespace";
+ final String entityTypeName = "ETNavProp";
+ final FullQualifiedName nameETNavProp = new FullQualifiedName(namespace, entityTypeName);
+ final String entitySetName = "ESNavProp";
+ final String keyPropertyName = "a";
+ EdmProperty keyProperty = Mockito.mock(EdmProperty.class);
+ Mockito.when(keyProperty.getType())
+ .thenReturn(OData.newInstance().createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Byte));
+ EdmKeyPropertyRef keyPropertyRef = Mockito.mock(EdmKeyPropertyRef.class);
+ Mockito.when(keyPropertyRef.getName()).thenReturn(keyPropertyName);
+ Mockito.when(keyPropertyRef.getProperty()).thenReturn(keyProperty);
+ EdmNavigationProperty navProperty = Mockito.mock(EdmNavigationProperty.class);
+ Mockito.when(navProperty.getName()).thenReturn(entitySetName);
+ Mockito.when(navProperty.isCollection()).thenReturn(true);
+ EdmEntityType entityType = Mockito.mock(EdmEntityType.class);
+ Mockito.when(entityType.getFullQualifiedName()).thenReturn(nameETNavProp);
+ Mockito.when(entityType.getKeyPredicateNames()).thenReturn(Collections.singletonList(keyPropertyName));
+ Mockito.when(entityType.getKeyPropertyRefs()).thenReturn(Collections.singletonList(keyPropertyRef));
+ Mockito.when(entityType.getNavigationProperty(entitySetName)).thenReturn(navProperty);
+ Mockito.when(navProperty.getType()).thenReturn(entityType);
+ EdmEntitySet entitySet = Mockito.mock(EdmEntitySet.class);
+ Mockito.when(entitySet.getName()).thenReturn(entitySetName);
+ Mockito.when(entitySet.getEntityType()).thenReturn(entityType);
+ EdmEntityContainer container = Mockito.mock(EdmEntityContainer.class);
+ Mockito.when(container.getEntitySet(entitySetName)).thenReturn(entitySet);
+ Edm mockedEdm = Mockito.mock(Edm.class);
+ Mockito.when(mockedEdm.getEntityContainer()).thenReturn(container);
+ new TestUriValidator().setEdm(mockedEdm)
+ .run("ESNavProp(1)/ESNavProp(2)/ESNavProp(3)/ESNavProp")
+ .goPath()
+ .at(0).isEntitySet(entitySetName)
+ .at(0).isKeyPredicate(0, keyPropertyName, "1")
+ .at(1).isNavProperty(entitySetName, nameETNavProp, false)
+ .at(1).isKeyPredicate(0, keyPropertyName, "2")
+ .at(2).isNavProperty(entitySetName, nameETNavProp, false)
+ .at(2).isKeyPredicate(0, keyPropertyName, "3")
+ .at(3).isNavProperty(entitySetName, nameETNavProp, true);
+ }
+
/**
* Test for EntitySet and NavigationProperty with same name defined in metadata.
* (related to Olingo issue OLINGO-741)
*/
@Test
- public void parseEntitySetAndNavigationPropertyWithSameName() throws Exception {
+ public void expandNavigationPropertyWithSameNameAsEntitySet() throws Exception {
TestUriValidator testUri = new TestUriValidator();
Edm mockEdm = Mockito.mock(Edm.class);
@@ -60,7 +106,7 @@ public class ParserTest {
Mockito.when(typeCategory.getNamespace()).thenReturn("NS");
Mockito.when(esCategory.getEntityType()).thenReturn(typeCategory);
Mockito.when(productsNavigation.getName()).thenReturn("Products");
- Mockito.when(typeCategory.getProperty("Products")).thenReturn(productsNavigation);
+ Mockito.when(typeCategory.getNavigationProperty("Products")).thenReturn(productsNavigation);
Mockito.when(container.getEntitySet("Category")).thenReturn(esCategory);
Mockito.when(container.getEntitySet("Products")).thenReturn(esProduct);
Mockito.when(productsType.getFullQualifiedName()).thenReturn(nameProducts);
@@ -122,7 +168,7 @@ public class ParserTest {
.isType(new FullQualifiedName("NS", "Category"), false);
fail("Expected exception was not thrown.");
} catch (final UriParserException e) {
- assertEquals("NavigationProperty 'Category' not found in type 'NS.Products'", e.getMessage());
+ assertEquals("Navigation Property 'Category' not found in type 'NS.Products'.", e.getMessage());
}
}
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/ExpandValidator.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/ExpandValidator.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/ExpandValidator.java
index 5638227..35245b4 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/ExpandValidator.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/ExpandValidator.java
@@ -19,6 +19,7 @@
package org.apache.olingo.server.core.uri.testutil;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -151,12 +152,6 @@ public class ExpandValidator implements TestValidator {
return this;
}
- public ExpandValidator isSelectText(final String text) {
- final QueryOption option = expandItem.getSelectOption();
- assertEquals(text, option.getText());
- return this;
- }
-
public ExpandValidator isSelectItemStar(final int index) {
SelectOption select = expandItem.getSelectOption();
SelectItem item = select.getSelectItems().get(index);
@@ -171,12 +166,6 @@ public class ExpandValidator implements TestValidator {
return this;
}
- public ExpandValidator isFilterOptionText(final String text) {
- QueryOption option = expandItem.getFilterOption();
- assertEquals(text, option.getText());
- return this;
- }
-
public ExpandValidator isFilterSerialized(final String serialized) {
FilterOption filter = expandItem.getFilterOption();
@@ -201,7 +190,13 @@ public class ExpandValidator implements TestValidator {
}
public ExpandValidator isExpandStartType(final FullQualifiedName fullName) {
+ assertNotNull(expandItem.getStartTypeFilter());
assertEquals(fullName, expandItem.getStartTypeFilter().getFullQualifiedName());
return this;
}
+
+ public ExpandValidator isSearchSerialized(final String serialized) {
+ assertEquals(serialized, expandItem.getSearchOption().getSearchExpression().toString());
+ return this;
+ }
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/FilterValidator.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/FilterValidator.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/FilterValidator.java
index 0800dd0..161299c 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/FilterValidator.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/FilterValidator.java
@@ -46,13 +46,16 @@ import org.apache.olingo.server.api.uri.queryoption.expression.Member;
import org.apache.olingo.server.api.uri.queryoption.expression.Method;
import org.apache.olingo.server.api.uri.queryoption.expression.MethodKind;
import org.apache.olingo.server.api.uri.queryoption.expression.TypeLiteral;
+import org.apache.olingo.server.api.uri.queryoption.expression.Unary;
import org.apache.olingo.server.core.uri.UriResourceFunctionImpl;
import org.apache.olingo.server.core.uri.parser.Parser;
import org.apache.olingo.server.core.uri.parser.UriParserException;
import org.apache.olingo.server.core.uri.parser.UriParserSemanticException;
import org.apache.olingo.server.core.uri.parser.UriParserSyntaxException;
+import org.apache.olingo.server.core.uri.queryoption.expression.BinaryImpl;
import org.apache.olingo.server.core.uri.queryoption.expression.MemberImpl;
import org.apache.olingo.server.core.uri.queryoption.expression.MethodImpl;
+import org.apache.olingo.server.core.uri.queryoption.expression.UnaryImpl;
import org.apache.olingo.server.core.uri.validator.UriValidationException;
public class FilterValidator implements TestValidator {
@@ -127,7 +130,7 @@ public class FilterValidator implements TestValidator {
}
public FilterValidator runOrderByOnETTwoKeyNavEx(final String orderBy) throws UriParserException {
- return runUriOrderByEx("ESTwoKeyNav", "$orderby=" + orderBy.trim());
+ return runUriEx("ESTwoKeyNav", "$orderby=" + orderBy.trim());
}
public FilterValidator runOnETTwoKeyNav(final String filter) throws UriParserException, UriValidationException {
@@ -225,19 +228,6 @@ public class FilterValidator implements TestValidator {
return this;
}
- public FilterValidator runUriOrderByEx(final String path, final String query) {
- exception = null;
- try {
- new Parser(edm, odata).parseUri(path, query, null);
- fail("Expected exception not thrown.");
- } catch (final UriParserException e) {
- exception = e;
- } catch (final UriValidationException e) {
- exception = e;
- }
- return this;
- }
-
// --- Navigation ---
public ExpandValidator goUpToExpandValidator() {
@@ -274,8 +264,8 @@ public class FilterValidator implements TestValidator {
// --- Validation ---
/**
- * Validates the serialized filterTree against a given filterString
- * The given expected filterString is compressed before to allow better readable code in the unit tests
+ * Validates the serialized filterTree against a given filterString.
+ * The given expected filterString is compressed before to allow better readable code in the unit tests.
* @param toBeCompr
* @return {@link FilterValidator}
*/
@@ -310,14 +300,19 @@ public class FilterValidator implements TestValidator {
EdmType actualType = null;
if (curExpression instanceof Member) {
- Member member = (Member) curExpression;
- actualType = member.getType();
+ actualType = ((Member) curExpression).getType();
} else if (curExpression instanceof TypeLiteral) {
- TypeLiteral typeLiteral = (TypeLiteral) curExpression;
- actualType = typeLiteral.getType();
+ actualType = ((TypeLiteral) curExpression).getType();
} else if (curExpression instanceof Literal) {
- Literal typeLiteral = (Literal) curExpression;
- actualType = typeLiteral.getType();
+ actualType = ((Literal) curExpression).getType();
+ } else if (curExpression instanceof Enumeration) {
+ actualType = ((Enumeration) curExpression).getType();
+ } else if (curExpression instanceof Unary) {
+ actualType = ((UnaryImpl) curExpression).getType();
+ } else if (curExpression instanceof Binary) {
+ actualType = ((BinaryImpl) curExpression).getType();
+ } else if (curExpression instanceof Method) {
+ actualType = ((MethodImpl) curExpression).getType();
}
if (actualType == null) {
@@ -349,7 +344,6 @@ public class FilterValidator implements TestValidator {
curExpression = ((Binary) curExpression).getRightOperand();
return this;
-
}
public FilterValidator isLiteral(final String literalText) {
@@ -361,9 +355,9 @@ public class FilterValidator implements TestValidator {
assertEquals(literalText, actualLiteralText);
return this;
}
-
- public FilterValidator isLiteralType(EdmType edmType) {
- if(!(curExpression instanceof Literal)) {
+
+ public FilterValidator isLiteralType(final EdmType edmType) {
+ if (!(curExpression instanceof Literal)) {
fail("Current expression is not a literal");
}
@@ -374,7 +368,7 @@ public class FilterValidator implements TestValidator {
}
public FilterValidator isNullLiteralType() {
- if(!(curExpression instanceof Literal)) {
+ if (!(curExpression instanceof Literal)) {
fail("Current expression is not a literal");
}
@@ -495,12 +489,4 @@ public class FilterValidator implements TestValidator {
assertEquals(messageKey, exception.getMessageKey());
return this;
}
-
- public FilterValidator isNull() {
- return isLiteral("null");
- }
-
- public FilterValidator isTrue() {
- return isLiteral("true");
- }
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/TestUriValidator.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/TestUriValidator.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/TestUriValidator.java
index 1dbe62b..fbce5c9 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/TestUriValidator.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/TestUriValidator.java
@@ -140,6 +140,20 @@ public class TestUriValidator implements TestValidator {
return this;
}
+ public TestUriValidator isSelectItemStar(final int index) {
+ final SelectOption select = uriInfo.getSelectOption();
+ SelectItem item = select.getSelectItems().get(index);
+ assertTrue(item.isStar());
+ return this;
+ }
+
+ public TestUriValidator isSelectItemAllOp(final int index, final FullQualifiedName fqn) {
+ final SelectOption select = uriInfo.getSelectOption();
+ SelectItem item = select.getSelectItems().get(index);
+ assertEquals(fqn, item.getAllOperationsInSchemaNameSpace());
+ return this;
+ }
+
// Validation
public TestUriValidator isKind(final UriInfoKind kind) {
assertEquals(kind, uriInfo.getKind());
@@ -202,16 +216,6 @@ public class TestUriValidator implements TestValidator {
return this;
}
- public TestUriValidator isExpandText(final String text) {
- assertEquals(text, uriInfo.getExpandOption().getText());
- return this;
- }
-
- public TestUriValidator isSelectText(final String text) {
- assertEquals(text, uriInfo.getSelectOption().getText());
- return this;
- }
-
public TestUriValidator isFormatText(final String text) {
assertEquals(text, uriInfo.getFormatOption().getText());
return this;
@@ -234,18 +238,4 @@ public class TestUriValidator implements TestValidator {
assertEquals(fullName, uriInfo.getEntityTypeCast().getFullQualifiedName());
return this;
}
-
- public TestUriValidator isSelectItemStar(final int index) {
- final SelectOption select = uriInfo.getSelectOption();
- SelectItem item = select.getSelectItems().get(index);
- assertTrue(item.isStar());
- return this;
- }
-
- public TestUriValidator isSelectItemAllOp(final int index, final FullQualifiedName fqn) {
- final SelectOption select = uriInfo.getSelectOption();
- SelectItem item = select.getSelectItems().get(index);
- assertEquals(fqn, item.getAllOperationsInSchemaNameSpace());
- return this;
- }
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/TokenValidator.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/TokenValidator.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/TokenValidator.java
deleted file mode 100644
index 547c2ea..0000000
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/TokenValidator.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.olingo.server.core.uri.testutil;
-
-import static org.junit.Assert.assertEquals;
-
-import java.util.List;
-
-import org.antlr.v4.runtime.ANTLRInputStream;
-import org.antlr.v4.runtime.Token;
-import org.apache.olingo.server.core.uri.antlr.UriLexer;
-
-public class TokenValidator {
-
- private String input = null;
- private List<? extends Token> tokens = null;
- private Token curToken = null;
- private Exception curException = null;
-
- private int startMode;
-
- // --- Execution ---
-
- public TokenValidator run(final String uri) {
- input = uri;
- tokens = parseInput(uri);
- first();
- return this;
- }
-
- // --- Navigation ---
-
- // navigate within the tokenlist
- public TokenValidator first() {
- try {
- curToken = tokens.get(0);
- } catch (IndexOutOfBoundsException ex) {
- curToken = null;
- }
- return this;
- }
-
- public TokenValidator last() {
- curToken = tokens.get(tokens.size() - 1);
- return this;
- }
-
- public TokenValidator at(final int index) {
- try {
- curToken = tokens.get(index);
- } catch (IndexOutOfBoundsException ex) {
- curToken = null;
- }
- return this;
- }
-
- // --- Validation ---
-
- public TokenValidator isText(final String expected) {
- assertEquals(expected, curToken.getText());
- return this;
- }
-
- public TokenValidator isAllText(final String expected) {
- String actual = "";
-
- for (Token curToken : tokens) {
- actual += curToken.getText();
- }
- assertEquals(expected, actual);
- return this;
- }
-
- public TokenValidator isAllInput() {
- String actual = "";
-
- for (Token curToken : tokens) {
- actual += curToken.getText();
- }
- assertEquals(input, actual);
- return this;
- }
-
- public TokenValidator isInput() {
- assertEquals(input, curToken.getText());
- return this;
- }
-
- public TokenValidator isType(final int expected) {
- assertEquals(UriLexer.VOCABULARY.getDisplayName(expected), UriLexer.VOCABULARY.getDisplayName(curToken.getType()));
- return this;
- }
-
- public TokenValidator isExType(final Class<?> exClass) {
- assertEquals(exClass, curException.getClass());
- return this;
- }
-
- public void globalMode(final int mode) {
- startMode = mode;
- }
-
- // --- Helper ---
-
- private List<? extends Token> parseInput(final String input) {
- ANTLRInputStream inputStream = new ANTLRInputStream(input);
- UriLexer lexer = new UriLexer(inputStream);
- lexer.mode(startMode);
- return lexer.getAllTokens();
- }
-}
[6/6] olingo-odata4 git commit: [OLINGO-834] $expand parser in Java +
clean-up
Posted by ch...@apache.org.
[OLINGO-834] $expand parser in Java + clean-up
Signed-off-by: Christian Amend <ch...@sap.com>
Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/8925274c
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/8925274c
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/8925274c
Branch: refs/heads/OLINGO-834_Filter_Parser
Commit: 8925274c0b5bd6936c3f6c1d3ab55608ced2cf13
Parents: 8919d3e
Author: Klaus Straubinger <kl...@sap.com>
Authored: Thu Jan 7 13:55:34 2016 +0100
Committer: Christian Amend <ch...@sap.com>
Committed: Thu Jan 7 14:02:09 2016 +0100
----------------------------------------------------------------------
.../tecsvc/client/FilterSystemQueryITCase.java | 7 +-
.../tecsvc/client/OrderBySystemQueryITCase.java | 7 +-
.../server/api/uri/queryoption/ExpandItem.java | 1 -
.../server/core/uri/parser/ExpandParser.java | 282 +++
.../core/uri/parser/ExpressionParser.java | 332 +--
.../server/core/uri/parser/FilterParser.java | 11 +-
.../olingo/server/core/uri/parser/Parser.java | 234 +-
.../server/core/uri/parser/ParserHelper.java | 34 +-
.../core/uri/parser/ResourcePathParser.java | 62 +-
.../server/core/uri/parser/SearchParser.java | 108 +
.../server/core/uri/parser/UriContext.java | 115 -
.../core/uri/parser/UriParseTreeVisitor.java | 2313 ------------------
.../server/core/uri/parser/UriTokenizer.java | 211 +-
.../uri/queryoption/expression/AliasImpl.java | 4 +
.../queryoption/expression/EnumerationImpl.java | 6 +
.../queryoption/expression/LambdaRefImpl.java | 5 +
.../queryoption/expression/TypeLiteralImpl.java | 5 +
.../server-core-exceptions-i18n.properties | 8 +-
.../core/uri/parser/ExpressionParserTest.java | 14 +-
.../core/uri/parser/UriTokenizerTest.java | 82 +-
.../search/SearchParserAndTokenizerTest.java | 44 +-
.../core/uri/antlr/TestFullResourcePath.java | 1311 +++++-----
.../olingo/server/core/uri/antlr/TestLexer.java | 450 ++--
.../core/uri/antlr/TestUriParserImpl.java | 220 +-
.../server/core/uri/parser/ParserTest.java | 56 +-
.../core/uri/testutil/ExpandValidator.java | 19 +-
.../core/uri/testutil/FilterValidator.java | 56 +-
.../core/uri/testutil/TestUriValidator.java | 38 +-
.../core/uri/testutil/TokenValidator.java | 127 -
29 files changed, 1941 insertions(+), 4221 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/FilterSystemQueryITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/FilterSystemQueryITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/FilterSystemQueryITCase.java
index ca6eb21..6865a65 100644
--- a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/FilterSystemQueryITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/FilterSystemQueryITCase.java
@@ -35,11 +35,8 @@ import org.apache.olingo.commons.api.edm.FullQualifiedName;
import org.apache.olingo.commons.api.http.HttpHeader;
import org.apache.olingo.commons.api.http.HttpStatusCode;
import org.junit.Assert;
-import org.junit.Ignore;
import org.junit.Test;
-// TODO
-@Ignore
public class FilterSystemQueryITCase extends AbstractParamTecSvcITCase {
private static final String ES_COMP_ALL_PRIM = "ESCompAllPrim";
@@ -212,7 +209,7 @@ public class FilterSystemQueryITCase extends AbstractParamTecSvcITCase {
sendRequest(ES_TWO_KEY_NAV, "PropertyComp/PropertyComp/PropertyBoolean eq not null");
assertEquals(0, result.getBody().getEntities().size());
- result = sendRequest(ES_TWO_KEY_NAV, "PropertyComp/PropertyComp/PropertyBoolean eq 0 add -(5 add null)");
+ result = sendRequest(ES_TWO_KEY_NAV, "PropertyComp/PropertyComp/PropertyInt16 eq 0 add -(5 add null)");
assertEquals(0, result.getBody().getEntities().size());
}
@@ -357,7 +354,7 @@ public class FilterSystemQueryITCase extends AbstractParamTecSvcITCase {
@Test
public void notOperator() {
- ODataRetrieveResponse<ClientEntitySet> result = sendRequest(ES_TWO_KEY_NAV, "not(PropertyInt16 eq 1)");
+ ODataRetrieveResponse<ClientEntitySet> result = sendRequest(ES_TWO_KEY_NAV, "not (PropertyInt16 eq 1)");
assertEquals(2, result.getBody().getEntities().size());
ClientEntity clientEntity = result.getBody().getEntities().get(0);
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/OrderBySystemQueryITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/OrderBySystemQueryITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/OrderBySystemQueryITCase.java
index 0e31b33..8e16a70 100644
--- a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/OrderBySystemQueryITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/OrderBySystemQueryITCase.java
@@ -30,11 +30,8 @@ import org.apache.olingo.client.api.domain.ClientEntitySet;
import org.apache.olingo.client.api.domain.ClientValuable;
import org.apache.olingo.commons.api.http.HttpStatusCode;
import org.junit.Assert;
-import org.junit.Ignore;
import org.junit.Test;
-// TODO
-@Ignore
public class OrderBySystemQueryITCase extends AbstractParamTecSvcITCase {
private static final String ES_TWO_PRIM = "ESTwoPrim";
@@ -74,7 +71,7 @@ public class OrderBySystemQueryITCase extends AbstractParamTecSvcITCase {
@Test
public void multipleOrderBy() {
- final ODataRetrieveResponse<ClientEntitySet> response = sendRequest(ES_ALL_PRIM, "PropertyByte, PropertyInt16");
+ final ODataRetrieveResponse<ClientEntitySet> response = sendRequest(ES_ALL_PRIM, "PropertyByte,PropertyInt16");
assertEquals(3, response.getBody().getEntities().size());
ClientEntity clientEntity = response.getBody().getEntities().get(0);
@@ -90,7 +87,7 @@ public class OrderBySystemQueryITCase extends AbstractParamTecSvcITCase {
@Test
public void multipleOrderByDescending() {
final ODataRetrieveResponse<ClientEntitySet> response =
- sendRequest(ES_ALL_PRIM, "PropertyByte, PropertyInt16 desc");
+ sendRequest(ES_ALL_PRIM, "PropertyByte,PropertyInt16 desc");
assertEquals(3, response.getBody().getEntities().size());
ClientEntity clientEntity = response.getBody().getEntities().get(0);
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/queryoption/ExpandItem.java
----------------------------------------------------------------------
diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/queryoption/ExpandItem.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/queryoption/ExpandItem.java
index a16c137..fccf844 100644
--- a/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/queryoption/ExpandItem.java
+++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/queryoption/ExpandItem.java
@@ -38,7 +38,6 @@ public interface ExpandItem {
FilterOption getFilterOption();
/**
- * <b>CURRENTLY NOT SUPPORTED. WILL ALWAYS RETURN NULL</b>
* @return Information of the option $search when used within $expand
*/
SearchOption getSearchOption();
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpandParser.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpandParser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpandParser.java
new file mode 100644
index 0000000..d8209d8
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpandParser.java
@@ -0,0 +1,282 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.server.core.uri.parser;
+
+import org.apache.olingo.commons.api.edm.Edm;
+import org.apache.olingo.commons.api.edm.EdmEntityType;
+import org.apache.olingo.commons.api.edm.EdmNavigationProperty;
+import org.apache.olingo.commons.api.edm.EdmProperty;
+import org.apache.olingo.commons.api.edm.EdmStructuredType;
+import org.apache.olingo.commons.api.edm.FullQualifiedName;
+import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
+import org.apache.olingo.commons.api.ex.ODataRuntimeException;
+import org.apache.olingo.server.api.OData;
+import org.apache.olingo.server.api.uri.UriInfoKind;
+import org.apache.olingo.server.api.uri.UriResourceNavigation;
+import org.apache.olingo.server.api.uri.UriResourcePartTyped;
+import org.apache.olingo.server.api.uri.queryoption.ExpandItem;
+import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
+import org.apache.olingo.server.api.uri.queryoption.LevelsExpandOption;
+import org.apache.olingo.server.api.uri.queryoption.SystemQueryOption;
+import org.apache.olingo.server.api.uri.queryoption.SystemQueryOptionKind;
+import org.apache.olingo.server.core.uri.UriInfoImpl;
+import org.apache.olingo.server.core.uri.UriResourceComplexPropertyImpl;
+import org.apache.olingo.server.core.uri.UriResourceCountImpl;
+import org.apache.olingo.server.core.uri.UriResourceNavigationPropertyImpl;
+import org.apache.olingo.server.core.uri.UriResourceRefImpl;
+import org.apache.olingo.server.core.uri.parser.UriTokenizer.TokenKind;
+import org.apache.olingo.server.core.uri.queryoption.CountOptionImpl;
+import org.apache.olingo.server.core.uri.queryoption.ExpandItemImpl;
+import org.apache.olingo.server.core.uri.queryoption.ExpandOptionImpl;
+import org.apache.olingo.server.core.uri.queryoption.LevelsOptionImpl;
+import org.apache.olingo.server.core.uri.queryoption.SkipOptionImpl;
+import org.apache.olingo.server.core.uri.queryoption.TopOptionImpl;
+import org.apache.olingo.server.core.uri.validator.UriValidationException;
+
+public class ExpandParser {
+
+ private final Edm edm;
+ private final OData odata;
+
+ public ExpandParser(final Edm edm, final OData odata) {
+ this.edm = edm;
+ this.odata = odata;
+ }
+
+ public ExpandOption parse(UriTokenizer tokenizer, final EdmStructuredType referencedType)
+ throws UriParserException, UriValidationException {
+ ExpandOptionImpl expandOption = new ExpandOptionImpl();
+ do {
+ final ExpandItem item = parseItem(tokenizer, referencedType);
+ expandOption.addExpandItem(item);
+ } while (tokenizer.next(TokenKind.COMMA));
+
+ return expandOption;
+ }
+
+ private ExpandItem parseItem(UriTokenizer tokenizer, final EdmStructuredType referencedType)
+ throws UriParserException, UriValidationException {
+ ExpandItemImpl item = new ExpandItemImpl();
+ if (tokenizer.next(TokenKind.STAR)) {
+ item.setIsStar(true);
+ if (tokenizer.next(TokenKind.SLASH)) {
+ ParserHelper.requireNext(tokenizer, TokenKind.REF);
+ item.setIsRef(true);
+ } else if (tokenizer.next(TokenKind.OPEN)) {
+ ParserHelper.requireNext(tokenizer, TokenKind.LEVELS);
+ ParserHelper.requireNext(tokenizer, TokenKind.EQ);
+ item.setSystemQueryOption((SystemQueryOption) parseLevels(tokenizer));
+ ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
+ }
+
+ } else {
+ final EdmStructuredType typeCast = parseTypeCast(tokenizer, referencedType);
+ if (typeCast != null) {
+ item.setTypeFilter(typeCast);
+ ParserHelper.requireNext(tokenizer, TokenKind.SLASH);
+ }
+
+ UriInfoImpl resource = parseExpandPath(tokenizer, referencedType);
+
+ UriResourcePartTyped lastPart = (UriResourcePartTyped) resource.getLastResourcePart();
+
+ boolean hasSlash = false;
+ if (tokenizer.next(TokenKind.SLASH)) {
+ hasSlash = true;
+ if (lastPart instanceof UriResourceNavigation) {
+ UriResourceNavigationPropertyImpl navigationResource = (UriResourceNavigationPropertyImpl) lastPart;
+ final EdmNavigationProperty navigationProperty = navigationResource.getProperty();
+ final EdmStructuredType typeCastSuffix = parseTypeCast(tokenizer, navigationProperty.getType());
+ if (typeCastSuffix != null) {
+ if (navigationProperty.isCollection()) {
+ navigationResource.setCollectionTypeFilter(typeCastSuffix);
+ } else {
+ navigationResource.setEntryTypeFilter(typeCastSuffix);
+ }
+ hasSlash = false;
+ }
+ }
+ }
+
+ final EdmStructuredType newReferencedType = (EdmStructuredType) lastPart.getType();
+ final boolean newReferencedIsCollection = lastPart.isCollection();
+ if (hasSlash || tokenizer.next(TokenKind.SLASH)) {
+ if (tokenizer.next(TokenKind.REF)) {
+ resource.addResourcePart(new UriResourceRefImpl());
+ parseOptions(tokenizer, newReferencedType, newReferencedIsCollection, item, true, false);
+ } else {
+ ParserHelper.requireNext(tokenizer, TokenKind.COUNT);
+ resource.addResourcePart(new UriResourceCountImpl());
+ parseOptions(tokenizer, newReferencedType, newReferencedIsCollection, item, false, true);
+ }
+ } else {
+ parseOptions(tokenizer, newReferencedType, newReferencedIsCollection, item, false, false);
+ }
+
+ item.setResourcePath(resource);
+ }
+
+ return item;
+ }
+
+ private EdmStructuredType parseTypeCast(UriTokenizer tokenizer, final EdmStructuredType referencedType)
+ throws UriParserException {
+ if (tokenizer.next(TokenKind.QualifiedName)) {
+ final FullQualifiedName qualifiedName = new FullQualifiedName(tokenizer.getText());
+ final EdmStructuredType type = referencedType instanceof EdmEntityType ?
+ edm.getEntityType(qualifiedName) :
+ edm.getComplexType(qualifiedName);
+ if (type == null) {
+ throw new UriParserSemanticException("Type '" + qualifiedName + "' not found.",
+ UriParserSemanticException.MessageKeys.UNKNOWN_PART, qualifiedName.getFullQualifiedNameAsString());
+ } else {
+ if (!type.compatibleTo(referencedType)) {
+ throw new UriParserSemanticException("The type cast '" + qualifiedName + "' is not compatible.",
+ UriParserSemanticException.MessageKeys.INCOMPATIBLE_TYPE_FILTER, type.getName());
+ }
+ }
+ return type;
+ }
+ return null;
+ }
+
+ private UriInfoImpl parseExpandPath(UriTokenizer tokenizer, final EdmStructuredType referencedType)
+ throws UriParserException {
+ UriInfoImpl resource = new UriInfoImpl().setKind(UriInfoKind.resource);
+
+ EdmStructuredType type = referencedType;
+ String name = null;
+ while (tokenizer.next(TokenKind.ODataIdentifier)) {
+ name = tokenizer.getText();
+ final EdmProperty property = referencedType.getStructuralProperty(name);
+ if (property != null && property.getType().getKind() == EdmTypeKind.COMPLEX) {
+ type = (EdmStructuredType) property.getType();
+ UriResourceComplexPropertyImpl complexResource = new UriResourceComplexPropertyImpl(property);
+ ParserHelper.requireNext(tokenizer, TokenKind.SLASH);
+ final EdmStructuredType typeCast = parseTypeCast(tokenizer, type);
+ if (typeCast != null) {
+ complexResource.setTypeFilter(typeCast);
+ ParserHelper.requireNext(tokenizer, TokenKind.SLASH);
+ type = typeCast;
+ }
+ resource.addResourcePart(complexResource);
+ }
+ }
+
+ final EdmNavigationProperty navigationProperty = type.getNavigationProperty(name);
+ if (navigationProperty == null) {
+ // TODO: could also have been star after complex property (and maybe type cast)
+ throw new UriParserSemanticException(
+ "Navigation Property '" + name + "' not found in type '" + type.getFullQualifiedName() + "'.",
+ UriParserSemanticException.MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE, type.getName(), name);
+ } else {
+ resource.addResourcePart(new UriResourceNavigationPropertyImpl(navigationProperty));
+ }
+
+ return resource;
+ }
+
+ private void parseOptions(UriTokenizer tokenizer,
+ final EdmStructuredType referencedType, final boolean referencedIsCollection,
+ ExpandItemImpl item,
+ final boolean forRef, final boolean forCount) throws UriParserException, UriValidationException {
+ if (tokenizer.next(TokenKind.OPEN)) {
+ do {
+ SystemQueryOption systemQueryOption;
+ if (!forCount && tokenizer.next(TokenKind.COUNT)) {
+ ParserHelper.requireNext(tokenizer, TokenKind.EQ);
+ ParserHelper.requireNext(tokenizer, TokenKind.BooleanValue);
+ CountOptionImpl countOption = new CountOptionImpl();
+ countOption.setText(tokenizer.getText());
+ countOption.setValue(Boolean.parseBoolean(tokenizer.getText()));
+ systemQueryOption = countOption;
+
+ } else if (!forRef && !forCount && tokenizer.next(TokenKind.EXPAND)) {
+ ParserHelper.requireNext(tokenizer, TokenKind.EQ);
+ systemQueryOption = new ExpandParser(edm, odata).parse(tokenizer, referencedType);
+
+ } else if (tokenizer.next(TokenKind.FILTER)) {
+ ParserHelper.requireNext(tokenizer, TokenKind.EQ);
+ systemQueryOption = new FilterParser(edm, odata).parse(tokenizer, referencedType, null);
+
+ } else if (!forRef && !forCount && tokenizer.next(TokenKind.LEVELS)) {
+ ParserHelper.requireNext(tokenizer, TokenKind.EQ);
+ systemQueryOption = (SystemQueryOption) parseLevels(tokenizer);
+
+ } else if (!forCount && tokenizer.next(TokenKind.ORDERBY)) {
+ ParserHelper.requireNext(tokenizer, TokenKind.EQ);
+ systemQueryOption = new OrderByParser(edm, odata).parse(tokenizer, referencedType, null);
+
+ } else if (tokenizer.next(TokenKind.SEARCH)) {
+ ParserHelper.requireNext(tokenizer, TokenKind.EQ);
+ systemQueryOption = new SearchParser().parse(tokenizer);
+
+ } else if (!forRef && !forCount && tokenizer.next(TokenKind.SELECT)) {
+ ParserHelper.requireNext(tokenizer, TokenKind.EQ);
+ systemQueryOption = new SelectParser(edm).parse(tokenizer, referencedType, referencedIsCollection);
+
+ } else if (!forCount && tokenizer.next(TokenKind.SKIP)) {
+ ParserHelper.requireNext(tokenizer, TokenKind.EQ);
+ ParserHelper.requireNext(tokenizer, TokenKind.IntegerValue);
+ final int value = ParserHelper.parseNonNegativeInteger(SystemQueryOptionKind.SKIP.toString(),
+ tokenizer.getText(), true);
+ SkipOptionImpl skipOption = new SkipOptionImpl();
+ skipOption.setText(tokenizer.getText());
+ skipOption.setValue(value);
+ systemQueryOption = skipOption;
+
+ } else if (!forCount && tokenizer.next(TokenKind.TOP)) {
+ ParserHelper.requireNext(tokenizer, TokenKind.EQ);
+ ParserHelper.requireNext(tokenizer, TokenKind.IntegerValue);
+ final int value = ParserHelper.parseNonNegativeInteger(SystemQueryOptionKind.TOP.toString(),
+ tokenizer.getText(), true);
+ TopOptionImpl topOption = new TopOptionImpl();
+ topOption.setText(tokenizer.getText());
+ topOption.setValue(value);
+ systemQueryOption = topOption;
+
+ } else {
+ throw new UriParserSyntaxException("Allowed query option expected.",
+ UriParserSyntaxException.MessageKeys.SYNTAX);
+ }
+ try {
+ item.setSystemQueryOption(systemQueryOption);
+ } catch (final ODataRuntimeException e) {
+ throw new UriParserSyntaxException("Double system query option '" + systemQueryOption.getName() + "'.", e,
+ UriParserSyntaxException.MessageKeys.DOUBLE_SYSTEM_QUERY_OPTION, systemQueryOption.getName());
+ }
+ } while (tokenizer.next(TokenKind.SEMI));
+ ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
+ }
+ }
+
+ private LevelsExpandOption parseLevels(UriTokenizer tokenizer) throws UriParserException {
+ final LevelsOptionImpl option = new LevelsOptionImpl();
+ if (tokenizer.next(TokenKind.MAX)) {
+ option.setText(tokenizer.getText());
+ option.setMax();
+ } else {
+ ParserHelper.requireNext(tokenizer, TokenKind.IntegerValue);
+ option.setText(tokenizer.getText());
+ option.setValue(
+ ParserHelper.parseNonNegativeInteger(SystemQueryOptionKind.LEVELS.toString(), tokenizer.getText(), false));
+ }
+ return option;
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java
index 049880f..6fa415f 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java
@@ -47,9 +47,6 @@ import org.apache.olingo.commons.api.edm.EdmType;
import org.apache.olingo.commons.api.edm.EdmTypeDefinition;
import org.apache.olingo.commons.api.edm.FullQualifiedName;
import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmByte;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmPrimitiveTypeFactory;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmSByte;
import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.uri.UriParameter;
import org.apache.olingo.server.api.uri.UriResourceFunction;
@@ -161,7 +158,7 @@ public class ExpressionParser {
private static final Map<TokenKind, EdmPrimitiveTypeKind> tokenToPrimitiveType;
static {
- /* Enum and null are not present in the map. These have to be handled differently */
+ /* Enum and null are not present in the map. These have to be handled differently. */
Map<TokenKind, EdmPrimitiveTypeKind> temp = new HashMap<TokenKind, EdmPrimitiveTypeKind>();
temp.put(TokenKind.BooleanValue, EdmPrimitiveTypeKind.Boolean);
temp.put(TokenKind.StringValue, EdmPrimitiveTypeKind.String);
@@ -242,9 +239,9 @@ public class ExpressionParser {
}
private Expression parseExprRel() throws UriParserException, UriValidationException {
- if(tokenizer.next(TokenKind.IsofMethod)) {
- // The isof method is a terminal. So no further operators are allowed
- return parseIsOfMethod(TokenKind.IsofMethod);
+ if (tokenizer.next(TokenKind.IsofMethod)) {
+ // The isof method is a terminal. So no further operators are allowed.
+ return parseIsOfOrCastMethod(MethodKind.ISOF);
} else {
Expression left = parseExprAdd();
TokenKind operatorTokenKind = ParserHelper.next(tokenizer,
@@ -264,30 +261,25 @@ public class ExpressionParser {
}
}
- private Expression parseIsOfMethod(final TokenKind lastToken) throws UriParserException, UriValidationException {
- if(lastToken == TokenKind.IsofMethod) {
- // The TokenKind 'IsOfMethod' consumes also the opening parenthesis
-
- // The first parameter could be an expression or a type literal
- final List<Expression> parameters = new ArrayList<Expression>();
+ private Expression parseIsOfOrCastMethod(final MethodKind kind) throws UriParserException, UriValidationException {
+ // The TokenKind 'IsOfMethod' consumes also the opening parenthesis.
+ // The first parameter could be an expression or a type literal.
+ List<Expression> parameters = new ArrayList<Expression>();
+ parameters.add(parseExpression());
+ if (!(parameters.get(0) instanceof TypeLiteral)) {
+ // The first parameter is not a type literal, so there must be a second parameter.
+ ParserHelper.requireNext(tokenizer, TokenKind.COMMA);
parameters.add(parseExpression());
- if(!(parameters.get(0) instanceof TypeLiteral)) {
- // The first parameter is not a type literal, so there must be a second parameter
- ParserHelper.requireNext(tokenizer, TokenKind.COMMA);
- parameters.add(parseExpression());
-
- // The second parameter must be a type literal
- if(!(parameters.get(1) instanceof TypeLiteral)) {
- throw new UriParserSemanticException("Type literal extected",
- UriParserSemanticException.MessageKeys.INCOMPATIBLE_TYPE_FILTER);
- }
+
+ // The second parameter must be a type literal.
+ if (!(parameters.get(1) instanceof TypeLiteral)) {
+ throw new UriParserSemanticException("Type literal expected.",
+ UriParserSemanticException.MessageKeys.INCOMPATIBLE_TYPE_FILTER);
}
-
- ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
- return new MethodImpl(MethodKind.ISOF, parameters);
- } else {
- throw new UriParserSyntaxException("Unexpected token.", UriParserSyntaxException.MessageKeys.SYNTAX);
}
+
+ ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
+ return new MethodImpl(kind, parameters);
}
private Expression parseExprAdd() throws UriParserException, UriValidationException {
@@ -296,9 +288,9 @@ public class ExpressionParser {
// Null for everything other than ADD or SUB
while (operatorTokenKind != null) {
final Expression right = parseExprMul();
- checkAddSubTypes(left, right, operatorTokenKind == TokenKind.AddOperator);
- left = new BinaryImpl(left, tokenToBinaryOperator.get(operatorTokenKind), right,
- odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Double));
+ final EdmType resultType = getAddSubTypeAndCheckLeftAndRight(left, right,
+ operatorTokenKind == TokenKind.SubOperator);
+ left = new BinaryImpl(left, tokenToBinaryOperator.get(operatorTokenKind), right, resultType);
operatorTokenKind = ParserHelper.next(tokenizer, TokenKind.AddOperator, TokenKind.SubOperator);
}
return left;
@@ -328,10 +320,7 @@ public class ExpressionParser {
}
private Expression parseExprUnary() throws UriParserException, UriValidationException {
- final TokenKind operatorTokenKind = ParserHelper.next(tokenizer, TokenKind.MINUS, TokenKind.NotOperator,
- TokenKind.CastMethod);
-
- if(operatorTokenKind == TokenKind.MINUS) {
+ if (tokenizer.next(TokenKind.MinusOperator)) {
final Expression expression = parseExprPrimary();
checkType(expression,
EdmPrimitiveTypeKind.Int16, EdmPrimitiveTypeKind.Int32, EdmPrimitiveTypeKind.Int64,
@@ -339,37 +328,14 @@ public class ExpressionParser {
EdmPrimitiveTypeKind.Decimal, EdmPrimitiveTypeKind.Single, EdmPrimitiveTypeKind.Double,
EdmPrimitiveTypeKind.Duration);
return new UnaryImpl(UnaryOperatorKind.MINUS, expression, getType(expression));
- } else if(operatorTokenKind == TokenKind.NotOperator) {
+ } else if (tokenizer.next(TokenKind.NotOperator)) {
final Expression expression = parseExprPrimary();
checkType(expression, EdmPrimitiveTypeKind.Boolean);
return new UnaryImpl(UnaryOperatorKind.NOT, expression, getType(expression));
- } else if(operatorTokenKind == TokenKind.CastMethod) {
- return parseCastMethod(operatorTokenKind);
+ } else if (tokenizer.next(TokenKind.CastMethod)) {
+ return parseIsOfOrCastMethod(MethodKind.CAST);
} else {
- final Expression expression = parseExprPrimary();
- return expression;
- }
- }
-
- private Expression parseCastMethod(final TokenKind lastToken) throws UriParserException, UriValidationException {
- // The TokenKind 'CastMethod' consumes also the opening parenthesis
- if(lastToken == TokenKind.CastMethod) {
- final List<Expression> parameters = new ArrayList<Expression>();
- parameters.add(parseExpression());
-
- if(!(parameters.get(0) instanceof TypeLiteral)) {
- ParserHelper.requireNext(tokenizer, TokenKind.COMMA);
- parameters.add(parseExpression());
- if(!(parameters.get(1) instanceof TypeLiteral)) {
- throw new UriParserSemanticException("Type literal extected",
- UriParserSemanticException.MessageKeys.INCOMPATIBLE_TYPE_FILTER);
- }
- }
-
- ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
- return new MethodImpl(MethodKind.CAST, parameters);
- } else {
- throw new UriParserSyntaxException("Unexpected token.", UriParserSyntaxException.MessageKeys.SYNTAX);
+ return parseExprPrimary();
}
}
@@ -433,22 +399,20 @@ public class ExpressionParser {
private Expression parseMethod(final TokenKind nextMethod) throws UriParserException, UriValidationException {
// The method token text includes the opening parenthesis so that method calls can be recognized unambiguously.
// OData identifiers have to be considered after that.
-
final MethodKind methodKind = tokenToMethod.get(nextMethod);
return new MethodImpl(methodKind, parseMethodParameters(methodKind));
}
- private Expression parsePrimitive(TokenKind nextPrimitive) throws UriParserException {
+ private Expression parsePrimitive(final TokenKind primitiveTokenKind) throws UriParserException {
final String primitiveValueLiteral = tokenizer.getText();
- if (nextPrimitive == TokenKind.EnumValue) {
+ if (primitiveTokenKind == TokenKind.EnumValue) {
return createEnumExpression(primitiveValueLiteral);
} else {
- EdmPrimitiveTypeKind primitiveTypeKind = tokenToPrimitiveType.get(nextPrimitive);
-
- if(primitiveTypeKind == EdmPrimitiveTypeKind.Int64) {
+ EdmPrimitiveTypeKind primitiveTypeKind = tokenToPrimitiveType.get(primitiveTokenKind);
+ if (primitiveTypeKind == EdmPrimitiveTypeKind.Int64) {
primitiveTypeKind = determineIntegerType(primitiveValueLiteral);
}
-
+
final EdmPrimitiveType type = primitiveTypeKind == null ?
// Null handling
null :
@@ -472,12 +436,11 @@ public class ExpressionParser {
} else {
typeKind = EdmPrimitiveTypeKind.Int64;
}
- } catch (NumberFormatException e) {
- // This should never happen. Because the tokenizer has figured out that the literal is an integer
- throw new UriParserSyntaxException(intValueAsString + " is not an integer",
+ } catch (final NumberFormatException e) {
+ // This should never happen because the tokenizer has figured out that the literal is an integer.
+ throw new UriParserSyntaxException("'" + intValueAsString + "' is not an integer.", e,
UriParserSyntaxException.MessageKeys.SYNTAX);
}
-
return typeKind;
}
@@ -622,19 +585,19 @@ public class ExpressionParser {
if (filterType == null) {
filterType = edm.getComplexType(fullQualifiedName);
}
-
- if(filterType == null) {
- filterType = getEdmType(fullQualifiedName);
+
+ if (filterType == null) {
+ filterType = getPrimitiveType(fullQualifiedName);
}
-
- if(filterType == null) {
+
+ if (filterType == null) {
filterType = edm.getEnumType(fullQualifiedName);
}
-
- if(filterType == null) {
+
+ if (filterType == null) {
filterType = edm.getTypeDefinition(fullQualifiedName);
}
-
+
if (filterType != null) {
if (tokenizer.next(TokenKind.SLASH)) {
// Leading type cast
@@ -642,30 +605,29 @@ public class ExpressionParser {
startTypeFilter = filterType;
final TokenKind tokenKind = ParserHelper.next(tokenizer, TokenKind.QualifiedName, TokenKind.ODataIdentifier);
- parseMemberExpression(tokenKind, uriInfo, new UriResourceStartingTypeFilterImpl(filterType, false),
- false);
+ parseMemberExpression(tokenKind, uriInfo, new UriResourceStartingTypeFilterImpl(filterType, false), false);
} else {
// Type literal
return new TypeLiteralImpl(filterType);
}
} else {
- // Must be bound or unbound function.
+ // Must be bound or unbound function.
parseFunction(fullQualifiedName, uriInfo, referringType, true);
}
} else if (lastTokenKind == TokenKind.ODataIdentifier) {
parseFirstMemberODataIdentifier(uriInfo);
}
-
+
return new MemberImpl(uriInfo, startTypeFilter);
}
- private EdmType getEdmType(final FullQualifiedName fullQualifiedName) {
- if(!fullQualifiedName.getNamespace().equals(EdmPrimitiveType.EDM_NAMESPACE)) {
+ private EdmType getPrimitiveType(final FullQualifiedName fullQualifiedName) {
+ if (EdmPrimitiveType.EDM_NAMESPACE.equals(fullQualifiedName.getNamespace())) {
+ final EdmPrimitiveTypeKind primitiveTypeKind = EdmPrimitiveTypeKind.valueOf(fullQualifiedName.getName());
+ return primitiveTypeKind == null ? null : odata.createPrimitiveTypeInstance(primitiveTypeKind);
+ } else {
return null;
}
-
- final EdmPrimitiveTypeKind primitiveTypeKind = EdmPrimitiveTypeKind.valueOfFQN(fullQualifiedName);
- return primitiveTypeKind == null ? null : EdmPrimitiveTypeFactory.getInstance(primitiveTypeKind);
}
private void parseDollarRoot(UriInfoImpl uriInfo) throws UriParserException, UriValidationException {
@@ -694,7 +656,7 @@ public class ExpressionParser {
parseSingleNavigationExpr(uriInfo, resource);
}
- private void parseDollarIt(UriInfoImpl uriInfo, EdmType referringType)
+ private void parseDollarIt(UriInfoImpl uriInfo, final EdmType referringType)
throws UriParserException, UriValidationException {
UriResourceItImpl itResource = new UriResourceItImpl(referringType, false);
uriInfo.addResourcePart(itResource);
@@ -759,16 +721,14 @@ public class ExpressionParser {
if (edmEntityType != null) {
if (allowTypeFilter) {
setTypeFilter(lastResource, edmEntityType);
-
- if(tokenizer.next(TokenKind.SLASH)) {
- final TokenKind nextTokenKind = ParserHelper.next(tokenizer, TokenKind.QualifiedName,
- TokenKind.ODataIdentifier);
- if(nextTokenKind == TokenKind.ODataIdentifier) {
- parsePropertyPathExpr(uriInfo, lastResource);
- } else if(nextTokenKind == TokenKind.QualifiedName) {
+
+ if (tokenizer.next(TokenKind.SLASH)) {
+ if (tokenizer.next(TokenKind.QualifiedName)) {
parseBoundFunction(fullQualifiedName, uriInfo, lastResource);
+ } else if (tokenizer.next(TokenKind.ODataIdentifier)) {
+ parsePropertyPathExpr(uriInfo, lastResource);
} else {
- throw new UriParserSyntaxException("Extected OData Identifier or Full Qualified Name",
+ throw new UriParserSyntaxException("Expected OData Identifier or Full Qualified Name.",
UriParserSyntaxException.MessageKeys.SYNTAX);
}
}
@@ -814,7 +774,9 @@ public class ExpressionParser {
if (property == null) {
throw new UriParserSemanticException("Unknown property.",
- UriParserSemanticException.MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE, oDataIdentifier);
+ UriParserSemanticException.MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE,
+ lastType.getFullQualifiedName().getFullQualifiedNameAsString(),
+ oDataIdentifier);
}
if (property.getType() instanceof EdmComplexType) {
@@ -823,7 +785,9 @@ public class ExpressionParser {
uriInfo.addResourcePart(complexResource);
if (property.isCollection()) {
- parseCollectionPathExpr(uriInfo, complexResource);
+ if (tokenizer.next(TokenKind.SLASH)) {
+ parseCollectionPathExpr(uriInfo, complexResource);
+ }
} else {
parseComplexPathExpr(uriInfo, complexResource);
}
@@ -847,7 +811,9 @@ public class ExpressionParser {
uriInfo.addResourcePart(primitiveResource);
if (property.isCollection()) {
- parseCollectionPathExpr(uriInfo, primitiveResource);
+ if (tokenizer.next(TokenKind.SLASH)) {
+ parseCollectionPathExpr(uriInfo, primitiveResource);
+ }
} else {
parseSinglePathExpr(uriInfo, primitiveResource);
}
@@ -856,7 +822,6 @@ public class ExpressionParser {
private void parseSingleNavigationExpr(UriInfoImpl uriInfo, final UriResourcePartTyped lastResource)
throws UriParserException, UriValidationException {
- // TODO: Is that correct?
if (tokenizer.next(TokenKind.SLASH)) {
final TokenKind tokenKind = ParserHelper.next(tokenizer, TokenKind.QualifiedName, TokenKind.ODataIdentifier);
parseMemberExpression(tokenKind, uriInfo, lastResource, true);
@@ -865,8 +830,22 @@ public class ExpressionParser {
private void parseCollectionNavigationExpr(UriInfoImpl uriInfo, UriResourcePartTyped lastResource)
throws UriParserException, UriValidationException {
- // TODO: Is type cast missing?
- if (tokenizer.next(TokenKind.OPEN)) {
+ boolean hasSlash = false;
+ if (tokenizer.next(TokenKind.SLASH)) {
+ hasSlash = true;
+ if (tokenizer.next(TokenKind.QualifiedName)) {
+ final FullQualifiedName qualifiedName = new FullQualifiedName(tokenizer.getText());
+ final EdmEntityType edmEntityType = edm.getEntityType(qualifiedName);
+ if (edmEntityType == null) {
+ parseBoundFunction(qualifiedName, uriInfo, lastResource);
+ } else {
+ setTypeFilter(lastResource, edmEntityType);
+ }
+ hasSlash = false;
+ }
+ }
+
+ if (!hasSlash && tokenizer.next(TokenKind.OPEN)) {
if (lastResource instanceof UriResourceNavigation) {
((UriResourceNavigationPropertyImpl) lastResource).setKeyPredicates(
ParserHelper.parseNavigationKeyPredicate(tokenizer,
@@ -883,7 +862,10 @@ public class ExpressionParser {
}
parseSingleNavigationExpr(uriInfo, lastResource);
}
- parseCollectionPathExpr(uriInfo, lastResource);
+
+ if (hasSlash || tokenizer.next(TokenKind.SLASH)) {
+ parseCollectionPathExpr(uriInfo, lastResource);
+ }
}
private void parseSinglePathExpr(UriInfoImpl uriInfo, final UriResourcePartTyped lastResource)
@@ -932,25 +914,23 @@ public class ExpressionParser {
private void parseCollectionPathExpr(UriInfoImpl uriInfo, final UriResourcePartTyped lastResource)
throws UriParserException, UriValidationException {
-
- if (tokenizer.next(TokenKind.SLASH)) {
- if (tokenizer.next(TokenKind.COUNT)) {
- uriInfo.addResourcePart(new UriResourceCountImpl());
- } else if (tokenizer.next(TokenKind.ANY)) {
- uriInfo.addResourcePart(parseLambdaRest(TokenKind.ANY, lastResource));
- } else if (tokenizer.next(TokenKind.ALL)) {
- uriInfo.addResourcePart(parseLambdaRest(TokenKind.ALL, lastResource));
- } else if (tokenizer.next(TokenKind.QualifiedName)) {
- final FullQualifiedName fullQualifiedName = new FullQualifiedName(tokenizer.getText());
- parseBoundFunction(fullQualifiedName, uriInfo, lastResource);
- }
+ // The initial slash (see grammar) must have been checked and consumed by the caller.
+ if (tokenizer.next(TokenKind.COUNT)) {
+ uriInfo.addResourcePart(new UriResourceCountImpl());
+ } else if (tokenizer.next(TokenKind.ANY)) {
+ uriInfo.addResourcePart(parseLambdaRest(TokenKind.ANY, lastResource));
+ } else if (tokenizer.next(TokenKind.ALL)) {
+ uriInfo.addResourcePart(parseLambdaRest(TokenKind.ALL, lastResource));
+ } else if (tokenizer.next(TokenKind.QualifiedName)) {
+ final FullQualifiedName fullQualifiedName = new FullQualifiedName(tokenizer.getText());
+ parseBoundFunction(fullQualifiedName, uriInfo, lastResource);
}
}
private void parseFunction(final FullQualifiedName fullQualifiedName, UriInfoImpl uriInfo,
final EdmType lastType, final boolean lastIsCollection) throws UriParserException, UriValidationException {
- final List<UriParameter> parameters = ParserHelper.parseFunctionParameters(tokenizer, true);
+ final List<UriParameter> parameters = ParserHelper.parseFunctionParameters(tokenizer, edm, referringType, true);
final List<String> parameterNames = ParserHelper.getParameterNames(parameters);
final EdmFunction boundFunction = edm.getBoundFunction(fullQualifiedName,
lastType.getFullQualifiedName(), lastIsCollection, parameterNames);
@@ -966,18 +946,19 @@ public class ExpressionParser {
return;
}
- throw new UriParserSemanticException("No function found.",
+ throw new UriParserSemanticException("No function '" + fullQualifiedName + "' found.",
UriParserSemanticException.MessageKeys.FUNCTION_NOT_FOUND, fullQualifiedName.getFullQualifiedNameAsString());
}
private void parseBoundFunction(final FullQualifiedName fullQualifiedName, UriInfoImpl uriInfo,
final UriResourcePartTyped lastResource) throws UriParserException, UriValidationException {
- final List<UriParameter> parameters = ParserHelper.parseFunctionParameters(tokenizer, true);
+ final EdmType type = lastResource.getType();
+ final List<UriParameter> parameters = ParserHelper.parseFunctionParameters(tokenizer, edm, referringType, true);
final List<String> parameterNames = ParserHelper.getParameterNames(parameters);
final EdmFunction boundFunction = edm.getBoundFunction(fullQualifiedName,
- lastResource.getType().getFullQualifiedName(), lastResource.isCollection(), parameterNames);
+ type.getFullQualifiedName(), lastResource.isCollection(), parameterNames);
if (boundFunction == null) {
- throw new UriParserSemanticException("Bound function not found.",
+ throw new UriParserSemanticException("Bound function '" + fullQualifiedName + "' not found.",
UriParserSemanticException.MessageKeys.FUNCTION_NOT_FOUND, fullQualifiedName.getFullQualifiedNameAsString());
}
parseFunctionRest(uriInfo, boundFunction, parameters);
@@ -995,19 +976,23 @@ public class ExpressionParser {
if (function.isComposable()) {
if (edmType instanceof EdmEntityType ) {
if (isCollection) {
- parseCollectionNavigationExpr(uriInfo, functionResource);
+ parseCollectionNavigationExpr(uriInfo, functionResource);
} else {
parseSingleNavigationExpr(uriInfo, functionResource);
}
} else if (edmType instanceof EdmComplexType) {
if (isCollection) {
- parseCollectionPathExpr(uriInfo, functionResource);
+ if (tokenizer.next(TokenKind.SLASH)) {
+ parseCollectionPathExpr(uriInfo, functionResource);
+ }
} else {
parseComplexPathExpr(uriInfo, functionResource);
}
} else if (edmType instanceof EdmPrimitiveType) {
if (isCollection) {
- parseCollectionPathExpr(uriInfo, functionResource);
+ if (tokenizer.next(TokenKind.SLASH)) {
+ parseCollectionPathExpr(uriInfo, functionResource);
+ }
} else {
parseSinglePathExpr(uriInfo, functionResource);
}
@@ -1077,7 +1062,7 @@ public class ExpressionParser {
TokenKind.YearMethod);
}
- private EdmType getType(final Expression expression) throws UriParserException {
+ protected static EdmType getType(final Expression expression) throws UriParserException {
EdmType type;
if (expression instanceof Literal) {
type = ((Literal) expression).getType();
@@ -1108,13 +1093,12 @@ public class ExpressionParser {
return type;
}
- private boolean isType(final Expression expression, final EdmPrimitiveTypeKind... kinds) throws UriParserException {
- final EdmType expressionType = getType(expression);
- if (expressionType == null) {
+ private boolean isType(final EdmType type, final EdmPrimitiveTypeKind... kinds) throws UriParserException {
+ if (type == null) {
return true;
}
for (final EdmPrimitiveTypeKind kind : kinds) {
- if (expressionType.equals(odata.createPrimitiveTypeInstance(kind))) {
+ if (type.equals(odata.createPrimitiveTypeInstance(kind))) {
return true;
}
}
@@ -1122,12 +1106,13 @@ public class ExpressionParser {
}
private void checkType(final Expression expression, final EdmPrimitiveTypeKind... kinds) throws UriParserException {
- if (!isType(expression, kinds)) {
+ final EdmType type = getType(expression);
+ if (!isType(type, kinds)) {
throw new UriParserSemanticException("Incompatible type.",
UriParserSemanticException.MessageKeys.UNKNOWN_TYPE, // TODO: better message
- getType(expression) == null ?
+ type == null ?
"" :
- getType(expression).getFullQualifiedName().getFullQualifiedNameAsString());
+ type.getFullQualifiedName().getFullQualifiedNameAsString());
}
}
@@ -1137,21 +1122,21 @@ public class ExpressionParser {
if (leftType == null || rightType == null || leftType.equals(rightType)) {
return;
}
-
+
// Numeric promotion for Edm.Byte and Edm.SByte
- if((leftType instanceof EdmByte || leftType instanceof EdmSByte)
- && (rightType instanceof EdmByte || rightType instanceof EdmSByte)) {
+ if (isType(leftType, EdmPrimitiveTypeKind.Byte, EdmPrimitiveTypeKind.SByte)
+ && isType(rightType, EdmPrimitiveTypeKind.Byte, EdmPrimitiveTypeKind.SByte)) {
return;
}
-
+
if (leftType.getKind() != EdmTypeKind.PRIMITIVE
|| rightType.getKind() != EdmTypeKind.PRIMITIVE
|| !(((EdmPrimitiveType) leftType).isCompatible((EdmPrimitiveType) rightType)
- || ((EdmPrimitiveType) rightType).isCompatible((EdmPrimitiveType) leftType)))
- {
+ || ((EdmPrimitiveType) rightType).isCompatible((EdmPrimitiveType) leftType))) {
throw new UriParserSemanticException("Incompatible types.",
- UriParserSemanticException.MessageKeys.TYPES_NOT_COMPATIBLE, leftType.getFullQualifiedName().toString(),
- rightType.getFullQualifiedName().toString());
+ UriParserSemanticException.MessageKeys.TYPES_NOT_COMPATIBLE,
+ leftType.getFullQualifiedName().getFullQualifiedNameAsString(),
+ rightType.getFullQualifiedName().getFullQualifiedNameAsString());
}
}
@@ -1164,12 +1149,12 @@ public class ExpressionParser {
}
return type;
}
-
+
private boolean isEnumType(final Expression expression) throws UriParserException {
final EdmType expressionType = getType(expression);
return expressionType == null
|| expressionType.getKind() == EdmTypeKind.ENUM
- || isType(expression,
+ || isType(expressionType,
EdmPrimitiveTypeKind.Int16, EdmPrimitiveTypeKind.Int32, EdmPrimitiveTypeKind.Int64,
EdmPrimitiveTypeKind.Byte, EdmPrimitiveTypeKind.SByte);
}
@@ -1208,44 +1193,69 @@ public class ExpressionParser {
EdmPrimitiveTypeKind.Date, EdmPrimitiveTypeKind.TimeOfDay,
EdmPrimitiveTypeKind.DateTimeOffset, EdmPrimitiveTypeKind.Duration);
if (!(((EdmPrimitiveType) leftType).isCompatible((EdmPrimitiveType) rightType)
- || ((EdmPrimitiveType) rightType).isCompatible((EdmPrimitiveType) leftType))) {
+ || ((EdmPrimitiveType) rightType).isCompatible((EdmPrimitiveType) leftType))) {
throw new UriParserSemanticException("Incompatible types.",
- UriParserSemanticException.MessageKeys.UNKNOWN_TYPE, ""); // TODO: better message
+ UriParserSemanticException.MessageKeys.TYPES_NOT_COMPATIBLE,
+ leftType.getFullQualifiedName().getFullQualifiedNameAsString(),
+ rightType.getFullQualifiedName().getFullQualifiedNameAsString());
}
}
- private void checkAddSubTypes(final Expression left, final Expression right, final boolean isAdd)
+ private EdmType getAddSubTypeAndCheckLeftAndRight(final Expression left, final Expression right, final boolean isSub)
throws UriParserException {
final EdmType leftType = getType(left);
final EdmType rightType = getType(right);
- if (leftType == null || rightType == null
- || isType(left,
+ if (leftType == null || rightType == null) {
+ return null;
+ }
+ if (isType(leftType,
EdmPrimitiveTypeKind.Int16, EdmPrimitiveTypeKind.Int32, EdmPrimitiveTypeKind.Int64,
EdmPrimitiveTypeKind.Byte, EdmPrimitiveTypeKind.SByte,
EdmPrimitiveTypeKind.Decimal, EdmPrimitiveTypeKind.Single, EdmPrimitiveTypeKind.Double)
- && isType(right,
+ && isType(rightType,
EdmPrimitiveTypeKind.Int16, EdmPrimitiveTypeKind.Int32, EdmPrimitiveTypeKind.Int64,
EdmPrimitiveTypeKind.Byte, EdmPrimitiveTypeKind.SByte,
EdmPrimitiveTypeKind.Decimal, EdmPrimitiveTypeKind.Single, EdmPrimitiveTypeKind.Double)) {
- return;
+ // The result type must be able to handle the overflow,
+ // so we return always a wider type than the types of the operands.
+ if (isType(leftType, EdmPrimitiveTypeKind.Decimal, EdmPrimitiveTypeKind.Single, EdmPrimitiveTypeKind.Double)
+ || isType(rightType,
+ EdmPrimitiveTypeKind.Decimal, EdmPrimitiveTypeKind.Single, EdmPrimitiveTypeKind.Double)) {
+ return odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Double);
+ } else if (isType(leftType, EdmPrimitiveTypeKind.Int64) || isType(rightType, EdmPrimitiveTypeKind.Int64)) {
+ return odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Decimal);
+ } else if (isType(leftType, EdmPrimitiveTypeKind.Int32) || isType(rightType, EdmPrimitiveTypeKind.Int32)) {
+ return odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Int64);
+ } else if (isType(leftType, EdmPrimitiveTypeKind.Int16) || isType(rightType, EdmPrimitiveTypeKind.Int16)) {
+ return odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Int32);
+ } else {
+ return odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Int16);
+ }
}
- if (isType(left, EdmPrimitiveTypeKind.DateTimeOffset)
- && (isType(right, EdmPrimitiveTypeKind.Duration)
- || isType(right, EdmPrimitiveTypeKind.DateTimeOffset) && !isAdd)) {
- return;
+ if ((isType(leftType, EdmPrimitiveTypeKind.DateTimeOffset)
+ || isType(leftType, EdmPrimitiveTypeKind.Duration))
+ && isType(rightType, EdmPrimitiveTypeKind.Duration)) {
+ return leftType;
}
- if (isType(left, EdmPrimitiveTypeKind.Duration) && isType(right, EdmPrimitiveTypeKind.Duration)
- || isType(left, EdmPrimitiveTypeKind.Date)
- && (isType(right, EdmPrimitiveTypeKind.Duration) || isType(right, EdmPrimitiveTypeKind.Date) && !isAdd)) {
- return;
+ if (isType(leftType, EdmPrimitiveTypeKind.Date) && isType(rightType, EdmPrimitiveTypeKind.Duration)) {
+ return odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.DateTimeOffset);
+ }
+ if (isSub
+ && (isType(leftType, EdmPrimitiveTypeKind.DateTimeOffset)
+ && isType(rightType, EdmPrimitiveTypeKind.DateTimeOffset)
+ || isType(leftType, EdmPrimitiveTypeKind.Date)
+ && isType(rightType, EdmPrimitiveTypeKind.Date))) {
+ return odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Duration);
}
throw new UriParserSemanticException("Incompatible types.",
- UriParserSemanticException.MessageKeys.UNKNOWN_TYPE, ""); // TODO: better message
+ UriParserSemanticException.MessageKeys.TYPES_NOT_COMPATIBLE,
+ leftType.getFullQualifiedName().getFullQualifiedNameAsString(),
+ rightType.getFullQualifiedName().getFullQualifiedNameAsString());
}
private void checkStructuredTypeFilter(final EdmType type, final EdmType filterType)
throws UriParserException {
- if (!(filterType instanceof EdmStructuredType && ((EdmStructuredType)filterType).compatibleTo(type))) {
+ if (!(filterType instanceof EdmStructuredType && ((EdmStructuredType) filterType).compatibleTo(type))) {
throw new UriParserSemanticException("Incompatible type filter.",
UriParserSemanticException.MessageKeys.INCOMPATIBLE_TYPE_FILTER,
filterType.getFullQualifiedName().getFullQualifiedNameAsString());
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/FilterParser.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/FilterParser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/FilterParser.java
index e2767a1..dd73009 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/FilterParser.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/FilterParser.java
@@ -21,6 +21,7 @@ package org.apache.olingo.server.core.uri.parser;
import java.util.Collection;
import org.apache.olingo.commons.api.edm.Edm;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
import org.apache.olingo.commons.api.edm.EdmType;
import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.uri.queryoption.FilterOption;
@@ -43,7 +44,13 @@ public class FilterParser {
throws UriParserException, UriValidationException {
final Expression filterExpression = new ExpressionParser(edm, odata)
.parse(tokenizer, referencedType, crossjoinEntitySetNames);
- // TODO: Check that the expression is boolean.
- return new FilterOptionImpl().setExpression(filterExpression);
+ final EdmType type = ExpressionParser.getType(filterExpression);
+ if (type == null || type.equals(odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Boolean))) {
+ return new FilterOptionImpl().setExpression(filterExpression);
+ } else {
+ throw new UriParserSemanticException("Filter expressions must be boolean.",
+ UriParserSemanticException.MessageKeys.TYPES_NOT_COMPATIBLE,
+ "Edm.Boolean", type.getFullQualifiedName().getFullQualifiedNameAsString());
+ }
}
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
index 47efda5..3125fa6 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
@@ -18,18 +18,11 @@
*/
package org.apache.olingo.server.core.uri.parser;
+import java.util.ArrayDeque;
+import java.util.Deque;
import java.util.List;
-import org.antlr.v4.runtime.ANTLRInputStream;
-import org.antlr.v4.runtime.BailErrorStrategy;
-import org.antlr.v4.runtime.CommonTokenStream;
-import org.antlr.v4.runtime.Lexer;
-import org.antlr.v4.runtime.ParserRuleContext;
-import org.antlr.v4.runtime.RecognitionException;
-import org.antlr.v4.runtime.atn.PredictionMode;
-import org.antlr.v4.runtime.misc.ParseCancellationException;
import org.apache.olingo.commons.api.edm.Edm;
-import org.apache.olingo.commons.api.edm.EdmEntityContainer;
import org.apache.olingo.commons.api.edm.EdmEntitySet;
import org.apache.olingo.commons.api.edm.EdmStructuredType;
import org.apache.olingo.commons.api.edm.EdmType;
@@ -52,14 +45,10 @@ import org.apache.olingo.server.api.uri.queryoption.SystemQueryOptionKind;
import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
import org.apache.olingo.server.core.uri.UriInfoImpl;
import org.apache.olingo.server.core.uri.UriResourceStartingTypeFilterImpl;
-import org.apache.olingo.server.core.uri.antlr.UriLexer;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandItemsEOFContext;
import org.apache.olingo.server.core.uri.parser.UriTokenizer.TokenKind;
import org.apache.olingo.server.core.uri.parser.search.SearchParser;
import org.apache.olingo.server.core.uri.queryoption.AliasQueryOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.CountOptionImpl;
-import org.apache.olingo.server.core.uri.queryoption.ExpandOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.FormatOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.IdOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.SkipOptionImpl;
@@ -77,8 +66,6 @@ public class Parser {
private final Edm edm;
private final OData odata;
- private enum ParserEntryRules { ExpandItems }
-
public Parser(final Edm edm, final OData odata) {
this.edm = edm;
this.odata = odata;
@@ -87,8 +74,9 @@ public class Parser {
public UriInfo parseUri(final String path, final String query, final String fragment)
throws UriParserException, UriValidationException {
- UriContext context = new UriContext();
- UriParseTreeVisitor uriParseTreeVisitor = new UriParseTreeVisitor(edm, context);
+ UriInfoImpl contextUriInfo = new UriInfoImpl();
+ Deque<EdmType> contextTypes = new ArrayDeque<EdmType>();
+ boolean contextIsCollection = false;
final List<String> pathSegmentsDecoded = UriDecoder.splitAndDecodePath(path);
final int numberOfSegments = pathSegmentsDecoded.size();
@@ -98,49 +86,46 @@ public class Parser {
if (firstSegment.isEmpty()) {
ensureLastSegment(firstSegment, 0, numberOfSegments);
- context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.service);
+ contextUriInfo.setKind(UriInfoKind.service);
} else if (firstSegment.equals("$batch")) {
ensureLastSegment(firstSegment, 1, numberOfSegments);
- context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.batch);
+ contextUriInfo.setKind(UriInfoKind.batch);
} else if (firstSegment.equals("$metadata")) {
ensureLastSegment(firstSegment, 1, numberOfSegments);
- context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.metadata);
- context.contextUriInfo.setFragment(fragment);
+ contextUriInfo.setKind(UriInfoKind.metadata);
+ contextUriInfo.setFragment(fragment);
} else if (firstSegment.equals("$all")) {
ensureLastSegment(firstSegment, 1, numberOfSegments);
- context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.all);
+ contextUriInfo.setKind(UriInfoKind.all);
// This loads nearly the whole schema, but sooner or later '$all' needs all entity sets anyway.
for (final EdmEntitySet entitySet : edm.getEntityContainer().getEntitySets()) {
- context.contextTypes.push(entitySet.getEntityType());
+ contextTypes.push(entitySet.getEntityType());
}
- context.isCollection = true;
+ contextIsCollection = true;
} else if (firstSegment.equals("$entity")) {
if (numberOfSegments > 1) {
final String typeCastSegment = pathSegmentsDecoded.get(1);
ensureLastSegment(typeCastSegment, 2, numberOfSegments);
- context.contextUriInfo = new ResourcePathParser(edm).parseDollarEntityTypeCast(typeCastSegment);
- context.contextTypes.push(context.contextUriInfo.getEntityTypeCast());
+ contextUriInfo = new ResourcePathParser(edm).parseDollarEntityTypeCast(typeCastSegment);
+ contextTypes.push(contextUriInfo.getEntityTypeCast());
} else {
- context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.entityId);
+ contextUriInfo.setKind(UriInfoKind.entityId);
// The type of the entity is not known until the $id query option has been parsed.
+ // TODO: Set the type (needed for the evaluation of system query options).
}
- context.isCollection = false;
+ contextIsCollection = false;
} else if (firstSegment.startsWith("$crossjoin")) {
ensureLastSegment(firstSegment, 1, numberOfSegments);
- context.contextUriInfo = new ResourcePathParser(edm).parseCrossjoinSegment(firstSegment);
- final EdmEntityContainer container = edm.getEntityContainer();
- for (final String name : context.contextUriInfo.getEntitySetNames()) {
- context.contextTypes.push(container.getEntitySet(name).getEntityType());
- }
- context.isCollection = true;
+ contextUriInfo = new ResourcePathParser(edm).parseCrossjoinSegment(firstSegment);
+ contextIsCollection = true;
} else {
- context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.resource);
+ contextUriInfo.setKind(UriInfoKind.resource);
final ResourcePathParser resourcePathParser = new ResourcePathParser(edm);
int count = 0;
UriResource lastSegment = null;
@@ -168,7 +153,7 @@ public class Parser {
} else {
lastSegment = segment;
}
- context.contextUriInfo.addResourcePart(segment);
+ contextUriInfo.addResourcePart(segment);
}
}
@@ -176,9 +161,9 @@ public class Parser {
final UriResourcePartTyped typed = (UriResourcePartTyped) lastSegment;
final EdmType type = ParserHelper.getTypeInformation(typed);
if (type != null) { // could be null for, e.g., actions without return type
- context.contextTypes.push(type);
+ contextTypes.push(type);
}
- context.isCollection = typed.isCollection();
+ contextIsCollection = typed.isCollection();
}
}
@@ -191,9 +176,10 @@ public class Parser {
SystemQueryOption systemOption = null;
if (optionName.equals(SystemQueryOptionKind.FILTER.toString())) {
UriTokenizer filterTokenizer = new UriTokenizer(optionValue);
- // The Referring type could also be a primitive type not only a structured type
- systemOption = new FilterParser(edm, odata).parse(filterTokenizer, context.contextTypes.peek(),
- context.contextUriInfo.getEntitySetNames());
+ // The referring type could be a primitive type or a structured type.
+ systemOption = new FilterParser(edm, odata).parse(filterTokenizer,
+ contextTypes.peek(),
+ contextUriInfo.getEntitySetNames());
checkOptionEOF(filterTokenizer, optionName, optionValue);
} else if (optionName.equals(SystemQueryOptionKind.FORMAT.toString())) {
@@ -211,19 +197,26 @@ public class Parser {
systemOption = formatOption;
} else if (optionName.equals(SystemQueryOptionKind.EXPAND.toString())) {
- try {
- ExpandItemsEOFContext ctxExpandItems =
- (ExpandItemsEOFContext) parseRule(optionValue, ParserEntryRules.ExpandItems);
- systemOption = (ExpandOptionImpl) uriParseTreeVisitor.visitExpandItemsEOF(ctxExpandItems);
- } catch (final ParseCancellationException e) {
- throw e.getCause() instanceof UriParserException ?
- (UriParserException) e.getCause() :
- new UriParserSyntaxException("Syntax error", e, UriParserSyntaxException.MessageKeys.SYNTAX);
+ if (contextTypes.peek() instanceof EdmStructuredType
+ || !contextUriInfo.getEntitySetNames().isEmpty()
+ || contextUriInfo.getKind() == UriInfoKind.entityId) { // TODO: Remove once the type has been set above.
+ UriTokenizer expandTokenizer = new UriTokenizer(optionValue);
+ systemOption = new ExpandParser(edm, odata).parse(expandTokenizer,
+ contextTypes.peek() instanceof EdmStructuredType ? (EdmStructuredType) contextTypes.peek() : null);
+ checkOptionEOF(expandTokenizer, optionName, optionValue);
+ } else {
+ throw new UriValidationException("Expand is only allowed on structured types!",
+ UriValidationException.MessageKeys.SYSTEM_QUERY_OPTION_NOT_ALLOWED, optionName);
}
} else if (optionName.equals(SystemQueryOptionKind.ID.toString())) {
IdOptionImpl idOption = new IdOptionImpl();
idOption.setText(optionValue);
+ if (optionValue == null || optionValue.isEmpty()) {
+ throw new UriParserSyntaxException("Illegal value of $id option!",
+ UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION,
+ optionName, optionValue);
+ }
idOption.setValue(optionValue);
systemOption = idOption;
@@ -234,10 +227,8 @@ public class Parser {
} else if (optionName.equals(SystemQueryOptionKind.ORDERBY.toString())) {
UriTokenizer orderByTokenizer = new UriTokenizer(optionValue);
systemOption = new OrderByParser(edm, odata).parse(orderByTokenizer,
- context.contextTypes.peek() instanceof EdmStructuredType ?
- (EdmStructuredType) context.contextTypes.peek() :
- null,
- context.contextUriInfo.getEntitySetNames());
+ contextTypes.peek() instanceof EdmStructuredType ? (EdmStructuredType) contextTypes.peek() : null,
+ contextUriInfo.getEntitySetNames());
checkOptionEOF(orderByTokenizer, optionName, optionValue);
} else if (optionName.equals(SystemQueryOptionKind.SEARCH.toString())) {
@@ -246,40 +237,31 @@ public class Parser {
} else if (optionName.equals(SystemQueryOptionKind.SELECT.toString())) {
UriTokenizer selectTokenizer = new UriTokenizer(optionValue);
systemOption = new SelectParser(edm).parse(selectTokenizer,
- context.contextTypes.peek() instanceof EdmStructuredType ?
- (EdmStructuredType) context.contextTypes.peek() :
- null,
- context.isCollection);
+ contextTypes.peek() instanceof EdmStructuredType ? (EdmStructuredType) contextTypes.peek() : null,
+ contextIsCollection);
checkOptionEOF(selectTokenizer, optionName, optionValue);
} else if (optionName.equals(SystemQueryOptionKind.SKIP.toString())) {
SkipOptionImpl skipOption = new SkipOptionImpl();
skipOption.setText(optionValue);
- try {
- skipOption.setValue(Integer.parseInt(optionValue));
- } catch (final NumberFormatException e) {
- throw new UriParserSyntaxException("Illegal value of $skip option!", e,
- UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION,
- optionName, optionValue);
- }
+ skipOption.setValue(ParserHelper.parseNonNegativeInteger(optionName, optionValue, true));
systemOption = skipOption;
} else if (optionName.equals(SystemQueryOptionKind.SKIPTOKEN.toString())) {
SkipTokenOptionImpl skipTokenOption = new SkipTokenOptionImpl();
skipTokenOption.setText(optionValue);
+ if (optionValue == null || optionValue.isEmpty()) {
+ throw new UriParserSyntaxException("Illegal value of $skiptoken option!",
+ UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION,
+ optionName, optionValue);
+ }
skipTokenOption.setValue(optionValue);
systemOption = skipTokenOption;
} else if (optionName.equals(SystemQueryOptionKind.TOP.toString())) {
TopOptionImpl topOption = new TopOptionImpl();
topOption.setText(optionValue);
- try {
- topOption.setValue(Integer.parseInt(optionValue));
- } catch (final NumberFormatException e) {
- throw new UriParserSyntaxException("Illegal value of $top option!", e,
- UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION,
- optionName, optionValue);
- }
+ topOption.setValue(ParserHelper.parseNonNegativeInteger(optionName, optionValue, true));
systemOption = topOption;
} else if (optionName.equals(SystemQueryOptionKind.COUNT.toString())) {
@@ -299,14 +281,14 @@ public class Parser {
UriParserSyntaxException.MessageKeys.UNKNOWN_SYSTEM_QUERY_OPTION, optionName);
}
try {
- context.contextUriInfo.setSystemQueryOption(systemOption);
+ contextUriInfo.setSystemQueryOption(systemOption);
} catch (final ODataRuntimeException e) {
throw new UriParserSyntaxException("Double system query option!", e,
UriParserSyntaxException.MessageKeys.DOUBLE_SYSTEM_QUERY_OPTION, optionName);
}
} else if (optionName.startsWith(AT)) {
- if (context.contextUriInfo.getAlias(optionName) == null) {
+ if (contextUriInfo.getAlias(optionName) == null) {
// TODO: Create a proper alias-value parser that can parse also common expressions.
Expression expression = null;
UriTokenizer aliasTokenizer = new UriTokenizer(optionValue);
@@ -318,13 +300,13 @@ public class Parser {
} else {
UriTokenizer aliasValueTokenizer = new UriTokenizer(optionValue);
expression = new ExpressionParser(edm, odata).parse(aliasValueTokenizer, null,
- context.contextUriInfo.getEntitySetNames());
+ contextUriInfo.getEntitySetNames());
if (!aliasValueTokenizer.next(TokenKind.EOF)) {
throw new UriParserSyntaxException("Illegal value for alias '" + optionName + "'.",
UriParserSyntaxException.MessageKeys.SYNTAX);
}
}
- context.contextUriInfo.addAlias((AliasQueryOption) new AliasQueryOptionImpl()
+ contextUriInfo.addAlias((AliasQueryOption) new AliasQueryOptionImpl()
.setAliasValue(expression)
.setName(optionName)
.setText(NULL.equals(optionValue) ? null : optionValue));
@@ -334,11 +316,11 @@ public class Parser {
}
} else {
- context.contextUriInfo.addCustomQueryOption((CustomQueryOption) option);
+ contextUriInfo.addCustomQueryOption((CustomQueryOption) option);
}
}
- return context.contextUriInfo;
+ return contextUriInfo;
}
private void ensureLastSegment(final String segment, final int pos, final int size)
@@ -362,102 +344,4 @@ public class Parser {
optionName, optionValue);
}
}
-
- private ParserRuleContext parseRule(final String input, final ParserEntryRules entryPoint)
- throws UriParserSyntaxException {
- UriParserParser parser = null;
- UriLexer lexer = null;
- ParserRuleContext ret = null;
-
- // Use 2 stage approach to improve performance
- // see https://github.com/antlr/antlr4/issues/192
-
- // stage = 1
- try {
-
- // create parser
- lexer = new UriLexer(new ANTLRInputStream(input));
- parser = new UriParserParser(new CommonTokenStream(lexer));
-
- // Set error strategy
- addStage1ErrorStrategy(parser);
-
- // Set error collector
- addStage1ErrorListener(parser);
-
- // user the faster LL parsing
- parser.getInterpreter().setPredictionMode(PredictionMode.SLL);
-
- // parse
- switch (entryPoint) {
- case ExpandItems:
- lexer.mode(Lexer.DEFAULT_MODE);
- ret = parser.expandItemsEOF();
- break;
- default:
- break;
-
- }
-
- } catch (ParseCancellationException hardException) {
- // stage = 2
- try {
-
- // create parser
- lexer = new UriLexer(new ANTLRInputStream(input));
- parser = new UriParserParser(new CommonTokenStream(lexer));
-
- // Set error strategy
- addStage2ErrorStrategy(parser);
-
- // Set error collector
- addStage2ErrorListener(parser);
-
- // Use the slower SLL parsing
- parser.getInterpreter().setPredictionMode(PredictionMode.LL);
-
- // parse
- switch (entryPoint) {
- case ExpandItems:
- lexer.mode(Lexer.DEFAULT_MODE);
- ret = parser.expandItemsEOF();
- break;
- default:
- break;
- }
-
- } catch (final RecognitionException weakException) {
- throw new UriParserSyntaxException("Error in syntax", weakException,
- UriParserSyntaxException.MessageKeys.SYNTAX);
-
- // exceptionOnStage = 2;
- }
- } catch (final RecognitionException hardException) {
- throw new UriParserSyntaxException("Error in syntax", hardException,
- UriParserSyntaxException.MessageKeys.SYNTAX);
- }
-
- return ret;
- }
-
- protected void addStage1ErrorStrategy(final UriParserParser parser) {
- // Throw exception at first syntax error
- parser.setErrorHandler(new BailErrorStrategy());
-
- }
-
- protected void addStage2ErrorStrategy(final UriParserParser parser) {
- // Throw exception at first syntax error
- parser.setErrorHandler(new BailErrorStrategy());
- }
-
- protected void addStage1ErrorListener(final UriParserParser parser) {
- // No error logging to System.out or System.err, only exceptions used (depending on ErrorStrategy)
- parser.removeErrorListeners();
- }
-
- protected void addStage2ErrorListener(final UriParserParser parser) {
- // No error logging to System.out or System.err, only exceptions used (depending on ErrorStrategy)
- parser.removeErrorListeners();
- }
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java
index 65ee461..7f4abf7 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java
@@ -23,6 +23,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import org.apache.olingo.commons.api.edm.Edm;
import org.apache.olingo.commons.api.edm.EdmEntityType;
import org.apache.olingo.commons.api.edm.EdmKeyPropertyRef;
import org.apache.olingo.commons.api.edm.EdmNavigationProperty;
@@ -36,6 +37,8 @@ import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.uri.UriParameter;
import org.apache.olingo.server.api.uri.UriResourcePartTyped;
+import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
+import org.apache.olingo.server.api.uri.queryoption.expression.Literal;
import org.apache.olingo.server.core.ODataImpl;
import org.apache.olingo.server.core.uri.UriParameterImpl;
import org.apache.olingo.server.core.uri.UriResourceTypedImpl;
@@ -88,8 +91,9 @@ public class ParserHelper {
TokenKind.EnumValue);
}
- protected static List<UriParameter> parseFunctionParameters(UriTokenizer tokenizer, final boolean withComplex)
- throws UriParserException {
+ protected static List<UriParameter> parseFunctionParameters(UriTokenizer tokenizer,
+ final Edm edm, final EdmType referringType, final boolean withComplex)
+ throws UriParserException, UriValidationException {
List<UriParameter> parameters = new ArrayList<UriParameter>();
ParserHelper.requireNext(tokenizer, TokenKind.OPEN);
if (tokenizer.next(TokenKind.CLOSE)) {
@@ -115,6 +119,13 @@ public class ParserHelper {
throw new UriParserSemanticException("A JSON array or object is not allowed as parameter value.",
UriParserSemanticException.MessageKeys.COMPLEX_PARAMETER_IN_RESOURCE_PATH, tokenizer.getText());
}
+ } else if (withComplex) {
+ final Expression expression = new ExpressionParser(edm, odata).parse(tokenizer, referringType, null);
+ parameters.add(new UriParameterImpl().setName(name)
+ .setText(expression instanceof Literal ?
+ "null".equals(((Literal) expression).getText()) ? null : ((Literal) expression).getText() :
+ null)
+ .setExpression(expression instanceof Literal ? null : expression));
} else if (nextPrimitiveValue(tokenizer) == null) {
throw new UriParserSemanticException("Wrong parameter value.",
UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, "");
@@ -387,4 +398,23 @@ public class ParserHelper {
return type;
}
+
+ protected static int parseNonNegativeInteger(final String optionName, final String optionValue,
+ final boolean zeroAllowed) throws UriParserException {
+ int value;
+ try {
+ value = Integer.parseInt(optionValue);
+ } catch (final NumberFormatException e) {
+ throw new UriParserSyntaxException("Illegal value of '" + optionName + "' option!", e,
+ UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION,
+ optionName, optionValue);
+ }
+ if (value > 0 || value == 0 && zeroAllowed) {
+ return value;
+ } else {
+ throw new UriParserSyntaxException("Illegal value of '" + optionName + "' option!",
+ UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION,
+ optionName, optionValue);
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ResourcePathParser.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ResourcePathParser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ResourcePathParser.java
index 1cd4d7a..87cb91a 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ResourcePathParser.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ResourcePathParser.java
@@ -261,30 +261,33 @@ public class ResourcePathParser {
throws UriParserException, UriValidationException {
final FullQualifiedName name = new FullQualifiedName(tokenizer.getText());
requireTyped(previous, name.getFullQualifiedNameAsString());
- final UriResourcePartTyped previousTyped = (UriResourcePartTyped) previous;
- final EdmType previousTypeFilter = getPreviousTypeFilter(previousTyped);
- final EdmType previousType = previousTypeFilter == null ? previousTyped.getType() : previousTypeFilter;
- final EdmAction boundAction = edm.getBoundAction(name,
- previousType.getFullQualifiedName(),
- previousTyped.isCollection());
- if (boundAction != null) {
- ParserHelper.requireTokenEnd(tokenizer);
- return new UriResourceActionImpl(boundAction);
- }
- EdmStructuredType type = edm.getEntityType(name);
- if (type == null) {
- type = edm.getComplexType(name);
- }
- if (type != null) {
- return typeCast(name, type, previousTyped);
- }
- if (tokenizer.next(TokenKind.EOF)) {
- throw new UriParserSemanticException("Type '" + name.getFullQualifiedNameAsString() + "' not found.",
- UriParserSemanticException.MessageKeys.UNKNOWN_TYPE, name.getFullQualifiedNameAsString());
- }
- return functionCall(null, name,
- previousType.getFullQualifiedName(),
- previousTyped.isCollection());
+ final UriResourcePartTyped previousTyped = (UriResourcePartTyped) previous;
+ final EdmType previousTypeFilter = getPreviousTypeFilter(previousTyped);
+ final EdmType previousType = previousTypeFilter == null ? previousTyped.getType() : previousTypeFilter;
+
+ // We check for bound actions first because they cannot be followed by anything.
+ final EdmAction boundAction =
+ edm.getBoundAction(name, previousType.getFullQualifiedName(), previousTyped.isCollection());
+ if (boundAction != null) {
+ ParserHelper.requireTokenEnd(tokenizer);
+ return new UriResourceActionImpl(boundAction);
+ }
+
+ // Type casts can be syntactically indistinguishable from bound function calls in the case of additional keys.
+ // But normally they are shorter, so they come next.
+ final EdmStructuredType type = previousTyped.getType() instanceof EdmEntityType ?
+ edm.getEntityType(name) :
+ edm.getComplexType(name);
+ if (type != null) {
+ return typeCast(name, type, previousTyped);
+ }
+ if (tokenizer.next(TokenKind.EOF)) {
+ throw new UriParserSemanticException("Type '" + name.getFullQualifiedNameAsString() + "' not found.",
+ UriParserSemanticException.MessageKeys.UNKNOWN_TYPE, name.getFullQualifiedNameAsString());
+ }
+
+ // Now a bound function call is the only remaining option.
+ return functionCall(null, name, previousType.getFullQualifiedName(), previousTyped.isCollection());
}
private void requireTyped(final UriResource previous, final String forWhat) throws UriParserException {
@@ -317,8 +320,13 @@ public class ResourcePathParser {
((UriResourceWithKeysImpl) previousTyped).setEntryTypeFilter(type);
}
if (tokenizer.next(TokenKind.OPEN)) {
- ((UriResourceWithKeysImpl) previousTyped).setKeyPredicates(
- ParserHelper.parseKeyPredicate(tokenizer, (EdmEntityType) type, null));
+ final List<UriParameter> keys = ParserHelper.parseKeyPredicate(tokenizer, (EdmEntityType) type, null);
+ if (previousTyped.isCollection()) {
+ ((UriResourceWithKeysImpl) previousTyped).setKeyPredicates(keys);
+ } else {
+ throw new UriParserSemanticException("Key not allowed here.",
+ UriParserSemanticException.MessageKeys.KEY_NOT_ALLOWED);
+ }
}
} else {
previousTypeFilter = ((UriResourceTypedImpl) previousTyped).getTypeFilter();
@@ -351,7 +359,7 @@ public class ResourcePathParser {
private UriResource functionCall(final EdmFunctionImport edmFunctionImport,
final FullQualifiedName boundFunctionName, final FullQualifiedName bindingParameterTypeName,
final boolean isBindingParameterCollection) throws UriParserException, UriValidationException {
- final List<UriParameter> parameters = ParserHelper.parseFunctionParameters(tokenizer, false);
+ final List<UriParameter> parameters = ParserHelper.parseFunctionParameters(tokenizer, edm, null, false);
final List<String> names = ParserHelper.getParameterNames(parameters);
EdmFunction function = null;
if (edmFunctionImport != null) {
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/SearchParser.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/SearchParser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/SearchParser.java
new file mode 100644
index 0000000..a072327
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/SearchParser.java
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.server.core.uri.parser;
+
+import org.apache.olingo.server.api.uri.queryoption.SearchOption;
+import org.apache.olingo.server.api.uri.queryoption.search.SearchBinaryOperatorKind;
+import org.apache.olingo.server.api.uri.queryoption.search.SearchExpression;
+import org.apache.olingo.server.api.uri.queryoption.search.SearchTerm;
+import org.apache.olingo.server.core.uri.parser.UriTokenizer.TokenKind;
+import org.apache.olingo.server.core.uri.parser.search.SearchBinaryImpl;
+import org.apache.olingo.server.core.uri.parser.search.SearchParserException;
+import org.apache.olingo.server.core.uri.parser.search.SearchTermImpl;
+import org.apache.olingo.server.core.uri.parser.search.SearchUnaryImpl;
+import org.apache.olingo.server.core.uri.queryoption.SearchOptionImpl;
+
+/**
+ * Parses search expressions according to the following (rewritten) grammar:
+ * <pre>
+ * SearchExpr ::= ExprOR
+ * ExprOR ::= ExprAnd ('OR' ExprAnd)*
+ * ExprAnd ::= Term ('AND'? Term)*
+ * Term ::= ('NOT'? (Word | Phrase)) | ('(' SearchExpr ')')
+ * </pre>
+ */
+public class SearchParser {
+
+ public SearchOption parse(UriTokenizer tokenizer) throws SearchParserException {
+ SearchOptionImpl searchOption = new SearchOptionImpl();
+ searchOption.setSearchExpression(processExprOr(tokenizer));
+ return searchOption;
+ }
+
+ private SearchExpression processExprOr(UriTokenizer tokenizer) throws SearchParserException {
+ SearchExpression left = processExprAnd(tokenizer);
+
+ while (tokenizer.next(TokenKind.OrOperatorSearch)) {
+ final SearchExpression right = processExprAnd(tokenizer);
+ left = new SearchBinaryImpl(left, SearchBinaryOperatorKind.OR, right);
+ }
+
+ return left;
+ }
+
+ private SearchExpression processExprAnd(UriTokenizer tokenizer) throws SearchParserException {
+ SearchExpression left = processTerm(tokenizer);
+
+ while (tokenizer.next(TokenKind.AndOperatorSearch)) { // Could be whitespace or whitespace-surrounded 'AND'.
+ final SearchExpression right = processTerm(tokenizer);
+ left = new SearchBinaryImpl(left, SearchBinaryOperatorKind.AND, right);
+ }
+
+ return left;
+ }
+
+ private SearchExpression processTerm(UriTokenizer tokenizer) throws SearchParserException {
+ if (tokenizer.next(TokenKind.OPEN)) {
+ final SearchExpression expr = processExprOr(tokenizer);
+ if (!tokenizer.next(TokenKind.CLOSE)) {
+ throw new SearchParserException("Missing close parenthesis after open parenthesis.",
+ SearchParserException.MessageKeys.MISSING_CLOSE);
+ }
+ return expr;
+ } else if (tokenizer.next(TokenKind.NotOperatorSearch)) {
+ return processNot(tokenizer);
+ } else if (tokenizer.next(TokenKind.Word)) {
+ return new SearchTermImpl(tokenizer.getText());
+ } else if (tokenizer.next(TokenKind.Phrase)) {
+ return processPhrase(tokenizer);
+ } else {
+ throw new SearchParserException("Expected PHRASE or WORD not found.",
+ SearchParserException.MessageKeys.EXPECTED_DIFFERENT_TOKEN, "PHRASE, WORD", "");
+ }
+ }
+
+ private SearchExpression processNot(UriTokenizer tokenizer) throws SearchParserException {
+ if (tokenizer.next(TokenKind.Word)) {
+ return new SearchUnaryImpl(new SearchTermImpl(tokenizer.getText()));
+ } else if (tokenizer.next(TokenKind.Phrase)) {
+ return new SearchUnaryImpl(processPhrase(tokenizer));
+ } else {
+ throw new SearchParserException("NOT must be followed by a term.",
+ SearchParserException.MessageKeys.INVALID_NOT_OPERAND, "");
+ }
+ }
+
+ private SearchTerm processPhrase(UriTokenizer tokenizer) {
+ final String literal = tokenizer.getText();
+ return new SearchTermImpl(literal.substring(1, literal.length() - 1)
+ .replace("\\\"", "\"")
+ .replace("\\\\", "\\"));
+ }
+}
[5/6] olingo-odata4 git commit: [OLINGO-834] $expand parser in Java +
clean-up
Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriContext.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriContext.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriContext.java
deleted file mode 100644
index 36a0887..0000000
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriContext.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.olingo.server.core.uri.parser;
-
-import java.util.ArrayDeque;
-import java.util.Deque;
-
-import org.apache.olingo.commons.api.edm.EdmType;
-import org.apache.olingo.server.core.uri.UriInfoImpl;
-import org.apache.olingo.server.core.uri.queryoption.ExpandItemImpl;
-import org.apache.olingo.server.core.uri.queryoption.SelectItemImpl;
-
-/**
- * UriContext object used for holding information for URI parsing.
- *
- */
-public class UriContext {
-
- public static class LambdaVariable {
- public String name;
- public EdmType type;
- }
-
- /**
- * Hold all currently allowed lambda variables
- * As lambda functions can be nested there may be more than one allowed lambda variables at a time while parsing a
- * $filter or $orderby expressions.
- */
- public Deque<LambdaVariable> allowedLambdaVariables;
- /**
- * Used to stack type information for nested $expand, $filter query options and other cases.
- */
- public Deque<EdmType> contextTypes;
-
- /** Whether the context types are collections. */
- public boolean isCollection;
-
- // CHECKSTYLE:OFF (Maven checkstyle)
- /**
- * Set within method
- * {@link org.apache.olingo.server.core.uri.antlr.UriParserBaseVisitor#visitExpandItem(org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandItemContext ctx)}
- * and
- * {@link org.apache.olingo.server.core.uri.antlr.UriParserBaseVisitor#visitExpandPathExtension(org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandPathExtensionContext ctx)}
- * to allow nodes
- * deeper in the expand tree at
- * {@link org.apache.olingo.server.core.uri.antlr.UriParserBaseVisitor#visitExpandPathExtension(org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandPathExtensionContext ctx)}
- * appending path
- * segments to the currently processed {@link ExpandItemImpl}.
- */
- public ExpandItemImpl contextExpandItemPath;
- // CHECKSTYLE:ON (Maven checkstyle)
-
- //CHECKSTYLE:OFF (Maven checkstyle)
- /**
- * Set to true in method {@link UriParseTreeVisitor#visitExpandPath} right before
- * calling {@link org.apache.olingo.server.core.uri.parser.UriParseTreeVisitor#readResourcePathSegment}
- * After reading the path the variable is set back to false
- *
- * readResourcePathSegment handles all navigation properties, it depends on the context if key predicates are allowed or not.
- * In case of expand
- */
- public boolean contextVisitExpandResourcePath;
- //CHECKSTYLE:ON (Maven checkstyle)
-
- // CHECKSTYLE:OFF (Maven checkstyle)
- /**
- * Set within method
- * {@link org.apache.olingo.server.core.uri.antlr.UriParserBaseVisitor#visitSelectItem(org.apache.olingo.server.core.uri.antlr.UriParserParser.SelectItemContext ctx)}
- * to allow
- * nodes
- * deeper in the expand tree at
- * {@link org.apache.olingo.server.core.uri.antlr.UriParserBaseVisitor#visitSelectSegment(org.apache.olingo.server.core.uri.antlr.UriParserParser.SelectSegmentContext ctx)}
- * appending path segments to the
- * currently processed {@link SelectItemImpl}.
- */
- public SelectItemImpl contextSelectItem;
- // CHECKSTYLE:ON (Maven checkstyle)
- /**
- * Stores the currently processed UriInfo objects. There is one URI Info object for the resource path
- * and one for each new first member access within $filter and $orderBy options.
- */
- public UriInfoImpl contextUriInfo;
- public boolean contextReadingFunctionParameters;
-
- /**
- * Set to true if the parser operates on query part.
- */
- public boolean contextReadingQueryPart;
-
- public UriContext() {
-
- contextExpandItemPath = null;
- contextReadingFunctionParameters = false;
- contextSelectItem = null;
- contextTypes = new ArrayDeque<EdmType>();
- allowedLambdaVariables = new ArrayDeque<UriContext.LambdaVariable>();
-
- }
-}
\ No newline at end of file
[4/6] olingo-odata4 git commit: [OLINGO-834] $expand parser in Java +
clean-up
Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java
deleted file mode 100644
index 1bab218..0000000
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java
+++ /dev/null
@@ -1,2313 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.olingo.server.core.uri.parser;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-import org.antlr.v4.runtime.misc.NotNull;
-import org.antlr.v4.runtime.misc.ParseCancellationException;
-import org.antlr.v4.runtime.tree.ParseTree;
-import org.apache.olingo.commons.api.edm.Edm;
-import org.apache.olingo.commons.api.edm.EdmAction;
-import org.apache.olingo.commons.api.edm.EdmActionImport;
-import org.apache.olingo.commons.api.edm.EdmComplexType;
-import org.apache.olingo.commons.api.edm.EdmElement;
-import org.apache.olingo.commons.api.edm.EdmEntityContainer;
-import org.apache.olingo.commons.api.edm.EdmEntitySet;
-import org.apache.olingo.commons.api.edm.EdmEntityType;
-import org.apache.olingo.commons.api.edm.EdmEnumType;
-import org.apache.olingo.commons.api.edm.EdmFunction;
-import org.apache.olingo.commons.api.edm.EdmFunctionImport;
-import org.apache.olingo.commons.api.edm.EdmNavigationProperty;
-import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
-import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
-import org.apache.olingo.commons.api.edm.EdmProperty;
-import org.apache.olingo.commons.api.edm.EdmReturnType;
-import org.apache.olingo.commons.api.edm.EdmSingleton;
-import org.apache.olingo.commons.api.edm.EdmStructuredType;
-import org.apache.olingo.commons.api.edm.EdmType;
-import org.apache.olingo.commons.api.edm.FullQualifiedName;
-import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
-import org.apache.olingo.commons.api.ex.ODataRuntimeException;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmPrimitiveTypeFactory;
-import org.apache.olingo.server.api.uri.UriInfoKind;
-import org.apache.olingo.server.api.uri.UriInfoResource;
-import org.apache.olingo.server.api.uri.UriParameter;
-import org.apache.olingo.server.api.uri.UriResource;
-import org.apache.olingo.server.api.uri.UriResourceEntitySet;
-import org.apache.olingo.server.api.uri.UriResourceFunction;
-import org.apache.olingo.server.api.uri.UriResourceNavigation;
-import org.apache.olingo.server.api.uri.UriResourcePartTyped;
-import org.apache.olingo.server.api.uri.UriResourceRoot;
-import org.apache.olingo.server.api.uri.queryoption.SelectItem;
-import org.apache.olingo.server.api.uri.queryoption.expression.BinaryOperatorKind;
-import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
-import org.apache.olingo.server.api.uri.queryoption.expression.MethodKind;
-import org.apache.olingo.server.api.uri.queryoption.expression.UnaryOperatorKind;
-import org.apache.olingo.server.core.uri.UriInfoImpl;
-import org.apache.olingo.server.core.uri.UriParameterImpl;
-import org.apache.olingo.server.core.uri.UriResourceActionImpl;
-import org.apache.olingo.server.core.uri.UriResourceComplexPropertyImpl;
-import org.apache.olingo.server.core.uri.UriResourceCountImpl;
-import org.apache.olingo.server.core.uri.UriResourceEntitySetImpl;
-import org.apache.olingo.server.core.uri.UriResourceFunctionImpl;
-import org.apache.olingo.server.core.uri.UriResourceImpl;
-import org.apache.olingo.server.core.uri.UriResourceItImpl;
-import org.apache.olingo.server.core.uri.UriResourceLambdaAllImpl;
-import org.apache.olingo.server.core.uri.UriResourceLambdaAnyImpl;
-import org.apache.olingo.server.core.uri.UriResourceLambdaVarImpl;
-import org.apache.olingo.server.core.uri.UriResourceNavigationPropertyImpl;
-import org.apache.olingo.server.core.uri.UriResourcePrimitivePropertyImpl;
-import org.apache.olingo.server.core.uri.UriResourceRefImpl;
-import org.apache.olingo.server.core.uri.UriResourceRootImpl;
-import org.apache.olingo.server.core.uri.UriResourceSingletonImpl;
-import org.apache.olingo.server.core.uri.UriResourceStartingTypeFilterImpl;
-import org.apache.olingo.server.core.uri.UriResourceTypedImpl;
-import org.apache.olingo.server.core.uri.UriResourceValueImpl;
-import org.apache.olingo.server.core.uri.UriResourceWithKeysImpl;
-import org.apache.olingo.server.core.uri.antlr.UriLexer;
-import org.apache.olingo.server.core.uri.antlr.UriParserBaseVisitor;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.AllEOFContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.AllExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.AltAddContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.AltAllContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.AltAndContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.AltAnyContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.AltComparismContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.AltEqualityContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.AltHasContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.AltMultContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.AltOrContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.AnyExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.ArrayOrObjectContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.BinaryLiteralContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.BooleanNonCaseLiteralContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.CastExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.CeilingMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.ConcatMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.ConstSegmentContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.ContainsMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.DateLiteralContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.DateMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.DatetimeoffsetLiteralContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.DayMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.DecimalLiteralContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.DurationLiteralContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.EndsWithMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.EntityEOFContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.EnumLiteralContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandCountOptionContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandItemContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandItemsContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandItemsEOFContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandOptionContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandPathContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandPathExtensionContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandRefOptionContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.FilterContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.FilterExpressionEOFContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.FloorMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.FractionalsecondsMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.GeoDistanceMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.GeoIntersectsMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.GeoLengthMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.GuidLiteralContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.HourMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.IndexOfMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.InlinecountContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.IntLiteralContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.IsofExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.LengthMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.LevelsContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.MaxDateTimeMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.MemberExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.MetadataEOFContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.MinDateTimeMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.MinuteMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.MonthMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.NameValueOptListContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.NameValuePairContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.NamespaceContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.NaninfinityLiteralContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.NowMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.NullruleLiteralContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.OrderByContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.OrderByEOFContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.OrderByItemContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.OrderListContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.PathSegmentContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.PathSegmentsContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.PrimitiveLiteralContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.QueryOptionContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.QueryOptionsContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.RootExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.RoundMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.SearchSpecialTokenContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.SecondMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.SelectContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.SelectEOFContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.SelectItemContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.SelectSegmentContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.SkipContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.SkiptokenContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.StartsWithMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.StringLiteralContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.SubstringMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.TimeMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.TimeofdayLiteralContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.ToLowerMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.ToUpperMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.TopContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.TotalOffsetMinutesMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.TotalsecondsMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.TrimMethodCallExprContext;
-import org.apache.olingo.server.core.uri.antlr.UriParserParser.YearMethodCallExprContext;
-import org.apache.olingo.server.core.uri.parser.UriParserSemanticException.MessageKeys;
-import org.apache.olingo.server.core.uri.queryoption.CountOptionImpl;
-import org.apache.olingo.server.core.uri.queryoption.ExpandItemImpl;
-import org.apache.olingo.server.core.uri.queryoption.ExpandOptionImpl;
-import org.apache.olingo.server.core.uri.queryoption.FilterOptionImpl;
-import org.apache.olingo.server.core.uri.queryoption.LevelsOptionImpl;
-import org.apache.olingo.server.core.uri.queryoption.OrderByItemImpl;
-import org.apache.olingo.server.core.uri.queryoption.OrderByOptionImpl;
-import org.apache.olingo.server.core.uri.queryoption.QueryOptionImpl;
-import org.apache.olingo.server.core.uri.queryoption.SelectItemImpl;
-import org.apache.olingo.server.core.uri.queryoption.SelectOptionImpl;
-import org.apache.olingo.server.core.uri.queryoption.SkipOptionImpl;
-import org.apache.olingo.server.core.uri.queryoption.SkipTokenOptionImpl;
-import org.apache.olingo.server.core.uri.queryoption.SystemQueryOptionImpl;
-import org.apache.olingo.server.core.uri.queryoption.TopOptionImpl;
-import org.apache.olingo.server.core.uri.queryoption.expression.AliasImpl;
-import org.apache.olingo.server.core.uri.queryoption.expression.BinaryImpl;
-import org.apache.olingo.server.core.uri.queryoption.expression.EnumerationImpl;
-import org.apache.olingo.server.core.uri.queryoption.expression.LiteralImpl;
-import org.apache.olingo.server.core.uri.queryoption.expression.MemberImpl;
-import org.apache.olingo.server.core.uri.queryoption.expression.MethodImpl;
-import org.apache.olingo.server.core.uri.queryoption.expression.TypeLiteralImpl;
-import org.apache.olingo.server.core.uri.queryoption.expression.UnaryImpl;
-
-/**
- * Converts the URI parse tree as generated by ANTLR into an internal representation
- * suitable to give to an application.
- * While converting the tree is only validated against the EDM if necessary.
- * <br>
- * Attention:
- * <ul>
- * <li>This UriVisitor is at somes point more lax than the original ABNF.</li>
- * <li>It is more tolerable against additional white spaces.</li>
- * </ul>
- * Currently not supported are
- * <ul>
- * <li>parsing the context of $metadata</li>
- * <li>parsing $search</li>
- * </ul>
- */
-public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
-
- public UriContext context = null;
-
- public Edm edm;
-
- public EdmEntityContainer edmEntityContainer;
-
- // --- class ---
- public UriParseTreeVisitor(final Edm edm, final UriContext context) {
- this.edm = edm;
- this.context = context;
- edmEntityContainer = edm.getEntityContainer();
- }
-
- @Override
- protected Object aggregateResult(final Object aggregate, final Object nextResult) {
- if (aggregate != null) {
- return aggregate;
- } else {
- return nextResult;
- }
- }
-
- private FullQualifiedName getFullNameFromContext(final NamespaceContext vNS, final String odi) {
- String namespace = vNS.getText();
- namespace = namespace.substring(0, namespace.length() - 1); // vNS contains a trailing point that has to be removed
- return new FullQualifiedName(namespace, odi);
- }
-
- private UriContext.LambdaVariable getLambdaVar(final String odi) {
- for (UriContext.LambdaVariable item : context.allowedLambdaVariables) {
- if (item.name.equals(odi)) {
- return item;
- }
- }
- return null;
- }
-
- public UriResourceTypedImpl readResourcePathSegment(final PathSegmentContext ctx) {
-
- final boolean checkFirst =
- context.contextUriInfo.getLastResourcePart() == null
- || context.contextUriInfo.getLastResourcePart() instanceof UriResourceRootImpl;
-
- String odi = ctx.vODI.getText();
-
- boolean searchInContainer = true;
- // validate if context type and according property is available
- // otherwise search in container for first element
- if (checkFirst && ctx.vNS == null && !context.contextTypes.isEmpty()) {
- EdmType sourceType = context.contextTypes.peek();
- if (sourceType instanceof EdmStructuredType) {
- EdmStructuredType str = (EdmStructuredType) sourceType;
- EdmElement property = str.getProperty(odi);
- if (property != null) {
- searchInContainer = false;
- }
- }
- }
-
- if (searchInContainer) {
- final List<UriResource> parts = context.contextUriInfo.getUriResourceParts();
- // check EntitySet
- EdmEntitySet edmEntitySet = edmEntityContainer.getEntitySet(odi);
- if (edmEntitySet != null
- && (parts.isEmpty() || !(parts.get(0) instanceof UriResourcePartTyped)
- || parts.get(0) instanceof UriResourceRoot)) {
- ensureNamespaceIsNull(ctx.vNS);
- context.contextUriInfo.addResourcePart(
- new UriResourceEntitySetImpl(edmEntitySet));
- return null;
- }
-
- // check Singleton
- EdmSingleton edmSingleton = edmEntityContainer.getSingleton(odi);
- if (edmSingleton != null
- && (parts.isEmpty() || !(parts.get(0) instanceof UriResourcePartTyped)
- || parts.get(0) instanceof UriResourceRoot)) {
- ensureNamespaceIsNull(ctx.vNS);
- context.contextUriInfo.addResourcePart(
- new UriResourceSingletonImpl(edmSingleton));
- return null;
- }
-
- // check ActionImport
- EdmActionImport edmActionImport = edmEntityContainer.getActionImport(odi);
- if (edmActionImport != null
- && (parts.isEmpty() || !(parts.get(0) instanceof UriResourcePartTyped)
- || parts.get(0) instanceof UriResourceRoot)) {
- ensureNamespaceIsNull(ctx.vNS);
- context.contextUriInfo.addResourcePart(
- new UriResourceActionImpl(edmActionImport));
- return null;
- }
-
- // check FunctionImport
- EdmFunctionImport edmFunctionImport = edmEntityContainer.getFunctionImport(odi);
-
- if(edmFunctionImport != null && context.contextReadingQueryPart) {
- throw wrap(new UriParserSemanticException("Function Imports are not allowed in $filter or $orderby",
- UriParserSemanticException.MessageKeys.FUNCTION_IMPORT_NOT_ALLOWED, odi));
- }
-
- if (edmFunctionImport != null
- && (parts.isEmpty() || !(parts.get(0) instanceof UriResourcePartTyped)
- || parts.get(0) instanceof UriResourceRoot)) {
-
- // read the URI parameters
- if (ctx.vlNVO.isEmpty()) {
- throw wrap(new UriParserSyntaxException(
- "Function imports must have a (possibly empty) parameter list written in parentheses",
- UriParserSyntaxException.MessageKeys.SYNTAX));
- }
- context.contextReadingFunctionParameters = true;
- @SuppressWarnings("unchecked")
- List<UriParameter> parameters = (List<UriParameter>) ctx.vlNVO.get(0).accept(this);
- context.contextReadingFunctionParameters = false;
-
- // mark parameters as consumed
- ctx.vlNVO.remove(0);
-
- // collect parameter names
- List<String> names = new ArrayList<String>();
- for (UriParameter item : parameters) {
- names.add(item.getName());
- }
-
- // get function from function import
- EdmFunction function = edmFunctionImport.getUnboundFunction(names);
- if (function == null) {
- StringBuilder tmp = new StringBuilder();
- for (String name : names) {
- tmp.append((tmp.length() != 0 ? "," : "")).append(name);
- }
- throw wrap(new UriParserSemanticException("Function of functionimport '" + edmFunctionImport.getName()
- + "' with parameters [" + tmp.toString() + "] not found",
- UriParserSemanticException.MessageKeys.FUNCTION_NOT_FOUND, edmFunctionImport.getName(), tmp.toString()));
- }
-
- ensureNamespaceIsNull(ctx.vNS);
- UriResourceFunctionImpl uriResource = new UriResourceFunctionImpl(edmFunctionImport,
- edmFunctionImport.getUnboundFunction(names),
- parameters);
- context.contextUriInfo.addResourcePart(uriResource);
- return null;
- }
- }
-
- EdmType sourceType;
- boolean sourceIsCollection = false;
- final UriResource lastResourcePart = context.contextUriInfo.getLastResourcePart();
-
- if (lastResourcePart == null) {
- if (context.contextTypes.isEmpty()) {
- if (checkFirst && ctx.vNS == null) {
- throw wrap(new UriParserSemanticException(
- "Cannot find EntitySet, Singleton, ActionImport or FunctionImport with name '" + odi + "'.",
- UriParserSemanticException.MessageKeys.RESOURCE_NOT_FOUND, odi));
- }
- throw wrap(new UriParserSemanticException(
- "Resource part '" + odi + "' can only applied on typed resource parts",
- UriParserSemanticException.MessageKeys.RESOURCE_PART_ONLY_FOR_TYPED_PARTS, odi));
- }
- sourceType = context.contextTypes.peek();
- sourceIsCollection = context.isCollection;
- } else if (lastResourcePart instanceof UriResourcePartTyped) {
- sourceType = ParserHelper.getTypeInformation((UriResourcePartTyped) lastResourcePart);
- sourceIsCollection = ((UriResourcePartTyped) lastResourcePart).isCollection();
- } else {
- throw wrap(new UriParserSemanticException(
- "Resource part '" + odi + "' can only be applied on typed resource parts.",
- UriParserSemanticException.MessageKeys.RESOURCE_PART_ONLY_FOR_TYPED_PARTS, odi));
- }
-
- if (ctx.vNS == null) { // without namespace
-
- // first check for lambda variable because a newly add property should not shadow a long used lambda variable
- UriContext.LambdaVariable lVar = getLambdaVar(odi);
- if (lVar != null) {
- UriResourceLambdaVarImpl lambdaResource = new UriResourceLambdaVarImpl(lVar.name, lVar.type);
- context.contextUriInfo.addResourcePart(lambdaResource);
- return null;
- }
-
- if (!(sourceType instanceof EdmStructuredType)) {
- throw wrap(new UriParserSemanticException(
- "Cannot parse '" + odi + "'; previous path segment is not a structural type.",
- UriParserSemanticException.MessageKeys.RESOURCE_PART_MUST_BE_PRECEDED_BY_STRUCTURAL_TYPE, odi));
- }
-
- if ((ctx.depth() <= 2 // path evaluation for the resource path
- || lastResourcePart instanceof UriResourceTypedImpl
- || lastResourcePart instanceof UriResourceNavigationPropertyImpl)
- && sourceIsCollection) {
- throw wrap(new UriParserSemanticException("Property '" + odi + "' is not allowed after collection.",
- UriParserSemanticException.MessageKeys.PROPERTY_AFTER_COLLECTION, odi));
- }
-
- EdmStructuredType structType = (EdmStructuredType) sourceType;
-
- EdmElement property = structType.getProperty(odi);
- if (property == null) {
- throw wrap(new UriParserSemanticException("Property '" + odi + "' not found in type '"
- + structType.getFullQualifiedName().getFullQualifiedNameAsString() + "'",
- ctx.depth() > 2 ? // path evaluation inside an expression or for the resource path?
- UriParserSemanticException.MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE
- : UriParserSemanticException.MessageKeys.PROPERTY_NOT_IN_TYPE,
- structType.getFullQualifiedName().getFullQualifiedNameAsString(), odi));
- }
-
- if (property instanceof EdmProperty) {
- if (((EdmProperty) property).isPrimitive()
- || property.getType().getKind() == EdmTypeKind.ENUM
- || property.getType().getKind() == EdmTypeKind.DEFINITION) {
- // create simple property
- UriResourcePrimitivePropertyImpl simpleResource =
- new UriResourcePrimitivePropertyImpl((EdmProperty) property);
- context.contextUriInfo.addResourcePart(simpleResource);
- return null;
- } else {
- // create complex property
- UriResourceComplexPropertyImpl complexResource = new UriResourceComplexPropertyImpl((EdmProperty) property);
- context.contextUriInfo.addResourcePart(complexResource);
- return null;
- }
- } else if (property instanceof EdmNavigationProperty) {
- // create navigation property
- if (context.contextVisitExpandResourcePath && ctx.vlNVO.size() > 0) {
- throw wrap(new UriParserSemanticException(
- "Navigation properties in expand system query options must not be followed by a key.",
- UriParserSemanticException.MessageKeys.KEY_NOT_ALLOWED));
- }
-
- UriResourceNavigationPropertyImpl navigationResource =
- new UriResourceNavigationPropertyImpl((EdmNavigationProperty) property);
- context.contextUriInfo.addResourcePart(navigationResource);
- return null;
- } else {
- throw wrap(new UriParserSemanticException("Unkown type for property '" + property + "'",
- UriParserSemanticException.MessageKeys.UNKNOWN_PROPERTY_TYPE, property.getName()));
- }
-
- } else { // with namespace
-
- FullQualifiedName fullFilterName = getFullNameFromContext(ctx.vNS, odi);
-
- // EdmType lastType = getLastType(lastTyped);
- if (sourceType instanceof EdmEntityType) {
-
- EdmEntityType filterEntityType = edm.getEntityType(fullFilterName);
- if (filterEntityType != null) {
- // is entity type cast
- if (!(filterEntityType.compatibleTo(sourceType))) {
- throw wrap(new UriParserSemanticException(
- "Entity typefilter not compatible to previous path segment: " + fullFilterName.toString(),
- UriParserSemanticException.MessageKeys.INCOMPATIBLE_TYPE_FILTER, fullFilterName.toString()));
- }
-
- if (lastResourcePart == null) {
- // this may be the case if a member expression within a filter starts with a typeCast
- UriResourceStartingTypeFilterImpl uriResource = new UriResourceStartingTypeFilterImpl(
- filterEntityType,
- sourceIsCollection);
- if (sourceIsCollection) {
- uriResource.setCollectionTypeFilter(filterEntityType);
- } else {
- uriResource.setEntryTypeFilter(filterEntityType);
- }
- context.contextUriInfo.addResourcePart(uriResource);
- return null;
- } else {
-
- // check if last segment may contain key properties
- if (lastResourcePart instanceof UriResourceWithKeysImpl) {
- UriResourceWithKeysImpl lastPartWithKeys = (UriResourceWithKeysImpl) lastResourcePart;
-
- if (!lastPartWithKeys.isCollection()) {
- if (lastPartWithKeys.getTypeFilterOnEntry() != null) {
- throw wrap(new UriParserSemanticException("Entry typefilters are not chainable, used '"
- + getName(filterEntityType) + "' behind '"
- + getName(lastPartWithKeys.getTypeFilterOnEntry()) + "'",
- UriParserSemanticException.MessageKeys.TYPE_FILTER_NOT_CHAINABLE,
- getName(lastPartWithKeys.getTypeFilterOnEntry()), getName(filterEntityType)));
- }
- lastPartWithKeys.setEntryTypeFilter(filterEntityType);
- return null;
- } else {
- if (lastPartWithKeys.getTypeFilterOnCollection() != null) {
- throw wrap(new UriParserSemanticException("Collection typefilters are not chainable, used '"
- + getName(filterEntityType) + "' behind '"
- + getName(lastPartWithKeys.getTypeFilterOnCollection()) + "'",
- UriParserSemanticException.MessageKeys.TYPE_FILTER_NOT_CHAINABLE,
- getName(lastPartWithKeys.getTypeFilterOnCollection()), getName(filterEntityType)));
- }
- lastPartWithKeys.setCollectionTypeFilter(filterEntityType);
- return null;
- }
- } else if (lastResourcePart instanceof UriResourceTypedImpl) {
- UriResourceTypedImpl lastPartTyped = (UriResourceTypedImpl) lastResourcePart;
- if (lastPartTyped.getTypeFilter() != null) {
- throw wrap(new UriParserSemanticException("Typefilters are not chainable, used '"
- + getName(filterEntityType) + "' behind '"
- + getName(lastPartTyped.getTypeFilter()) + "'",
- UriParserSemanticException.MessageKeys.TYPE_FILTER_NOT_CHAINABLE,
- getName(lastPartTyped.getTypeFilter()), getName(filterEntityType)));
- }
-
- lastPartTyped.setTypeFilter(filterEntityType);
- return null;
- } else {
- throw wrap(new UriParserSemanticException("Path segment before '" + getName(filterEntityType)
- + "' not typed",
- UriParserSemanticException.MessageKeys.PREVIOUS_PART_NOT_TYPED, getName(filterEntityType)));
- }
- }
- }
-
- } else if (sourceType instanceof EdmComplexType) {
-
- EdmComplexType filterComplexType = edm.getComplexType(fullFilterName);
-
- if (filterComplexType != null) {
-
- // is complex type cast
- if (!(filterComplexType.compatibleTo(sourceType))) {
- throw wrap(new UriParserSemanticException(
- "Complex typefilter '" + getName(sourceType) + "'not compatible type of previous path segment '"
- + getName(filterComplexType) + "'",
- UriParserSemanticException.MessageKeys.INCOMPATIBLE_TYPE_FILTER, getName(sourceType)));
- }
-
- // is simple complex type cast
- if (lastResourcePart == null) {
- // this may be the case if a member expression within a filter starts with a typeCast
- UriResourceStartingTypeFilterImpl uriResource =
- new UriResourceStartingTypeFilterImpl(filterComplexType, sourceIsCollection);
-
- if (sourceIsCollection) {
- uriResource.setCollectionTypeFilter(filterComplexType);
- } else {
- uriResource.setEntryTypeFilter(filterComplexType);
- }
- context.contextUriInfo.addResourcePart(uriResource);
- return null;
- } else {
- if (lastResourcePart instanceof UriResourceWithKeysImpl) {
- // e.g. in case of function returning complex data or a list of complex data
- UriResourceWithKeysImpl lastPartWithKeys = (UriResourceWithKeysImpl) lastResourcePart;
-
- if (!lastPartWithKeys.isCollection()) {
- if (lastPartWithKeys.getTypeFilterOnEntry() != null) {
- throw wrap(new UriParserSemanticException("Entry typefilters are not chainable, used '"
- + getName(filterComplexType) + "' behind '"
- + getName(lastPartWithKeys.getTypeFilterOnEntry()) + "'",
- UriParserSemanticException.MessageKeys.TYPE_FILTER_NOT_CHAINABLE,
- getName(lastPartWithKeys.getTypeFilterOnEntry()), getName(filterComplexType)));
- }
- lastPartWithKeys.setEntryTypeFilter(filterComplexType);
- return null;
- } else {
- if (lastPartWithKeys.getTypeFilterOnCollection() != null) {
- throw wrap(new UriParserSemanticException("Collection typefilters are not chainable, used '"
- + getName(filterComplexType) + "' behind '"
- + getName(lastPartWithKeys.getTypeFilterOnCollection()) + "'",
- UriParserSemanticException.MessageKeys.TYPE_FILTER_NOT_CHAINABLE,
- getName(lastPartWithKeys.getTypeFilterOnCollection()), getName(filterComplexType)));
- }
- lastPartWithKeys.setCollectionTypeFilter(filterComplexType);
- return null;
- }
-
- } else if (lastResourcePart instanceof UriResourceTypedImpl) {
- UriResourceTypedImpl lastPartTyped = (UriResourceTypedImpl) lastResourcePart;
- if (lastPartTyped.getTypeFilter() != null) {
- throw wrap(new UriParserSemanticException("Typefilters are not chainable, used '"
- + getName(filterComplexType) + "' behind '"
- + getName(lastPartTyped.getTypeFilter()) + "'",
- UriParserSemanticException.MessageKeys.TYPE_FILTER_NOT_CHAINABLE,
- getName(lastPartTyped.getTypeFilter()), getName(filterComplexType)));
- }
-
- lastPartTyped.setTypeFilter(filterComplexType);
- return null;
- } else {
- throw wrap(new UriParserSemanticException("Path segment before '" + getName(filterComplexType)
- + "' not typed",
- UriParserSemanticException.MessageKeys.PREVIOUS_PART_NOT_TYPED, getName(filterComplexType)));
- }
- }
- }
- }
-
- FullQualifiedName fullBindingTypeName = sourceType.getFullQualifiedName();
-
- // check for action
- EdmAction action = edm.getBoundAction(fullFilterName, fullBindingTypeName, sourceIsCollection);
- if (action != null) {
- UriResourceActionImpl pathInfoAction = new UriResourceActionImpl(action);
- context.contextUriInfo.addResourcePart(pathInfoAction);
- return null;
- }
-
- // do a check for bound functions (which requires a parameter list)
- if (ctx.vlNVO.size() == 0) {
- throw wrap(new UriParserSemanticException("Unknown type for type cast " + fullFilterName.toString()
- + " not found", UriParserSemanticException.MessageKeys.UNKNOWN_TYPE, fullFilterName.toString()));
- }
-
- context.contextReadingFunctionParameters = true;
- @SuppressWarnings("unchecked")
- List<UriParameter> parameters = (List<UriParameter>) ctx.vlNVO.get(0).accept(this);
- context.contextReadingFunctionParameters = false;
-
- // get names of function parameters
- List<String> names = new ArrayList<String>();
- for (UriParameter item : parameters) {
- names.add(item.getName());
- }
-
- EdmFunction function = edm.getBoundFunction(fullFilterName, fullBindingTypeName, sourceIsCollection, names);
-
- if (function != null) {
- UriResourceFunctionImpl pathInfoFunction = new UriResourceFunctionImpl(null, function, parameters);
- context.contextUriInfo.addResourcePart(pathInfoFunction);
-
- // mark parameters as consumed
- ctx.vlNVO.remove(0);
- return null;
- }
-
- // check for unbound function in the $filter case ( where the previous resource segment is a $it)
- function = edm.getUnboundFunction(fullFilterName, names);
-
- if (function != null) {
- UriResourceFunctionImpl pathInfoFunction = new UriResourceFunctionImpl(null, function, parameters);
- context.contextUriInfo.addResourcePart(pathInfoFunction);
-
- // mark parameters as consumed
- ctx.vlNVO.remove(0);
- return null;
- }
-
- throw wrap(new UriParserSemanticException("Unknown resource path segment:" + fullFilterName.toString(),
- UriParserSemanticException.MessageKeys.UNKNOWN_PART, fullFilterName.toString()));
- }
- }
-
- /**
- * Ensures that the namespace of the first resource parts is null
- * @param vNS namespace or null
- */
- private void ensureNamespaceIsNull(final NamespaceContext vNS) {
- if (vNS != null && context.contextUriInfo.getLastResourcePart() == null) {
- // First resource part and namespace is not null!
- throw wrap(new UriParserSemanticException("Namespace is not allowed for EntitySets, Singeltons, "
- + " Action Imports and Function Imports. Found " + vNS.getText(),
- UriParserSemanticException.MessageKeys.NAMESPACE_NOT_ALLOWED_AT_FIRST_ELEMENT, vNS.getText()));
- }
- }
-
- private String getName(final EdmType type) {
- return type.getFullQualifiedName().getFullQualifiedNameAsString();
- }
-
- @Override
- public Object visitAllEOF(final AllEOFContext ctx) {
- context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.all);
- return null;
- }
-
- @Override
- public Object visitAllExpr(final AllExprContext ctx) {
- UriResource obj = context.contextUriInfo.getLastResourcePart();
- if (!(obj instanceof UriResourcePartTyped)) {
- throw wrap(new UriParserSemanticException("all only allowed on typed path segments",
- UriParserSemanticException.MessageKeys.ONLY_FOR_TYPED_PARTS, "all"));
- } else if (obj instanceof UriResourceNavigation) {
- if (!((UriResourceNavigation) obj).getKeyPredicates().isEmpty()) {
- throw wrap(new UriParserSemanticException(
- "Any lamdba expression must not be following navigation properties with key predicates.",
- UriParserSemanticException.MessageKeys.KEY_NOT_ALLOWED));
- }
- }
-
- UriContext.LambdaVariable var = new UriContext.LambdaVariable();
- var.name = ctx.vLV.getText();
- var.type = ParserHelper.getTypeInformation((UriResourcePartTyped) obj);
-
- context.allowedLambdaVariables.push(var);
- Expression expression = (Expression) ctx.vLE.accept(this);
- context.allowedLambdaVariables.pop();
- return new UriResourceLambdaAllImpl(var.name, expression);
- }
-
- @Override
- public Expression visitAltAdd(final AltAddContext ctx) {
- int tokenIndex = ctx.vO.getType();
- return new BinaryImpl(
- (Expression) ctx.vE1.accept(this),
- tokenIndex == UriLexer.ADD ? BinaryOperatorKind.ADD : BinaryOperatorKind.SUB,
- (Expression) ctx.vE2.accept(this),
- null);
- }
-
- @Override
- public Object visitAltAll(final AltAllContext ctx) {
-
- UriInfoImpl uriInfoImplpath = new UriInfoImpl().setKind(UriInfoKind.resource);
-
- uriInfoImplpath.addResourcePart((UriResourceImpl) super.visitAltAll(ctx));
-
- EdmType startType = removeUriResourceStartingTypeFilterImpl(uriInfoImplpath);
-
- return new MemberImpl(uriInfoImplpath, startType);
- }
-
- private EdmType removeUriResourceStartingTypeFilterImpl(final UriInfoImpl uriInfoImplpath) {
-
- List<UriResource> segments = uriInfoImplpath.getUriResourceParts();
- if (segments.size() == 0) {
- return null;
- }
-
- UriResource segment = segments.get(0);
- if (segment instanceof UriResourceStartingTypeFilterImpl) {
- UriResourceStartingTypeFilterImpl startingTypeFilter = (UriResourceStartingTypeFilterImpl) segment;
-
- EdmType type = null;
- if (startingTypeFilter.getTypeFilterOnEntry() != null) {
- type = startingTypeFilter.getTypeFilterOnEntry();
- } else if (startingTypeFilter.getTypeFilterOnCollection() != null) {
- type = startingTypeFilter.getTypeFilterOnCollection();
- } else {
- type = startingTypeFilter.getType();
- }
-
- uriInfoImplpath.removeResourcePart(0);
- return type;
- }
-
- return null;
- }
-
- @Override
- public Expression visitAltAnd(final AltAndContext ctx) {
- return new BinaryImpl(
- (Expression) ctx.vE1.accept(this),
- BinaryOperatorKind.AND,
- (Expression) ctx.vE2.accept(this),
- EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Boolean));
- }
-
- @Override
- public Object visitAltAny(final AltAnyContext ctx) {
- UriInfoImpl uriInfoImplpath = new UriInfoImpl().setKind(UriInfoKind.resource);
-
- uriInfoImplpath.addResourcePart((UriResourceImpl) super.visitAltAny(ctx));
-
- EdmType startType = removeUriResourceStartingTypeFilterImpl(uriInfoImplpath);
-
- return new MemberImpl(uriInfoImplpath, startType);
- }
-
- @Override
- public Expression visitAltComparism(final AltComparismContext ctx) {
- int tokenIndex = ctx.vO.getType();
- BinaryOperatorKind kind = null;
- if (tokenIndex == UriLexer.GT) {
- kind = BinaryOperatorKind.GT;
- } else if (tokenIndex == UriLexer.GE) {
- kind = BinaryOperatorKind.GE;
- } else if (tokenIndex == UriLexer.LT) {
- kind = BinaryOperatorKind.LT;
- } else if (tokenIndex == UriLexer.LE) {
- kind = BinaryOperatorKind.LE;
- }
- return new BinaryImpl(
- (Expression) ctx.vE1.accept(this),
- kind,
- (Expression) ctx.vE2.accept(this),
- EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Boolean));
- }
-
- @Override
- public Object visitEntityEOF(final EntityEOFContext ctx) {
- String odi = ctx.vODI.getText();
- FullQualifiedName fullName = getFullNameFromContext(ctx.vNS, odi);
-
- EdmEntityType type = edm.getEntityType(fullName);
- if (type == null) {
- throw wrap(new UriParserSemanticException("Expected EntityTypeName",
- UriParserSemanticException.MessageKeys.UNKNOWN_ENTITY_TYPE, fullName.toString()));
- }
- context.contextUriInfo.setEntityTypeCast(type);
-
- // contextUriInfo = uriInfo;
- context.contextTypes.push(context.contextUriInfo.getEntityTypeCast());
- context.isCollection = true; // TODO: check!
-
- return null;
- }
-
- @Override
- public Expression visitAltEquality(final AltEqualityContext ctx) {
- int tokenIndex = ctx.vO.getType();
- return new BinaryImpl(
- (Expression) ctx.vE1.accept(this),
- tokenIndex == UriLexer.EQ_ALPHA ? BinaryOperatorKind.EQ : BinaryOperatorKind.NE,
- (Expression) ctx.vE2.accept(this),
- EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Boolean));
- }
-
- @Override
- public Object visitAltHas(final AltHasContext ctx) {
- return new BinaryImpl(
- (Expression) ctx.vE1.accept(this),
- BinaryOperatorKind.HAS,
- (Expression) ctx.vE2.accept(this),
- EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Boolean));
- }
-
- @Override
- public Object visitMetadataEOF(final MetadataEOFContext ctx) {
-
- context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.metadata);
- return null;
- }
-
- @Override
- public Expression visitAltMult(final AltMultContext ctx) {
- int tokenIndex = ctx.vO.getType();
- BinaryOperatorKind kind;
- if (tokenIndex == UriLexer.MUL) {
- kind = BinaryOperatorKind.MUL;
- } else if (tokenIndex == UriLexer.DIV) {
- kind = BinaryOperatorKind.DIV;
- } else {
- kind = BinaryOperatorKind.MOD;
- }
- return new BinaryImpl(
- (Expression) ctx.vE1.accept(this),
- kind,
- (Expression) ctx.vE2.accept(this),
- null);
- }
-
- @Override
- public Expression visitAltOr(final AltOrContext ctx) {
- return new BinaryImpl(
- (Expression) ctx.vE1.accept(this),
- BinaryOperatorKind.OR,
- (Expression) ctx.vE2.accept(this),
- EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Boolean));
- }
-
- @Override
- public Object visitAnyExpr(final AnyExprContext ctx) {
- if (ctx.vLV != null) {
- UriResourceImpl lastResourcePart = (UriResourceImpl) context.contextUriInfo.getLastResourcePart();
- if (!(lastResourcePart instanceof UriResourcePartTyped)) {
- throw wrap(new UriParserSemanticException("any only allowed on typed path segments",
- UriParserSemanticException.MessageKeys.ONLY_FOR_TYPED_PARTS, "any"));
- } else if (lastResourcePart instanceof UriResourceNavigation) {
- if (!((UriResourceNavigation) lastResourcePart).getKeyPredicates().isEmpty()) {
- throw wrap(new UriParserSemanticException(
- "Any lamdba expression must not be following navigation properties with key predicates",
- UriParserSemanticException.MessageKeys.KEY_NOT_ALLOWED));
- }
- }
-
- UriContext.LambdaVariable var = new UriContext.LambdaVariable();
- var.name = ctx.vLV.getText();
- var.type = ParserHelper.getTypeInformation((UriResourcePartTyped) lastResourcePart);
-
- context.allowedLambdaVariables.push(var);
- Expression expression = (Expression) ctx.vLE.accept(this);
- context.allowedLambdaVariables.pop();
- return new UriResourceLambdaAnyImpl(var.name, expression);
- }
- return null;
- }
-
- @Override
- public Object visitBooleanNonCaseLiteral(final BooleanNonCaseLiteralContext ctx) {
- final String text = ctx.getText().toLowerCase();
- return new LiteralImpl(text.equals("false") ? "false" : "true",
- EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Boolean));
- }
-
- @Override
- public Expression visitCastExpr(final CastExprContext ctx) {
- List<Expression> parameters = new ArrayList<Expression>();
- if (ctx.vE1 != null) {
- // is optional parameter
- parameters.add((Expression) ctx.vE1.accept(this));
- }
-
- String namespace = ctx.vNS.getText();
- namespace = namespace.substring(0, namespace.length() - 1);
-
- FullQualifiedName fullName = new FullQualifiedName(namespace, ctx.vODI.getText());
- EdmType type = getType(fullName);
- parameters.add(new TypeLiteralImpl(type));
- return new MethodImpl(MethodKind.CAST, parameters);
- }
-
- private EdmType getType(final FullQualifiedName fullName) {
- EdmType type = null;
-
- type = edm.getEntityType(fullName);
- if (type != null) {
- return type;
- }
-
- type = edm.getComplexType(fullName);
- if (type != null) {
- return type;
- }
-
- type = edm.getTypeDefinition(fullName);
- if (type != null) {
- return type;
- }
-
- type = edm.getEnumType(fullName);
- if (type != null) {
- return type;
- }
-
- if (fullName.getNamespace().equals(EdmPrimitiveType.EDM_NAMESPACE)) {
- final EdmPrimitiveTypeKind typeKind = EdmPrimitiveTypeKind.valueOf(fullName.getName());
- type = EdmPrimitiveTypeFactory.getInstance(typeKind);
- if (type != null) {
- return type;
- }
- }
-
- return null;
-
- }
-
- @Override
- public Expression visitCeilingMethodCallExpr(final CeilingMethodCallExprContext ctx) {
- return new MethodImpl(MethodKind.CEILING, Collections.singletonList((Expression) ctx.vE1.accept(this)));
- }
-
- @Override
- public Expression visitConcatMethodCallExpr(final ConcatMethodCallExprContext ctx) {
- return new MethodImpl(MethodKind.CONCAT, Arrays.asList(
- (Expression) ctx.vE1.accept(this),
- (Expression) ctx.vE2.accept(this)));
- }
-
- @Override
- public Object visitConstSegment(final ConstSegmentContext ctx) {
- UriInfoImpl uriInfoResource = context.contextUriInfo;
- UriResource pathInfo = uriInfoResource.getLastResourcePart();
-
- if (ctx.vV != null) {
- if (pathInfo instanceof UriResourcePartTyped) {
- if (!((UriResourcePartTyped) pathInfo).isCollection()) {
- context.contextUriInfo.addResourcePart(new UriResourceValueImpl());
- } else {
- throw wrap(new UriParserSemanticException("$value only allowed on typed path segments",
- UriParserSemanticException.MessageKeys.ONLY_FOR_TYPED_PARTS, "$value"));
- }
- return null;
- } else {
- throw wrap(new UriParserSemanticException("$value only allowed on typed path segments",
- UriParserSemanticException.MessageKeys.ONLY_FOR_TYPED_PARTS, "$value"));
- }
-
- } else if (ctx.vC != null) {
- if (pathInfo instanceof UriResourcePartTyped) {
- if (((UriResourcePartTyped) pathInfo).isCollection()) {
- context.contextUriInfo.addResourcePart(new UriResourceCountImpl());
- } else {
- throw wrap(new UriParserSemanticException("$count only allowed on collection properties",
- UriParserSemanticException.MessageKeys.ONLY_FOR_COLLECTIONS, "$count"));
- }
- } else {
- throw wrap(new UriParserSemanticException("$count only allowed on typed properties",
- UriParserSemanticException.MessageKeys.ONLY_FOR_TYPED_PARTS, "$count"));
- }
- } else if (ctx.vR != null) {
- if (pathInfo instanceof UriResourcePartTyped) {
- EdmType type = ((UriResourcePartTyped) pathInfo).getType();
- if (type instanceof EdmEntityType) {
- context.contextUriInfo.addResourcePart(new UriResourceRefImpl());
- } else {
- throw wrap(new UriParserSemanticException("$ref only allowed on entity types",
- UriParserSemanticException.MessageKeys.ONLY_FOR_ENTITY_TYPES, "$ref"));
- }
- } else {
- throw wrap(new UriParserSemanticException("$ref only allowed on typed properties",
- UriParserSemanticException.MessageKeys.ONLY_FOR_TYPED_PROPERTIES, "$ref"));
- }
-
- } else if (ctx.vAll != null) {
- context.contextUriInfo.addResourcePart((UriResourceLambdaAllImpl) ctx.vAll.accept(this));
- } else if (ctx.vAny != null) {
- context.contextUriInfo.addResourcePart((UriResourceLambdaAnyImpl) ctx.vAny.accept(this));
- }
- return null;
- }
-
- @Override
- public Expression visitContainsMethodCallExpr(final ContainsMethodCallExprContext ctx) {
- return new MethodImpl(MethodKind.CONTAINS, Arrays.asList(
- (Expression) ctx.vE1.accept(this),
- (Expression) ctx.vE2.accept(this)));
- }
-
- @Override
- public Object visitDateMethodCallExpr(final DateMethodCallExprContext ctx) {
- return new MethodImpl(MethodKind.DATE, Collections.singletonList((Expression) ctx.vE1.accept(this)));
- }
-
- @Override
- public Expression visitDayMethodCallExpr(final DayMethodCallExprContext ctx) {
- return new MethodImpl(MethodKind.DAY, Collections.singletonList((Expression) ctx.vE1.accept(this)));
- }
-
- @Override
- public Expression visitGeoDistanceMethodCallExpr(final GeoDistanceMethodCallExprContext ctx) {
- return new MethodImpl(MethodKind.GEODISTANCE, Arrays.asList(
- (Expression) ctx.vE1.accept(this),
- (Expression) ctx.vE2.accept(this)));
- }
-
- @Override
- public Object visitEndsWithMethodCallExpr(final EndsWithMethodCallExprContext ctx) {
- return new MethodImpl(MethodKind.ENDSWITH, Arrays.asList(
- (Expression) ctx.vE1.accept(this),
- (Expression) ctx.vE2.accept(this)));
- }
-
- @Override
- public Object visitEnumLiteral(final EnumLiteralContext ctx) {
- // get type
- final String odi = ctx.vODI.getText();
-
- final FullQualifiedName fullName = getFullNameFromContext(ctx.vNS, odi);
- final EdmEnumType edmEnumType = edm.getEnumType(fullName);
- if (edmEnumType == null) {
- throw wrap(new UriParserSemanticException(
- "Enum type '" + fullName.getFullQualifiedNameAsString() + "' not found!",
- UriParserSemanticException.MessageKeys.UNKNOWN_TYPE, fullName.getFullQualifiedNameAsString()));
- }
-
- String valueString = ctx.vValues.getText();
- valueString = valueString.substring(1, valueString.length() - 1);
- String[] values = valueString.split(",");
- return new EnumerationImpl(edmEnumType, Arrays.asList(values));
- }
-
- @Override
- public Object visitExpandItems(final ExpandItemsContext ctx) {
- ExpandOptionImpl expand = new ExpandOptionImpl();
- expand.setText(ctx.getText());
- for (ExpandItemContext eI : ctx.vlEI) {
- expand.addExpandItem((ExpandItemImpl) eI.accept(this));
- }
-
- return expand;
- }
-
- @Override
- public Object visitExpandItem(final ExpandItemContext ctx) {
-
- ExpandItemImpl expandItem = null;
- if (ctx.vS != null) {
- expandItem = new ExpandItemImpl().setIsStar(true);
- if (ctx.vR != null) {
- expandItem.setIsRef(true);
- } else if (ctx.vM != null) {
- LevelsOptionImpl levels = new LevelsOptionImpl().setMax();
- levels.setText(ctx.vM.getText());
- try {
- expandItem.setSystemQueryOption(levels);
- } catch (ODataRuntimeException e) {
- // Thrown if duplicated system query options are detected
- throw wrap(new UriParserSyntaxException("Double system query option!", e,
- UriParserSyntaxException.MessageKeys.DOUBLE_SYSTEM_QUERY_OPTION, e.getMessage()));
- }
- } else if (ctx.vL != null) {
- LevelsOptionImpl levels = new LevelsOptionImpl();
- String text = ctx.vL.getText();
- levels.setText(text);
- levels.setValue(Integer.parseInt(text));
- try {
- expandItem.setSystemQueryOption(levels);
- } catch (ODataRuntimeException e) {
- // Thrown if duplicated system query options are detected
- throw wrap(new UriParserSyntaxException("Double system query option!", e,
- UriParserSyntaxException.MessageKeys.DOUBLE_SYSTEM_QUERY_OPTION, e.getMessage()));
- }
- }
-
- } else if (ctx.vEP != null) {
- expandItem = (ExpandItemImpl) ctx.vEP.accept(this);
-
- if (ctx.vEPE != null) {
- ExpandItemImpl contextExpandItemPathBU = context.contextExpandItemPath;
- context.contextExpandItemPath = expandItem;
-
- @SuppressWarnings("unchecked")
- List<SystemQueryOptionImpl> list = (List<SystemQueryOptionImpl>) ctx.vEPE.accept(this);
- try {
- for (SystemQueryOptionImpl option : list) {
- expandItem.setSystemQueryOption(option);
- }
- } catch (ODataRuntimeException e) {
- // Thrown if duplicated system query options are detected
- throw wrap(new UriParserSyntaxException("Double system query option!", e,
- UriParserSyntaxException.MessageKeys.DOUBLE_SYSTEM_QUERY_OPTION, e.getMessage()));
- }
- context.contextExpandItemPath = contextExpandItemPathBU;
- }
- }
-
- return expandItem;
-
- }
-
- @Override
- public Object visitExpandPath(final ExpandPathContext ctx) {
- ExpandItemImpl expandItem = new ExpandItemImpl();
-
- // save context
- ExpandItemImpl contextExpandItemPathBU = context.contextExpandItemPath;
- UriInfoImpl uriInfoResourceBU = context.contextUriInfo;
-
- // set tmp context
- context.contextExpandItemPath = expandItem;
- context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.resource);
-
- context.contextVisitExpandResourcePath = true;
- super.visitExpandPath(ctx);
- context.contextVisitExpandResourcePath = false;
-
- EdmType startType = removeUriResourceStartingTypeFilterImpl(context.contextUriInfo);
- expandItem.setResourcePath(context.contextUriInfo);
- if (startType != null) {
- expandItem.setTypeFilter(startType);
- }
-
- // reset context
- context.contextUriInfo = uriInfoResourceBU;
- context.contextExpandItemPath = contextExpandItemPathBU;
-
- // test
- validate(uriInfoResourceBU.asUriInfoResource(), expandItem);
- //
-
- return expandItem;
- }
-
- private void validate(UriInfoResource uriInfoResource, ExpandItemImpl expandItem) {
- if (uriInfoResource != null) {
- EdmEntityType type = getEntityType(uriInfoResource);
- EdmEntityType name = getEntityType(expandItem.getResourcePath());
-
- if (name != null && type != null) {
- EdmElement property = type.getProperty(name.getName());
- if (!(property instanceof EdmNavigationProperty)) {
- throw wrap(new UriParserSemanticException(
- "NavigationProperty '" + name.getName() + "' not found in type '"
- + type.getFullQualifiedName().getFullQualifiedNameAsString() + "'",
- UriParserSemanticException.MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE,
- name.getFullQualifiedName().getFullQualifiedNameAsString(),
- type.getFullQualifiedName().getFullQualifiedNameAsString()));
- }
- }
- }
- }
-
- private EdmEntityType getEntityType(UriInfoResource test) {
- List<UriResource> parts = test.getUriResourceParts();
- if (!parts.isEmpty()) {
- UriResource lastPart = parts.get(parts.size() - 1);
- if (lastPart instanceof UriResourceEntitySet) {
- UriResourceEntitySet entitySet = (UriResourceEntitySet) lastPart;
- return entitySet.getEntityType();
- }
- }
- return null;
- }
-
- @Override
- public Object visitExpandPathExtension(final ExpandPathExtensionContext ctx) {
- List<SystemQueryOptionImpl> list = new ArrayList<SystemQueryOptionImpl>();
-
- EdmType targetType = null;
- boolean isColl = false;
- if (context.contextExpandItemPath == null) {
- // use the type of the last resource path segement
- UriResourceTypedImpl lastSegment = (UriResourceTypedImpl) context.contextUriInfo.getLastResourcePart();
- targetType = ParserHelper.getTypeInformation(lastSegment);
- isColl = lastSegment.isCollection();
- } else {
- if (context.contextExpandItemPath.getResourcePath() == null) {
- // use the type of the last resource path segement
- UriResourceTypedImpl lastSegment = (UriResourceTypedImpl) context.contextUriInfo.getLastResourcePart();
- targetType = ParserHelper.getTypeInformation(lastSegment);
- isColl = lastSegment.isCollection();
- } else {
- // use the type of the last ''expand'' path segement
- UriInfoImpl info = (UriInfoImpl) context.contextExpandItemPath.getResourcePath();
- targetType = ParserHelper.getTypeInformation((UriResourcePartTyped) info.getLastResourcePart());
- isColl = ((UriResourcePartTyped) info.getLastResourcePart()).isCollection();
- }
- }
-
- context.contextTypes.push(targetType);
- context.isCollection = isColl;
-
- if (ctx.vC != null) {
- UriInfoImpl resourcePath = (UriInfoImpl) context.contextExpandItemPath.getResourcePath();
- resourcePath.addResourcePart(new UriResourceCountImpl());
-
- for (ExpandCountOptionContext s : ctx.vlEOC) {
- list.add((SystemQueryOptionImpl) s.accept(this));
- }
- } else if (ctx.vR != null) {
- UriInfoImpl resourcePath = (UriInfoImpl) context.contextExpandItemPath.getResourcePath();
- resourcePath.addResourcePart(new UriResourceRefImpl());
-
- for (ExpandRefOptionContext s : ctx.vlEOR) {
- list.add((SystemQueryOptionImpl) s.accept(this));
- }
- } else {
- for (ExpandOptionContext s : ctx.vlEO) {
- list.add((SystemQueryOptionImpl) s.accept(this));
- }
- }
-
- context.contextTypes.pop();
- return list;
-
- }
-
- @Override
- public Object visitFilter(final FilterContext ctx) {
- context.contextReadingQueryPart = true;
- final FilterOptionImpl result = new FilterOptionImpl().setExpression((Expression) ctx.children.get(2)
- .accept(this));
- context.contextReadingQueryPart = false;
-
- return result;
- }
-
- @Override
- public Object visitFilterExpressionEOF(final FilterExpressionEOFContext ctx) {
- context.contextReadingQueryPart = true;
- final FilterOptionImpl result = new FilterOptionImpl().setExpression((Expression) ctx.children.get(0)
- .accept(this));
- context.contextReadingQueryPart = false;
-
- return result;
- }
-
- @Override
- public Expression visitFloorMethodCallExpr(final FloorMethodCallExprContext ctx) {
- return new MethodImpl(MethodKind.FLOOR, Collections.singletonList((Expression) ctx.vE1.accept(this)));
- }
-
- @Override
- public Expression visitFractionalsecondsMethodCallExpr(final FractionalsecondsMethodCallExprContext ctx) {
- return new MethodImpl(MethodKind.FRACTIONALSECONDS, Collections.singletonList((Expression) ctx.vE1.accept(this)));
- }
-
- @Override
- public Expression visitGeoLengthMethodCallExpr(final GeoLengthMethodCallExprContext ctx) {
- return new MethodImpl(MethodKind.GEOLENGTH, Collections.singletonList((Expression) ctx.vE1.accept(this)));
- }
-
- @Override
- public Expression visitHourMethodCallExpr(final HourMethodCallExprContext ctx) {
- return new MethodImpl(MethodKind.HOUR, Collections.singletonList((Expression) ctx.vE1.accept(this)));
- }
-
- @Override
- public Expression visitIndexOfMethodCallExpr(final IndexOfMethodCallExprContext ctx) {
- return new MethodImpl(MethodKind.INDEXOF, Arrays.asList(
- (Expression) ctx.vE1.accept(this),
- (Expression) ctx.vE2.accept(this)));
- }
-
- @Override
- public Object visitInlinecount(final InlinecountContext ctx) {
- final String text = ctx.children.get(2).getText();
- return new CountOptionImpl()
- .setValue(text.equalsIgnoreCase("true") ? true : false)
- .setText(text);
- }
-
- @Override
- public Expression visitGeoIntersectsMethodCallExpr(final GeoIntersectsMethodCallExprContext ctx) {
- return new MethodImpl(MethodKind.GEOINTERSECTS, Arrays.asList(
- (Expression) ctx.vE1.accept(this),
- (Expression) ctx.vE2.accept(this)));
- }
-
- @Override
- public Expression visitIsofExpr(final IsofExprContext ctx) {
- List<Expression> parameters = new ArrayList<Expression>();
- if (ctx.vE1 != null) {
- parameters.add((Expression) ctx.vE1.accept(this));
- }
-
- String namespace = ctx.vNS.getText();
- namespace = namespace.substring(0, namespace.length() - 1);
-
- FullQualifiedName fullName = new FullQualifiedName(namespace, ctx.vODI.getText());
- EdmType type = getType(fullName);
- parameters.add(new TypeLiteralImpl(type));
-
- return new MethodImpl(MethodKind.ISOF, parameters);
- }
-
- @Override
- public Expression visitLengthMethodCallExpr(final LengthMethodCallExprContext ctx) {
- return new MethodImpl(MethodKind.LENGTH, Collections.singletonList((Expression) ctx.vE1.accept(this)));
- }
-
- @Override
- public Object visitLevels(final LevelsContext ctx) {
-
- LevelsOptionImpl levels = new LevelsOptionImpl();
-
- String text = ctx.children.get(2).getText();
-
- if (text.equals("max")) {
- levels.setMax();
- } else {
- levels.setValue(Integer.parseInt(text));
- }
- levels.setText(text);
-
- return levels;
-
- }
-
- @Override
- public Expression visitMaxDateTimeMethodCallExpr(final MaxDateTimeMethodCallExprContext ctx) {
- return new MethodImpl(MethodKind.MAXDATETIME, null);
- }
-
- @Override
- public Object visitMemberExpr(final MemberExprContext ctx) {
-
- UriInfoImpl uriInfoImplpath = new UriInfoImpl().setKind(UriInfoKind.resource);
-
- if (context.contextTypes.isEmpty()) {
- throw wrap(new UriParserSemanticException("Expression '" + ctx.getText() + "' is not allowed as key value.",
- UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, ctx.getText()));
- }
-
- if (ctx.vIt != null || ctx.vIts != null) {
- uriInfoImplpath.addResourcePart(new UriResourceItImpl(context.contextTypes.peek(), context.isCollection));
- }
-
- if (ctx.vPs != null) {
- // save the context
- UriInfoImpl backupUriInfoPath = context.contextUriInfo;
-
- // set temporary uriInfoPath
- context.contextUriInfo = uriInfoImplpath;
-
- ctx.vPs.accept(this);
-
- // reset context
- context.contextUriInfo = backupUriInfoPath;
- }
-
- if (ctx.vALL != null) {
- uriInfoImplpath.addResourcePart((UriResourceImpl) ctx.vALL.accept(this));
- }
- if (ctx.vANY != null) {
- uriInfoImplpath.addResourcePart((UriResourceImpl) ctx.vANY.accept(this));
- }
-
- EdmType startType = removeUriResourceStartingTypeFilterImpl(uriInfoImplpath);
-
- return new MemberImpl(uriInfoImplpath, startType);
- }
-
- @Override
- public Expression visitMinDateTimeMethodCallExpr(final MinDateTimeMethodCallExprContext ctx) {
- return new MethodImpl(MethodKind.MINDATETIME, null);
- }
-
- @Override
- public Expression visitMinuteMethodCallExpr(final MinuteMethodCallExprContext ctx) {
- return new MethodImpl(MethodKind.MINUTE, Collections.singletonList((Expression) ctx.vE1.accept(this)));
- }
-
- @Override
- public Expression visitMonthMethodCallExpr(final MonthMethodCallExprContext ctx) {
- return new MethodImpl(MethodKind.MONTH, Collections.singletonList((Expression) ctx.vE1.accept(this)));
- }
-
- @Override
- public Object visitNameValueOptList(final NameValueOptListContext ctx) {
- if (ctx.vVO != null) {
- // This branch is chosen if the key predicate is a common expression e.g. EntitySet(0)
-
- // is single key predicate without a name
- String valueText = ctx.vVO.getText();
- Expression expression = null;
- try {
- expression = (Expression) ctx.vVO.accept(this);
- } catch (final RuntimeException e) {
- throw wrap(new UriParserSemanticException("Invalid key value: " + valueText, e,
- UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, valueText));
- }
-
- // get type of last resource part
- UriResource last = context.contextUriInfo.getLastResourcePart();
- if (!(last instanceof UriResourcePartTyped)) {
- throw wrap(new UriParserSemanticException("Parameters list on untyped resource path segment not allowed",
- UriParserSemanticException.MessageKeys.PARAMETERS_LIST_ONLY_FOR_TYPED_PARTS));
-
- } else if (last instanceof UriResourceFunction) {
- // Handle functions
- final UriResourceFunction uriResourceFunction =
- (UriResourceFunction) context.contextUriInfo.getLastResourcePart();
- final EdmReturnType returnType = uriResourceFunction.getFunction().getReturnType();
-
- if (returnType.getType().getKind() != EdmTypeKind.ENTITY || !returnType.isCollection()) {
- throw wrap(new UriParserSemanticException("No keys allowed",
- UriParserSemanticException.MessageKeys.KEY_NOT_ALLOWED));
- } else {
- // The functions returns a collection of entities
- // Get the EDM Type and determine how many key predicates are needed. In this case only one
- // key predicate is allowed. If the entity type needs more than one key predicate, the client
- // has to use the key value syntax e.g. EntitySet(ID=1,Order=2)
- final EdmEntityType entityType = (EdmEntityType) uriResourceFunction.getFunction().getReturnType().getType();
- final List<String> lastKeyPredicates = entityType.getKeyPredicateNames();
-
- if (lastKeyPredicates.size() == 1) {
- return Collections.singletonList(new UriParameterImpl()
- .setName(lastKeyPredicates.get(0))
- .setText(valueText)
- .setExpression(expression));
- } else {
- throw wrap(new UriParserSemanticException("Wrong number of key properties.",
- UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
- Integer.toString(lastKeyPredicates.size()), "1"));
- }
- }
- } else {
- // Handle EntitySets
- EdmEntityType lastType = (EdmEntityType) ((UriResourcePartTyped) last).getType();
-
- // get list of keys for lastType
- List<String> lastKeyPredicates = lastType.getKeyPredicateNames();
-
- // If there is exactly one key defined in the EDM, then this key is the key written in the URI,
- // so fill the keylist with this key and return.
- if (lastKeyPredicates.size() == 1) {
- return Collections.singletonList(new UriParameterImpl()
- .setName(lastKeyPredicates.get(0))
- .setText(valueText)
- .setExpression(expression));
- }
-
- // There are more keys defined in the EDM, but only one is written in the URI. This is allowed only if
- // referential constraints are defined on this navigation property which can be used to fill up all
- // required keys.
- // For using referential constraints the last resource part must be a navigation property.
- if (!(context.contextUriInfo.getLastResourcePart() instanceof UriResourceNavigationPropertyImpl)) {
- throw wrap(new UriParserSemanticException("Wrong number of key properties.",
- UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
- Integer.toString(lastKeyPredicates.size()), "1"));
- }
- UriResourceNavigationPropertyImpl lastNav = (UriResourceNavigationPropertyImpl) last;
-
- // get the partner of the navigation property
- EdmNavigationProperty partner = lastNav.getProperty().getPartner();
- if (partner == null) {
- throw wrap(new UriParserSemanticException("Wrong number of key properties.",
- UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
- Integer.toString(lastKeyPredicates.size()), "1"));
- }
-
- // create the keylist
- List<UriParameterImpl> list = new ArrayList<UriParameterImpl>();
-
- // Find the keys not filled by referential constraints
- // and collect the other keys filled by referential constraints.
- String missedKey = null;
- for (String item : lastKeyPredicates) {
- String property = partner.getReferencingPropertyName(item);
- if (property != null) {
- list.add(new UriParameterImpl().setName(item).setReferencedProperty(property));
- } else {
- if (missedKey == null) {
- missedKey = item;
- } else {
- // two of more keys are missing
- throw wrap(new UriParserSemanticException("Not enough referential constraints defined",
- UriParserSemanticException.MessageKeys.NOT_ENOUGH_REFERENTIAL_CONSTRAINTS));
- }
- }
- }
-
- // the missing key is the one which is defined in the URI
- list.add(new UriParameterImpl().setName(missedKey).setText(valueText).setExpression(expression));
-
- return list;
- }
- } else if (ctx.vNVL != null) {
- // The client provided a list of key values pairs e.g. EntitySet(ID=1,Order=2)
- List<UriParameterImpl> list = new ArrayList<UriParameterImpl>();
-
- for (ParseTree c : ctx.vNVL.vlNVP) {
- list.add((UriParameterImpl) c.accept(this));
- }
-
- if (context.contextReadingFunctionParameters) {
- return list;
- }
-
- UriResource last = context.contextUriInfo.getLastResourcePart();
-
- // get type of last resource part
- if (!(last instanceof UriResourcePartTyped)) {
- throw wrap(new UriParserSemanticException("Parameters list on untyped resource path segment not allowed",
- UriParserSemanticException.MessageKeys.PARAMETERS_LIST_ONLY_FOR_TYPED_PARTS));
- }
- if (last instanceof UriResourceFunction) {
- final UriResourceFunction uriResourceFunction = (UriResourceFunction) context.contextUriInfo
- .getLastResourcePart();
- final EdmReturnType returnType = uriResourceFunction.getFunction().getReturnType();
-
- if (returnType.getType().getKind() != EdmTypeKind.ENTITY || !returnType.isCollection()) {
- throw wrap(new UriParserSemanticException("No keys allowed",
- UriParserSemanticException.MessageKeys.KEY_NOT_ALLOWED));
- } else {
- // The functions returns a collection of entities
- // Get the EDM Type and determine how many key predicates are needed.
- // In case of functions all key predicates must be provided by the client.
- final EdmEntityType entityType = (EdmEntityType) uriResourceFunction.getFunction().getReturnType().getType();
- final List<String> lastKeyPredicates = entityType.getKeyPredicateNames();
-
- if (lastKeyPredicates.size() == list.size()) {
- return list;
- } else {
- throw wrap(new UriParserSemanticException("Wrong number of key properties.",
- UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
- Integer.toString(lastKeyPredicates.size()), "1"));
- }
- }
- } else {
- // Handle entity sets
- EdmEntityType lastType = (EdmEntityType) ((UriResourcePartTyped) last).getType();
-
- // get list of keys for lastType
- List<String> lastKeyPredicates = lastType.getKeyPredicateNames();
-
- // check if all key are filled from the URI
- if (list.size() == lastKeyPredicates.size()) {
- return list;
- }
-
- // if not, check if the missing key predicates can be satisfied with help of the defined
- // referential constraints
- // for using referential constraints the last resource part must be a navigation property
- if (!(context.contextUriInfo.getLastResourcePart() instanceof UriResourceNavigationPropertyImpl)) {
- throw wrap(new UriParserSemanticException("Wrong number of key properties.",
- UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
- Integer.toString(lastKeyPredicates.size()), Integer.toString(list.size())));
- }
- UriResourceNavigationPropertyImpl lastNav = (UriResourceNavigationPropertyImpl) last;
-
- // get the partner of the navigation property
- EdmNavigationProperty partner = lastNav.getProperty().getPartner();
- if (partner == null) {
- throw wrap(new UriParserSemanticException("Wrong number of key properties.",
- UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
- Integer.toString(lastKeyPredicates.size()), Integer.toString(list.size())));
- }
-
- // fill missing keys from referential constraints
- for (String key : lastKeyPredicates) {
- boolean found = false;
- for (UriParameterImpl item : list) {
- if (item.getName().equals(key)) {
- found = true;
- break;
- }
- }
-
- if (!found) {
- String property = partner.getReferencingPropertyName(key);
- if (property != null) {
- // store the key name as referenced property
- list.add(0, new UriParameterImpl().setName(key).setReferencedProperty(property));
- }
- }
- }
-
- // check again if all key predicates are filled from the URI
- if (list.size() == lastKeyPredicates.size()) {
- return list;
- } else {
- throw wrap(new UriParserSemanticException("Wrong number of key properties.",
- UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
- Integer.toString(lastKeyPredicates.size()), Integer.toString(list.size())));
- }
- }
- } else {
- // No key predicates are provided by the client
-
- if (context.contextReadingFunctionParameters) {
- return Collections.emptyList();
- } else {
- final UriResource last = context.contextUriInfo.getLastResourcePart();
- final int number = last instanceof UriResourcePartTyped ? ((EdmEntityType) ((UriResourcePartTyped) last)
- .getType()).getKeyPredicateNames().size() : 0;
- throw wrap(new UriParserSemanticException("Wrong number of key properties.",
- UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES, Integer.toString(number), "0"));
- }
- }
- }
-
- @Override
- public UriParameterImpl visitNameValuePair(final NameValuePairContext ctx) {
- UriParameterImpl uriParameter = new UriParameterImpl();
- uriParameter.setName(ctx.vODI.getText());
-
- if (ctx.vCOM != null) {
- final String text = ctx.vCOM.getText();
- uriParameter.setText("null".equals(text) ? null : text);
- uriParameter.setExpression((Expression) ctx.vCOM.accept(this));
- } else {
- uriParameter.setAlias("@" + ctx.vALI.getText());
- }
-
- return uriParameter;
- }
-
- @Override
- public Object visitNaninfinityLiteral(final NaninfinityLiteralContext ctx) {
- return new LiteralImpl(ctx.getText(),
- EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal));
- }
-
- @Override
- public Expression visitNowMethodCallExpr(final NowMethodCallExprContext ctx) {
- return new MethodImpl(MethodKind.NOW, null);
- }
-
- @Override
- public Object visitNullruleLiteral(final NullruleLiteralContext ctx) {
- return new LiteralImpl("null", null);
- }
-
- @Override
- public Object visitOrderBy(final OrderByContext ctx) {
-
- OrderByOptionImpl orderBy = new OrderByOptionImpl();
-
- for (OrderByItemContext item : ((OrderListContext) ctx.getChild(2)).vlOI) {
- OrderByItemImpl oItem = (OrderByItemImpl) item.accept(this);
- orderBy.addOrder(oItem);
- }
-
- return orderBy;
- }
-
- @Override
- public Object visitOrderByEOF(final OrderByEOFContext ctx) {
- context.contextReadingQueryPart = true;
-
- OrderByOptionImpl orderBy = new OrderByOptionImpl();
-
- for (OrderByItemContext item : ((OrderListContext) ctx.getChild(0)).vlOI) {
- OrderByItemImpl oItem = (OrderByItemImpl) item.accept(this);
- orderBy.addOrder(oItem);
- }
-
- context.contextReadingFunctionParameters = false;
- return orderBy;
- }
-
- @Override
- public Object visitOrderByItem(final OrderByItemContext ctx) {
- OrderByItemImpl oItem = new OrderByItemImpl();
- if (ctx.vD != null) {
- oItem.setDescending(true);
- }
-
- oItem.setExpression((Expression) ctx.vC.accept(this));
- return oItem;
- }
-
- @Override
- public Object visitPathSegment(final PathSegmentContext ctx) {
- readResourcePathSegment(ctx);
- /*
- * if (contextUriInfo.getLastResourcePart() == null ||
- * contextUriInfo.getLastResourcePart() instanceof UriResourceRootImpl) {
- *
- * } else {
- * readNextPathInfoSegment(ctx);
- * }
- */
- UriResourceImpl pathInfoSegment = (UriResourceImpl) context.contextUriInfo.getLastResourcePart();
-
- if (ctx.vlNVO.size() > 0) {
- // check for keyPredicates
- if (pathInfoSegment instanceof UriResourceWithKeysImpl) {
- if (ctx.vlNVO.size() > 1) {
- throw wrap(new UriParserSemanticException("More than one key predicates found",
- UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES, "1",
- Integer.toString(ctx.vlNVO.size())));
- }
-
- @SuppressWarnings("unchecked")
- List<UriParameter> list = (List<UriParameter>) ctx.vlNVO.get(0).accept(this);
- ((UriResourceWithKeysImpl) pathInfoSegment)
- .setKeyPredicates(list);
- } else {
- throw wrap(new UriParserSemanticException("Key properties not allowed",
- UriParserSemanticException.MessageKeys.KEY_NOT_ALLOWED));
- }
- }
-
- return pathInfoSegment;
- }
-
- @Override
- public Object visitPathSegments(final PathSegmentsContext ctx) {
- // path segment
- for (PathSegmentContext it : ctx.vlPS) {
- it.accept(this);
- }
-
- // const segment
- if (ctx.vCS != null) {
- ctx.vCS.accept(this);
- }
- return null;
- }
-
- @Override
- public Object visitPrimitiveLiteral(final PrimitiveLiteralContext ctx) {
- ParseTree child1 = ctx.children.get(0);
-
- if (child1 instanceof EnumLiteralContext
- || child1 instanceof BooleanNonCaseLiteralContext
- || child1 instanceof NullruleLiteralContext
- || child1 instanceof NaninfinityLiteralContext
- || child1 instanceof StringLiteralContext
- || child1 instanceof IntLiteralContext
- || child1 instanceof BinaryLiteralContext
- || child1 instanceof DateLiteralContext
- || child1 instanceof DatetimeoffsetLiteralContext
- || child1 instanceof DurationLiteralContext
- || child1 instanceof GuidLiteralContext
- || child1 instanceof TimeofdayLiteralContext
- || child1 instanceof DecimalLiteralContext
- || child1 instanceof BinaryLiteralContext) {
- return child1.accept(this);
- }
-
- // TODO Implement geography types and set a proper type
- return new LiteralImpl(ctx.getText(), null);
- }
-
- @Override
- public Object visitBinaryLiteral(BinaryLiteralContext ctx) {
- return new LiteralImpl(ctx.getText(),
- EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Binary));
- }
-
- @Override
- public Object visitStringLiteral(final StringLiteralContext ctx) {
- return new LiteralImpl(ctx.getText(),
- EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.String));
- }
-
- @Override
- public Object visitDecimalLiteral(final DecimalLiteralContext ctx) {
- final EdmType type = EdmPrimitiveTypeFactory.getInstance(
- ctx.getText().contains("e") || ctx.getText().contains("E") ?
- EdmPrimitiveTypeKind.Double :
- EdmPrimitiveTypeKind.Decimal);
-
- return new LiteralImpl(ctx.getText(), type);
- }
-
- @Override
- public Object visitIntLiteral(final IntLiteralContext ctx) {
- EdmPrimitiveTypeKind typeKind = null;
- try {
- final long value = Long.parseLong(ctx.getText());
- if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) {
- typeKind = EdmPrimitiveTypeKind.SByte;
- } else if (value >= 0 && value <= 255) {
- typeKind = EdmPrimitiveTypeKind.Byte;
- } else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) {
- typeKind = EdmPrimitiveTypeKind.Int16;
- } else if (value >= Integer.MIN_VALUE && value <= Integer.MAX_VALUE) {
- typeKind = EdmPrimitiveTypeKind.Int32;
- } else {
- typeKind = EdmPrimitiveTypeKind.Int64;
- }
- } catch (NumberFormatException e) {
- return new LiteralImpl(ctx.getText(),
- EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal));
- }
- return new LiteralImpl(ctx.getText(),
- EdmPrimitiveTypeFactory.getInstance(typeKind));
- }
-
- @Override
- public Object visitDateLiteral(final DateLiteralContext ctx) {
- return new LiteralImpl(ctx.getText(),
- EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Date));
- }
-
- @Override
- public Object visitDatetimeoffsetLiteral(final DatetimeoffsetLiteralContext ctx) {
- return new LiteralImpl(ctx.getText(),
- EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.DateTimeOffset));
- }
-
- @Override
- public Object visitDurationLiteral(final DurationLiteralContext ctx) {
- return new LiteralImpl(ctx.getText(),
- EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Duration));
- }
-
- @Override
- public Object visitGuidLiteral(final GuidLiteralContext ctx) {
- return new LiteralImpl(ctx.getText(),
- EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Guid));
- }
-
- @Override
- public Object visitTimeofdayLiteral(final TimeofdayLiteralContext ctx) {
- return new LiteralImpl(ctx.getText(),
- EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.TimeOfDay));
- }
-
- @Override
- public Object visitQueryOptions(final QueryOptionsContext ctx) {
-
- List<QueryOptionImpl> qpList = new ArrayList<QueryOptionImpl>();
- for (QueryOptionContext entityOption : ctx.vlQO) {
- qpList.add((QueryOptionImpl) entityOption.accept(this));
- }
-
- return qpList;
- }
-
- @Override
- public Object visitRootExpr(final RootExprContext ctx) {
-
- UriResource lastResource = context.contextUriInfo.getLastResourcePart();
-
- if (!(lastResource instanceof UriResourcePartTyped)) {
- throw wrap(new UriParserSemanticException("Resource path not typed",
- UriParserSemanticException.MessageKeys.RESOURCE_PATH_NOT_TYPED));
- }
-
- UriResourcePartTyped lastType = (UriResourcePartTyped) lastResource;
-
- UriResourceRootImpl pathInfoRoot = new UriResourceRootImpl(
- ParserHelper.getTypeInformation(lastType),
- lastType.isCollection());
-
- UriInfoImpl uriInfoImplpath = new UriInfoImpl().setKind(UriInfoKind.resource);
- uriInfoImplpath.addResourcePart(pathInfoRoot);
-
- if (ctx.vPs != null) {
- // store the context uriInfoPath
- UriInfoImpl backupUriInfoPath = context.contextUriInfo;
-
- // set temporary uriInfoPath to collect the path information of the memberExpression
- context.contextUriInfo = uriInfoImplpath;
-
- ctx.vPs.accept(this);
-
- context.contextUriInfo = backupUriInfoPath;
-
- }
- return new MemberImpl(uriInfoImplpath, null);
-
- }
-
- @Override
- public Expression visitRoundMethodCallExpr(final RoundMethodCallExprContext ctx) {
- return new MethodImpl(MethodKind.ROUND, Collections.singletonList((Expression) ctx.vE1.accept(this)));
- }
-
- @Override
- public Expression visitSecondMethodCallExpr(final SecondMethodCallExprContext ctx) {
- return new MethodImpl(MethodKind.SECOND, Collections.singletonList((Expression) ctx.vE1.accept(this)));
- }
-
- @Override
- public Object visitSelect(final SelectContext ctx) {
- List<SelectItem> selectItems = new ArrayList<SelectItem>();
- for (SelectItemContext si : ctx.vlSI) {
- selectItems.add((SelectItem) si.accept(this));
- }
-
- return new SelectOptionImpl().setSelectItems(selectItems).setText(ctx.children.get(2).getText());
- }
-
- @Override
- public Object visitSelectEOF(final SelectEOFContext ctx) {
- context.contextReadingQueryPart = true;
- List<SelectItem> selectItems = new ArrayList<SelectItem>();
- for (SelectItemContext si : ctx.vlSI) {
- selectItems.add((SelectItem) si.accept(this));
- }
-
- final QueryOptionImpl result = new SelectOptionImpl().setSelectItems(selectItems).setText(ctx.getText());
- context.contextReadingQueryPart = false;
-
- return result;
- }
-
- @Override
- public Object visitSelectItem(final SelectItemContext ctx) {
- SelectItemImpl selectItem = new SelectItemImpl();
-
- context.contextSelectItem = selectItem;
- for (SelectSegmentContext si : ctx.vlSS) {
- si.accept(this);
- }
- context.contextSelectItem = null;
-
- return selectItem;
- }
-
- @Override
- public Object visitSelectSegment(final SelectSegmentContext ctx) {
-
- if (ctx.vS != null) {
- if (ctx.vNS != null) {
- String namespace = ctx.vNS.getText();
- namespace = namespace.substring(0, namespace.length() - 1);
- FullQualifiedName fullName = new FullQualifiedName(namespace, "*");
- context.contextSelectItem.addAllOperationsInSchema(fullName);
- } else {
- context.contextSelectItem.setStar(true);
- }
- return null;
- }
-
- String odi = ctx.vODI.getText();
- if (ctx.vNS == null) {
-
- EdmType prevType = null;
- if (context.contextSelectItem.getResourcePath() == null) {
- prevType = context.contextTypes.peek();
- } else {
- UriInfoImpl uriInfo = (UriInfoImpl) context.contextSelectItem.getResourcePath();
- UriResource last = uriInfo.getLastResourcePart();
-
- prevType = ParserHelper.getTypeInformation((UriResourcePartTyped) last);
- if (prevType == null) {
- throw wrap(new UriParserSemanticException("prev segment not typed",
- UriParserSemanticException.MessageKeys.ONLY_FOR_TYPED_PARTS, "select"));
- }
- }
-
- if (!(prevType instanceof EdmStructuredType)) {
- throw wrap(new UriParserSemanticException("Previous select item is not a structural type",
- UriParserSemanticException.MessageKeys.ONLY_FOR_STRUCTURAL_TYPES, "select"));
<TRUNCATED>
[2/6] olingo-odata4 git commit: [OLINGO-834] $expand parser in Java +
clean-up
Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java
index c27c960..a94026f 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java
@@ -18,29 +18,19 @@
*/
package org.apache.olingo.server.core.uri.antlr;
-import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.Collections;
import org.apache.olingo.commons.api.edm.Edm;
-import org.apache.olingo.commons.api.edm.EdmEntityContainer;
-import org.apache.olingo.commons.api.edm.EdmEntitySet;
-import org.apache.olingo.commons.api.edm.EdmEntityType;
-import org.apache.olingo.commons.api.edm.EdmKeyPropertyRef;
-import org.apache.olingo.commons.api.edm.EdmNavigationProperty;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
-import org.apache.olingo.commons.api.edm.EdmProperty;
import org.apache.olingo.commons.api.edm.FullQualifiedName;
import org.apache.olingo.commons.api.format.ContentType;
-import org.apache.olingo.commons.core.Encoder;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmString;
import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.edmx.EdmxReference;
import org.apache.olingo.server.api.uri.UriInfoKind;
import org.apache.olingo.server.api.uri.UriResourceKind;
import org.apache.olingo.server.api.uri.queryoption.expression.BinaryOperatorKind;
import org.apache.olingo.server.api.uri.queryoption.expression.MethodKind;
-import org.apache.olingo.server.core.uri.parser.UriParserException;
import org.apache.olingo.server.core.uri.parser.UriParserSemanticException.MessageKeys;
import org.apache.olingo.server.core.uri.parser.UriParserSyntaxException;
import org.apache.olingo.server.core.uri.parser.search.SearchParserException;
@@ -56,19 +46,17 @@ import org.apache.olingo.server.tecsvc.provider.EnumTypeProvider;
import org.apache.olingo.server.tecsvc.provider.FunctionProvider;
import org.apache.olingo.server.tecsvc.provider.PropertyProvider;
import org.apache.olingo.server.tecsvc.provider.TypeDefinitionProvider;
-import org.junit.Ignore;
import org.junit.Test;
-import org.mockito.Mockito;
public class TestFullResourcePath {
private static final OData oData = OData.newInstance();
+ private static final Edm edm = oData.createServiceMetadata(
+ new EdmTechProvider(), Collections.<EdmxReference> emptyList()).getEdm();
private final TestUriValidator testUri;
private final FilterValidator testFilter;
public TestFullResourcePath() {
- final Edm edm = oData.createServiceMetadata(new EdmTechProvider(), Collections.<EdmxReference> emptyList())
- .getEdm();
testUri = new TestUriValidator().setEdm(edm);
testFilter = new FilterValidator().setEdm(edm);
}
@@ -1033,16 +1021,10 @@ public class TestFullResourcePath {
public void resourcePathWithApostrophe() throws Exception {
testUri.runEx("ESAllPrim'").isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
testUri.runEx("ESAllPrim'InvalidStuff").isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
-
- testFilter.runOnETKeyNavEx("PropertyInt16' eq 0")
- .isExSyntax(UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION);
-
- testFilter.runOnETKeyNavEx("PropertyInt16 eq' 0")
- .isExSyntax(UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION);
-
+ testFilter.runOnETKeyNavEx("PropertyInt16' eq 0").isExSemantic(MessageKeys.TYPES_NOT_COMPATIBLE);
+ testFilter.runOnETKeyNavEx("PropertyInt16 eq' 0").isExSemantic(MessageKeys.TYPES_NOT_COMPATIBLE);
testFilter.runOnETKeyNavEx("PropertyInt16 eq 0'")
.isExSyntax(UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION);
-
testFilter.runOnETKeyNavEx("PropertyInt16 eq 'dsd''")
.isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
}
@@ -1306,13 +1288,13 @@ public class TestFullResourcePath {
@Test
public void runEsNameParaKeys() throws Exception {
- testUri.run(encode("ESAllKey(PropertyString='O''Neil',PropertyBoolean=true,PropertyByte=255,"
+ testUri.run("ESAllKey(PropertyString='O''Neil',PropertyBoolean=true,PropertyByte=255,"
+ "PropertySByte=-128,PropertyInt16=-32768,PropertyInt32=-2147483648,"
+ "PropertyInt64=-9223372036854775808,PropertyDecimal=1,PropertyDate=2013-09-25,"
+ "PropertyDateTimeOffset=2002-10-10T12:00:00-05:00,"
+ "PropertyDuration=duration'P50903316DT2H25M4S',"
+ "PropertyGuid=12345678-1234-1234-1234-123456789012,"
- + "PropertyTimeOfDay=12:34:55)"))
+ + "PropertyTimeOfDay=12:34:55)")
.isKind(UriInfoKind.resource).goPath()
.first()
.isEntitySet("ESAllKey")
@@ -1380,12 +1362,11 @@ public class TestFullResourcePath {
.isType(EntityTypeProvider.nameETTwoPrim)
.isTypeFilterOnCollection(EntityTypeProvider.nameETTwoBase);
- // TODO: Keys cannot be specified twice.
- //testUri.runEx("ESTwoPrim(1)/olingo.odata.test1.ETBase(1)")
- // .isExSemantic(MessageKeys.INCOMPATIBLE_TYPE_FILTER);
-
- //testUri.runEx("ESTwoPrim/olingo.odata.test1.ETBase(1)/olingo.odata.test1.ETTwoBase(1)")
- // .isExSemantic(MessageKeys.TYPE_FILTER_NOT_CHAINABLE);
+ // Keys cannot be specified twice.
+ testUri.runEx("ESTwoPrim(1)/olingo.odata.test1.ETBase(1)")
+ .isExSemantic(MessageKeys.KEY_NOT_ALLOWED);
+ testUri.runEx("ESTwoPrim/olingo.odata.test1.ETBase(1)/olingo.odata.test1.ETTwoBase(1)")
+ .isExSemantic(MessageKeys.KEY_NOT_ALLOWED);
testUri.runEx("ESBase/olingo.odata.test1.ETTwoPrim(1)").isExSemantic(MessageKeys.INCOMPATIBLE_TYPE_FILTER);
}
@@ -2321,8 +2302,7 @@ public class TestFullResourcePath {
}
@Test
- public void runExpand() throws Exception {
-
+ public void expandStar() throws Exception {
testUri.run("ESKeyNav(1)", "$expand=*")
.isKind(UriInfoKind.resource).goPath().goExpand()
.first()
@@ -2353,7 +2333,10 @@ public class TestFullResourcePath {
.first()
.isSegmentStar()
.isLevelText("max");
+ }
+ @Test
+ public void expandNavigationRef() throws Exception {
testUri.run("ESKeyNav(1)", "$expand=NavPropertyETKeyNavMany/$ref")
.isKind(UriInfoKind.resource).goPath().goExpand()
.first()
@@ -2441,7 +2424,10 @@ public class TestFullResourcePath {
.goUpExpandValidator()
.isSkipText("1")
.isTopText("3");
+ }
+ @Test
+ public void expandNavigationCount() throws Exception {
testUri.run("ESKeyNav(1)", "$expand=NavPropertyETKeyNavMany/$count")
.isKind(UriInfoKind.resource).goPath().goExpand()
.first()
@@ -2467,7 +2453,10 @@ public class TestFullResourcePath {
.n().isCount()
.goUpExpandValidator()
.isFilterSerialized("<<PropertyInt16> gt <1>>");
+ }
+ @Test
+ public void expandNavigationOptions() throws Exception {
testUri.run("ESKeyNav(1)", "$expand=NavPropertyETKeyNavMany($filter=PropertyInt16 eq 1)")
.isKind(UriInfoKind.resource).goPath().goExpand()
.first()
@@ -2521,7 +2510,6 @@ public class TestFullResourcePath {
.isNavProperty("NavPropertyETKeyNavMany", EntityTypeProvider.nameETKeyNav, true)
.isType(EntityTypeProvider.nameETKeyNav, true)
.goUpExpandValidator()
- .isSelectText("PropertyString")
.goSelectItem(0).isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false);
testUri.run("ESKeyNav(1)", "$expand=NavPropertyETKeyNavMany($expand=NavPropertyETTwoKeyNavOne)")
@@ -2562,7 +2550,6 @@ public class TestFullResourcePath {
.isNavProperty("NavPropertyETKeyNavMany", EntityTypeProvider.nameETKeyNav, true)
.isType(EntityTypeProvider.nameETKeyNav, true)
.goUpExpandValidator()
- .isSelectText("PropertyString")
.goSelectItem(0).isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false);
testUri.run("ESKeyNav(1)", "$expand=NavPropertyETKeyNavOne($levels=max)")
@@ -2594,6 +2581,12 @@ public class TestFullResourcePath {
.isSkipText("1")
.isTopText("2");
+ testUri.run("ESKeyNav(1)", "$expand=NavPropertyETKeyNavMany($search=Country AND Western)")
+ .isKind(UriInfoKind.resource).goPath().goExpand()
+ .first().goPath().first().isNavProperty("NavPropertyETKeyNavMany", EntityTypeProvider.nameETKeyNav, true)
+ .goUpExpandValidator()
+ .isSearchSerialized("{'Country' AND 'Western'}");
+
testUri.run("ESTwoKeyNav(PropertyInt16=1,PropertyString='Hugo')", "$expand=NavPropertyETKeyNavMany")
.isKind(UriInfoKind.resource).goPath()
.first()
@@ -2604,7 +2597,10 @@ public class TestFullResourcePath {
.goPath().first()
.isNavProperty("NavPropertyETKeyNavMany", EntityTypeProvider.nameETKeyNav, true)
.isType(EntityTypeProvider.nameETKeyNav, true);
+ }
+ @Test
+ public void expandTypeCasts() throws Exception {
testUri.run("ESTwoKeyNav", "$expand=olingo.odata.test1.ETBaseTwoKeyNav/NavPropertyETKeyNavMany")
.isKind(UriInfoKind.resource).goPath().first()
.goExpand().first()
@@ -2635,15 +2631,13 @@ public class TestFullResourcePath {
.isNavProperty("NavPropertyETTwoKeyNavMany", EntityTypeProvider.nameETTwoKeyNav, true);
testUri.run("ESTwoKeyNav(PropertyInt16=1,PropertyString='2')",
- "$expand=olingo.odata.test1.ETBaseTwoKeyNav"
- + "/NavPropertyETTwoKeyNavMany/olingo.odata.test1.ETTwoBaseTwoKeyNav")
+ "$expand=olingo.odata.test1.ETBaseTwoKeyNav/NavPropertyETTwoKeyNavMany/olingo.odata.test1.ETTwoBaseTwoKeyNav")
.isKind(UriInfoKind.resource).goPath().first()
.isKeyPredicate(0, "PropertyInt16", "1")
.isKeyPredicate(1, "PropertyString", "'2'")
.goExpand().first()
.isExpandStartType(EntityTypeProvider.nameETBaseTwoKeyNav)
.goPath().first()
- .isType(EntityTypeProvider.nameETTwoKeyNav)
.isNavProperty("NavPropertyETTwoKeyNavMany", EntityTypeProvider.nameETTwoKeyNav, true)
.isTypeFilterOnCollection(EntityTypeProvider.nameETTwoBaseTwoKeyNav);
@@ -2724,7 +2718,6 @@ public class TestFullResourcePath {
.isNavProperty("NavPropertyETKeyNavOne", EntityTypeProvider.nameETKeyNav, false)
.isType(EntityTypeProvider.nameETKeyNav)
.goUpExpandValidator()
- .isSelectText("PropertyInt16")
.goSelectItem(0).isPrimitiveProperty("PropertyInt16", PropertyProvider.nameInt16, false);
testUri.run("ESKeyNav", "$expand=NavPropertyETKeyNavOne($select=PropertyCompNav/PropertyInt16)")
@@ -2735,7 +2728,9 @@ public class TestFullResourcePath {
.isNavProperty("NavPropertyETKeyNavOne", EntityTypeProvider.nameETKeyNav, false)
.isType(EntityTypeProvider.nameETKeyNav)
.goUpExpandValidator()
- .isSelectText("PropertyCompNav/PropertyInt16");
+ .goSelectItem(0)
+ .first().isComplexProperty("PropertyCompNav", ComplexTypeProvider.nameCTNavFiveProp, false)
+ .n().isPrimitiveProperty("PropertyInt16", PropertyProvider.nameInt16, false);
testUri.runEx("ESKeyNav", "$expand=undefined")
.isExSemantic(MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE);
@@ -2744,7 +2739,7 @@ public class TestFullResourcePath {
}
@Test
- public void runDuplicatedSystemQueryOptionsInExpand() throws UriParserException, UriValidationException {
+ public void duplicatedSystemQueryOptionsInExpand() throws Exception {
testUri.runEx("ESKeyNav", "$expand=NavPropertyETKeyNavOne($select=PropertyInt16;$select=PropertyInt16)")
.isExSyntax(UriParserSyntaxException.MessageKeys.DOUBLE_SYSTEM_QUERY_OPTION);
@@ -2768,11 +2763,7 @@ public class TestFullResourcePath {
testUri.runEx("ESKeyNav", "$expand=NavPropertyETKeyNavOne($skip=2;$skip=2)")
.isExSyntax(UriParserSyntaxException.MessageKeys.DOUBLE_SYSTEM_QUERY_OPTION);
- }
- @Test
- @Ignore("$search in expand currently not implemented")
- public void duplicatedSearchExpand() throws Exception {
testUri.runEx("ESKeyNav", "$expand=NavPropertyETKeyNavOne($search=Test;$search=Test)")
.isExSyntax(UriParserSyntaxException.MessageKeys.DOUBLE_SYSTEM_QUERY_OPTION);
}
@@ -2906,8 +2897,7 @@ public class TestFullResourcePath {
}
@Test
- public void runTop() throws Exception {
- // top
+ public void top() throws Exception {
testUri.run("ESKeyNav", "$top=1")
.isKind(UriInfoKind.resource).goPath()
.isEntitySet("ESKeyNav")
@@ -2918,20 +2908,16 @@ public class TestFullResourcePath {
.isEntitySet("ESKeyNav")
.isTopText("0");
- testUri.run("ESKeyNav", "$top=-3")
- .isKind(UriInfoKind.resource).goPath()
- .isEntitySet("ESKeyNav")
- .isTopText("-3");
-
testUri.runEx("ESKeyNav", "$top=undefined")
.isExSyntax(UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION);
testUri.runEx("ESKeyNav", "$top=")
.isExSyntax(UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION);
+ testUri.runEx("ESKeyNav", "$top=-3")
+ .isExSyntax(UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION);
}
@Test
- public void runFormat() throws Exception {
- // format
+ public void format() throws Exception {
testUri.run("ESKeyNav(1)", "$format=atom")
.isKind(UriInfoKind.resource).goPath()
.isFormatText("atom");
@@ -2963,8 +2949,7 @@ public class TestFullResourcePath {
}
@Test
- public void runCount() throws Exception {
- // count
+ public void count() throws Exception {
testUri.run("ESAllPrim", "$count=true")
.isKind(UriInfoKind.resource).goPath()
.isInlineCountText("true");
@@ -2979,20 +2964,19 @@ public class TestFullResourcePath {
@Test
public void skip() throws Exception {
- // skip
testUri.run("ESAllPrim", "$skip=3")
.isKind(UriInfoKind.resource).goPath()
.isSkipText("3");
testUri.run("ESAllPrim", "$skip=0")
.isKind(UriInfoKind.resource).goPath()
.isSkipText("0");
- testUri.run("ESAllPrim", "$skip=-3")
- .isKind(UriInfoKind.resource).goPath()
- .isSkipText("-3");
+
testUri.runEx("ESAllPrim", "$skip=F")
.isExSyntax(UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION);
testUri.runEx("ESAllPrim", "$skip=")
.isExSyntax(UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION);
+ testUri.runEx("ESAllPrim", "$skip=-3")
+ .isExSyntax(UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION);
}
@Test
@@ -3000,6 +2984,9 @@ public class TestFullResourcePath {
testUri.run("ESAllPrim", "$skiptoken=foo")
.isKind(UriInfoKind.resource).goPath()
.isSkipTokenText("foo");
+
+ testUri.runEx("ESAllPrim", "$skiptoken=")
+ .isExSyntax(UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION);
}
@Test
@@ -3010,7 +2997,6 @@ public class TestFullResourcePath {
@Test
public void misc() throws Exception {
-
testUri.run("")
.isKind(UriInfoKind.service);
testUri.run("/")
@@ -3227,56 +3213,47 @@ public class TestFullResourcePath {
.isType(EntityTypeProvider.nameETTwoKeyNav)
.isTypeFilterOnEntry(EntityTypeProvider.nameETBaseTwoKeyNav)
.n().isValue();
-
}
- // TODO
@Test
public void filter() throws Exception {
+ testFilter.runOnETAllPrim("PropertyBoolean")
+ .is("<PropertyBoolean>")
+ .isType(PropertyProvider.nameBoolean);
- testFilter.runOnETTwoKeyNav("PropertyString")
- .is("<PropertyString>")
- .isType(PropertyProvider.nameString);
-
- testFilter.runOnETTwoKeyNav("PropertyComp/PropertyInt16")
- .is("<PropertyComp/PropertyInt16>")
- .isType(PropertyProvider.nameInt16);
+ testFilter.runOnETTwoKeyNav("PropertyComp/PropertyInt16 gt 0")
+ .is("<<PropertyComp/PropertyInt16> gt <0>>")
+ .left().isType(PropertyProvider.nameInt16);
- testFilter.runOnETTwoKeyNav("PropertyComp/PropertyComp/PropertyDate")
- .is("<PropertyComp/PropertyComp/PropertyDate>")
- .isType(PropertyProvider.nameDate);
+ testFilter.runOnETTwoKeyNav("PropertyComp/PropertyComp/PropertyDate ne null")
+ .is("<<PropertyComp/PropertyComp/PropertyDate> ne <null>>")
+ .left().isType(PropertyProvider.nameDate);
- testFilter.runOnETTwoKeyNav("NavPropertyETTwoKeyNavOne")
- .is("<NavPropertyETTwoKeyNavOne>")
- .isType(EntityTypeProvider.nameETTwoKeyNav);
+ testFilter.runOnETTwoKeyNav("NavPropertyETTwoKeyNavOne eq null")
+ .is("<<NavPropertyETTwoKeyNavOne> eq <null>>")
+ .left().isType(EntityTypeProvider.nameETTwoKeyNav);
- testFilter.runOnETTwoKeyNav("NavPropertyETTwoKeyNavOne/PropertyString")
- .is("<NavPropertyETTwoKeyNavOne/PropertyString>")
- .isType(PropertyProvider.nameString);
-
- testFilter.runOnETTwoKeyNav("NavPropertyETTwoKeyNavOne/PropertyComp")
- .is("<NavPropertyETTwoKeyNavOne/PropertyComp>")
- .isType(ComplexTypeProvider.nameCTPrimComp);
+ testFilter.runOnETTwoKeyNav("NavPropertyETTwoKeyNavOne/PropertyString eq ''")
+ .is("<<NavPropertyETTwoKeyNavOne/PropertyString> eq <''>>")
+ .left().isType(PropertyProvider.nameString);
- testFilter.runOnETTwoKeyNav("NavPropertyETTwoKeyNavOne/PropertyComp/PropertyComp")
- .is("<NavPropertyETTwoKeyNavOne/PropertyComp/PropertyComp>")
- .isType(ComplexTypeProvider.nameCTAllPrim);
+ testFilter.runOnETTwoKeyNav("NavPropertyETTwoKeyNavOne/PropertyComp eq null")
+ .is("<<NavPropertyETTwoKeyNavOne/PropertyComp> eq <null>>")
+ .left().isType(ComplexTypeProvider.nameCTPrimComp);
- testFilter.runOnETTwoKeyNav("NavPropertyETTwoKeyNavOne/PropertyComp/PropertyInt16")
- .is("<NavPropertyETTwoKeyNavOne/PropertyComp/PropertyInt16>")
- .isType(PropertyProvider.nameInt16);
+ testFilter.runOnETTwoKeyNav("NavPropertyETTwoKeyNavOne/PropertyComp/PropertyComp eq null")
+ .is("<<NavPropertyETTwoKeyNavOne/PropertyComp/PropertyComp> eq <null>>")
+ .left().isType(ComplexTypeProvider.nameCTAllPrim);
testFilter.runOnETTwoKeyNav("NavPropertyETTwoKeyNavOne/PropertyComp/PropertyInt16 eq 1")
.is("<<NavPropertyETTwoKeyNavOne/PropertyComp/PropertyInt16> eq <1>>")
- .root().left()
- .isType(PropertyProvider.nameInt16)
- .root().right()
- .isLiteral("1");
+ .left().isType(PropertyProvider.nameInt16)
+ .root().right().isLiteral("1");
testFilter.runOnETTwoKeyNav("NavPropertyETKeyNavMany(1)/NavPropertyETTwoKeyNavMany(PropertyString='2')/"
+ "PropertyString eq 'SomeString'")
.is("<<NavPropertyETKeyNavMany/NavPropertyETTwoKeyNavMany/PropertyString> eq <'SomeString'>>")
- .root().left()
+ .left()
.isType(PropertyProvider.nameString)
.isMember().goPath()
.first()
@@ -3293,7 +3270,7 @@ public class TestFullResourcePath {
testFilter.runOnETTwoKeyNav("olingo.odata.test1.ETBaseTwoKeyNav/PropertyDate eq 2013-11-12")
.is("<<PropertyDate> eq <2013-11-12>>")
- .root().left()
+ .left()
.isType(PropertyProvider.nameDate)
.isMember().isMemberStartType(EntityTypeProvider.nameETBaseTwoKeyNav).goPath()
.first().isPrimitiveProperty("PropertyDate", PropertyProvider.nameDate, false)
@@ -3303,7 +3280,7 @@ public class TestFullResourcePath {
testFilter.runOnCTTwoPrim("olingo.odata.test1.CTBase/AdditionalPropString eq 'SomeString'")
.is("<<AdditionalPropString> eq <'SomeString'>>")
- .root().left()
+ .left()
.isType(PropertyProvider.nameString)
.isMember().isMemberStartType(ComplexTypeProvider.nameCTBase).goPath()
.first().isPrimitiveProperty("AdditionalPropString", PropertyProvider.nameString, false)
@@ -3314,7 +3291,7 @@ public class TestFullResourcePath {
testFilter
.runOnETTwoKeyNav("NavPropertyETTwoKeyNavOne/olingo.odata.test1.ETBaseTwoKeyNav/PropertyDate eq 2013-11-12")
.is("<<NavPropertyETTwoKeyNavOne/olingo.odata.test1.ETBaseTwoKeyNav/PropertyDate> eq <2013-11-12>>")
- .root().left()
+ .left()
.isType(PropertyProvider.nameDate)
.root().right()
.isLiteral("2013-11-12");
@@ -3322,20 +3299,15 @@ public class TestFullResourcePath {
testFilter
.runOnETTwoKeyNav("PropertyCompTwoPrim/olingo.odata.test1.CTTwoBase/AdditionalPropString eq 'SomeString'")
.is("<<PropertyCompTwoPrim/olingo.odata.test1.CTTwoBase/AdditionalPropString> eq <'SomeString'>>")
- .root().left()
+ .left()
.isType(PropertyProvider.nameString)
.root().right()
.isLiteral("'SomeString'");
- testFilter.runOnETTwoKeyNavEx("invalid")
- .isExSemantic(MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE);
- // TODO: This should throw an exception because the top node of the filter tree must be boolean.
- // testFilter.runOnETTwoKeyNavEx("PropertyComp")
- // .isExSemantic(MessageKeys.UNKNOWN_TYPE);
- testFilter.runOnETTwoKeyNavEx("PropertyComp/invalid")
- .isExSemantic(MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE);
- testFilter.runOnETTwoKeyNavEx("concat('a','b')/invalid")
- .isExSyntax(UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION);
+ testFilter.runOnETTwoKeyNavEx("invalid").isExSemantic(MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE);
+ testFilter.runOnETTwoKeyNavEx("PropertyComp").isExSemantic(MessageKeys.TYPES_NOT_COMPATIBLE);
+ testFilter.runOnETTwoKeyNavEx("PropertyComp/invalid").isExSemantic(MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE);
+ testFilter.runOnETTwoKeyNavEx("concat('a','b')/invalid").isExSemantic(MessageKeys.TYPES_NOT_COMPATIBLE);
testFilter.runOnETTwoKeyNavEx("PropertyComp/concat('a','b')")
.isExSemantic(MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE);
testFilter.runOnETTwoKeyNavEx("PropertyComp/PropertyInt16 eq '1'")
@@ -3347,437 +3319,307 @@ public class TestFullResourcePath {
testFilter.runOnETTwoKeyNavEx("PropertyComp/PropertyInt64 eq 1")
.isExSemantic(MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE);
testFilter.runOnETTwoKeyNavEx("NavPropertyETKeyNavMany/PropertyInt16 gt 42")
- .isExSyntax(UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION);
+ .isExSemantic(MessageKeys.TYPES_NOT_COMPATIBLE);
testFilter.runOnETTwoKeyNavEx("NavPropertyETKeyNavMany/NavPropertyETTwoKeyNavOne eq null")
- .isExSyntax(UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION);
+ .isExSemantic(MessageKeys.TYPES_NOT_COMPATIBLE);
+ }
+ @Test
+ public void filterBinaryOperators() throws Exception {
testFilter.runOnETAllPrim("PropertySByte eq PropertySByte")
.is("<<PropertySByte> eq <PropertySByte>>")
.isBinary(BinaryOperatorKind.EQ)
- .root().left()
- .isType(PropertyProvider.nameSByte)
- .root().right()
- .isType(PropertyProvider.nameSByte);
+ .left().isType(PropertyProvider.nameSByte)
+ .root().right().isType(PropertyProvider.nameSByte);
testFilter.runOnETAllPrim("PropertySByte ne PropertySByte")
.is("<<PropertySByte> ne <PropertySByte>>")
.isBinary(BinaryOperatorKind.NE)
- .root().left()
- .isType(PropertyProvider.nameSByte)
- .root().right()
- .isType(PropertyProvider.nameSByte);
-
- testFilter.runOnETAllPrim("PropertySByte add PropertySByte")
- .is("<<PropertySByte> add <PropertySByte>>")
- .root().left()
- .isType(PropertyProvider.nameSByte)
- .root().right()
- .isType(PropertyProvider.nameSByte);
-
- testFilter.runOnETAllPrim("PropertyByte add PropertyByte")
- .is("<<PropertyByte> add <PropertyByte>>")
- .root().left()
- .isType(PropertyProvider.nameByte)
- .root().right()
- .isType(PropertyProvider.nameByte);
- testFilter.runOnETAllPrim("PropertyInt16 add PropertyInt16")
- .is("<<PropertyInt16> add <PropertyInt16>>")
- .root().left()
- .isType(PropertyProvider.nameInt16)
- .root().right()
- .isType(PropertyProvider.nameInt16);
- testFilter.runOnETAllPrim("PropertyInt32 add PropertyInt32")
- .is("<<PropertyInt32> add <PropertyInt32>>")
- .root().left()
- .isType(PropertyProvider.nameInt32)
- .root().right()
- .isType(PropertyProvider.nameInt32);
-
- testFilter.runOnETAllPrim("PropertyInt64 add PropertyInt64")
- .is("<<PropertyInt64> add <PropertyInt64>>")
- .root().left()
- .isType(PropertyProvider.nameInt64)
- .root().right()
- .isType(PropertyProvider.nameInt64);
- testFilter.runOnETAllPrim("PropertySingle add PropertySingle")
- .is("<<PropertySingle> add <PropertySingle>>")
- .root().left()
- .isType(PropertyProvider.nameSingle)
- .root().right()
- .isType(PropertyProvider.nameSingle);
- testFilter.runOnETAllPrim("PropertyDouble add PropertyDouble")
- .is("<<PropertyDouble> add <PropertyDouble>>")
- .root().left()
- .isType(PropertyProvider.nameDouble)
- .root().right()
- .isType(PropertyProvider.nameDouble);
- testFilter.runOnETAllPrim("PropertyDecimal add PropertyDecimal")
- .is("<<PropertyDecimal> add <PropertyDecimal>>")
- .root().left()
- .isType(PropertyProvider.nameDecimal)
- .root().right()
- .isType(PropertyProvider.nameDecimal);
- testFilter.runOnETAllPrim("PropertySByte add PropertyDecimal")
- .is("<<PropertySByte> add <PropertyDecimal>>")
- .root().left()
- .isType(PropertyProvider.nameSByte)
- .root().right()
- .isType(PropertyProvider.nameDecimal);
- testFilter.runOnETAllPrim("PropertySByte add PropertyInt32")
- .is("<<PropertySByte> add <PropertyInt32>>")
- .root().left()
- .isType(PropertyProvider.nameSByte)
- .root().right()
- .isType(PropertyProvider.nameInt32);
- testFilter.runOnETAllPrim("PropertySByte add PropertyInt64")
- .is("<<PropertySByte> add <PropertyInt64>>")
- .root().left()
- .isType(PropertyProvider.nameSByte)
- .root().right()
- .isType(PropertyProvider.nameInt64);
- testFilter.runOnETAllPrim("PropertyDateTimeOffset add PropertyDuration")
- .is("<<PropertyDateTimeOffset> add <PropertyDuration>>")
- .root().left()
- .isType(PropertyProvider.nameDateTimeOffset)
- .root().right()
- .isType(PropertyProvider.nameDuration);
- testFilter.runOnETAllPrim("PropertyDuration add PropertyDuration")
- .is("<<PropertyDuration> add <PropertyDuration>>")
- .root().left()
- .isType(PropertyProvider.nameDuration)
- .root().right()
- .isType(PropertyProvider.nameDuration);
- testFilter.runOnETAllPrim("PropertyDate add PropertyDuration")
- .is("<<PropertyDate> add <PropertyDuration>>")
- .root().left()
- .isType(PropertyProvider.nameDate)
- .root().right()
- .isType(PropertyProvider.nameDuration);
- testFilter.runOnETAllPrim("PropertySByte sub PropertySByte")
- .is("<<PropertySByte> sub <PropertySByte>>")
- .root().left()
- .isType(PropertyProvider.nameSByte)
- .root().right()
- .isType(PropertyProvider.nameSByte);
- testFilter.runOnETAllPrim("PropertyByte sub PropertyByte")
- .is("<<PropertyByte> sub <PropertyByte>>")
- .root().left()
- .isType(PropertyProvider.nameByte)
- .root().right()
- .isType(PropertyProvider.nameByte);
- testFilter.runOnETAllPrim("PropertyInt16 sub PropertyInt16")
- .is("<<PropertyInt16> sub <PropertyInt16>>")
- .root().left()
- .isType(PropertyProvider.nameInt16)
- .root().right()
- .isType(PropertyProvider.nameInt16);
- testFilter.runOnETAllPrim("PropertyInt32 sub PropertyInt32")
- .is("<<PropertyInt32> sub <PropertyInt32>>")
- .root().left()
- .isType(PropertyProvider.nameInt32)
- .root().right()
- .isType(PropertyProvider.nameInt32);
- testFilter.runOnETAllPrim("PropertyInt64 sub PropertyInt64")
- .is("<<PropertyInt64> sub <PropertyInt64>>")
- .root().left()
- .isType(PropertyProvider.nameInt64)
- .root().right()
- .isType(PropertyProvider.nameInt64);
- testFilter.runOnETAllPrim("PropertySingle sub PropertySingle")
- .is("<<PropertySingle> sub <PropertySingle>>")
- .root().left()
- .isType(PropertyProvider.nameSingle)
- .root().right()
- .isType(PropertyProvider.nameSingle);
- testFilter.runOnETAllPrim("PropertyDouble sub PropertyDouble")
- .is("<<PropertyDouble> sub <PropertyDouble>>")
- .root().left()
- .isType(PropertyProvider.nameDouble)
- .root().right()
- .isType(PropertyProvider.nameDouble);
- testFilter.runOnETAllPrim("PropertyDecimal sub PropertyDecimal")
- .is("<<PropertyDecimal> sub <PropertyDecimal>>")
- .root().left()
- .isType(PropertyProvider.nameDecimal)
- .root().right()
- .isType(PropertyProvider.nameDecimal);
- testFilter.runOnETAllPrim("PropertyDecimal sub PropertyInt32")
- .is("<<PropertyDecimal> sub <PropertyInt32>>")
- .root().left()
- .isType(PropertyProvider.nameDecimal)
- .root().right()
- .isType(PropertyProvider.nameInt32);
- testFilter.runOnETAllPrim("PropertyDecimal sub PropertyInt64")
- .is("<<PropertyDecimal> sub <PropertyInt64>>")
- .root().left()
- .isType(PropertyProvider.nameDecimal)
- .root().right()
- .isType(PropertyProvider.nameInt64);
- testFilter.runOnETAllPrim("PropertyDecimal sub PropertyByte")
- .is("<<PropertyDecimal> sub <PropertyByte>>")
- .root().left()
- .isType(PropertyProvider.nameDecimal)
- .root().right()
- .isType(PropertyProvider.nameByte);
- testFilter.runOnETAllPrim("PropertyDateTimeOffset sub PropertyDuration")
- .is("<<PropertyDateTimeOffset> sub <PropertyDuration>>")
- .root().left()
- .isType(PropertyProvider.nameDateTimeOffset)
- .root().right()
- .isType(PropertyProvider.nameDuration);
- testFilter.runOnETAllPrim("PropertyDuration sub PropertyDuration")
- .is("<<PropertyDuration> sub <PropertyDuration>>")
- .root().left()
- .isType(PropertyProvider.nameDuration)
- .root().right()
- .isType(PropertyProvider.nameDuration);
- testFilter.runOnETAllPrim("PropertyDateTimeOffset sub PropertyDateTimeOffset")
- .is("<<PropertyDateTimeOffset> sub <PropertyDateTimeOffset>>")
- .root().left()
- .isType(PropertyProvider.nameDateTimeOffset)
- .root().right()
- .isType(PropertyProvider.nameDateTimeOffset);
- testFilter.runOnETAllPrim("PropertyDate sub PropertyDuration")
- .is("<<PropertyDate> sub <PropertyDuration>>")
- .root().left()
- .isType(PropertyProvider.nameDate)
- .root().right()
- .isType(PropertyProvider.nameDuration);
- testFilter.runOnETAllPrim("PropertyDate sub PropertyDate")
- .is("<<PropertyDate> sub <PropertyDate>>")
- .root().left()
- .isType(PropertyProvider.nameDate)
- .root().right()
- .isType(PropertyProvider.nameDate);
- testFilter.runOnETAllPrim("PropertySByte mul PropertySByte")
- .is("<<PropertySByte> mul <PropertySByte>>")
- .root().left()
- .isType(PropertyProvider.nameSByte)
- .root().right()
- .isType(PropertyProvider.nameSByte);
- testFilter.runOnETAllPrim("PropertyByte mul PropertyByte")
- .is("<<PropertyByte> mul <PropertyByte>>")
- .root().left()
- .isType(PropertyProvider.nameByte)
- .root().right()
- .isType(PropertyProvider.nameByte);
- testFilter.runOnETAllPrim("PropertyInt16 mul PropertyInt16")
- .is("<<PropertyInt16> mul <PropertyInt16>>")
- .root().left()
- .isType(PropertyProvider.nameInt16)
- .root().right()
- .isType(PropertyProvider.nameInt16);
- testFilter.runOnETAllPrim("PropertyInt32 mul PropertyInt32")
- .is("<<PropertyInt32> mul <PropertyInt32>>")
- .root().left()
- .isType(PropertyProvider.nameInt32)
- .root().right()
- .isType(PropertyProvider.nameInt32);
- testFilter.runOnETAllPrim("PropertyInt64 mul PropertyInt64")
- .is("<<PropertyInt64> mul <PropertyInt64>>")
- .root().left()
- .isType(PropertyProvider.nameInt64)
- .root().right()
- .isType(PropertyProvider.nameInt64);
- testFilter.runOnETAllPrim("PropertySingle mul PropertySingle")
- .is("<<PropertySingle> mul <PropertySingle>>")
- .root().left()
- .isType(PropertyProvider.nameSingle)
- .root().right()
- .isType(PropertyProvider.nameSingle);
- testFilter.runOnETAllPrim("PropertyDouble mul PropertyDouble")
- .is("<<PropertyDouble> mul <PropertyDouble>>")
- .root().left()
- .isType(PropertyProvider.nameDouble)
- .root().right()
- .isType(PropertyProvider.nameDouble);
- testFilter.runOnETAllPrim("PropertyDecimal mul PropertyDecimal")
- .is("<<PropertyDecimal> mul <PropertyDecimal>>")
- .root().left()
- .isType(PropertyProvider.nameDecimal)
- .root().right()
- .isType(PropertyProvider.nameDecimal);
- testFilter.runOnETAllPrim("PropertyInt64 mul PropertyInt32")
- .is("<<PropertyInt64> mul <PropertyInt32>>")
- .root().left()
- .isType(PropertyProvider.nameInt64)
- .root().right()
- .isType(PropertyProvider.nameInt32);
- testFilter.runOnETAllPrim("PropertyInt64 mul PropertySByte")
- .is("<<PropertyInt64> mul <PropertySByte>>")
- .root().left()
- .isType(PropertyProvider.nameInt64)
- .root().right()
- .isType(PropertyProvider.nameSByte);
- testFilter.runOnETAllPrim("PropertyInt64 mul PropertyDecimal")
- .is("<<PropertyInt64> mul <PropertyDecimal>>")
- .root().left()
- .isType(PropertyProvider.nameInt64)
- .root().right()
- .isType(PropertyProvider.nameDecimal);
- testFilter.runOnETAllPrim("PropertySByte div PropertySByte")
- .is("<<PropertySByte> div <PropertySByte>>")
- .root().left()
- .isType(PropertyProvider.nameSByte)
- .root().right()
- .isType(PropertyProvider.nameSByte);
- testFilter.runOnETAllPrim("PropertyByte div PropertyByte")
- .is("<<PropertyByte> div <PropertyByte>>")
- .root().left()
- .isType(PropertyProvider.nameByte)
- .root().right()
- .isType(PropertyProvider.nameByte);
- testFilter.runOnETAllPrim("PropertyInt16 div PropertyInt16")
- .is("<<PropertyInt16> div <PropertyInt16>>")
- .root().left()
- .isType(PropertyProvider.nameInt16)
- .root().right()
- .isType(PropertyProvider.nameInt16);
- testFilter.runOnETAllPrim("PropertyInt32 div PropertyInt32")
- .is("<<PropertyInt32> div <PropertyInt32>>")
- .root().left()
- .isType(PropertyProvider.nameInt32)
- .root().right()
- .isType(PropertyProvider.nameInt32);
- testFilter.runOnETAllPrim("PropertyInt64 div PropertyInt64")
- .is("<<PropertyInt64> div <PropertyInt64>>")
- .root().left()
- .isType(PropertyProvider.nameInt64)
- .root().right()
- .isType(PropertyProvider.nameInt64);
- testFilter.runOnETAllPrim("PropertySingle div PropertySingle")
- .is("<<PropertySingle> div <PropertySingle>>")
- .root().left()
- .isType(PropertyProvider.nameSingle)
- .root().right()
- .isType(PropertyProvider.nameSingle);
- testFilter.runOnETAllPrim("PropertyDouble div PropertyDouble")
- .is("<<PropertyDouble> div <PropertyDouble>>")
- .root().left()
- .isType(PropertyProvider.nameDouble)
- .root().right()
- .isType(PropertyProvider.nameDouble);
- testFilter.runOnETAllPrim("PropertyDecimal div PropertyDecimal")
- .is("<<PropertyDecimal> div <PropertyDecimal>>")
- .root().left()
- .isType(PropertyProvider.nameDecimal)
- .root().right()
- .isType(PropertyProvider.nameDecimal);
- testFilter.runOnETAllPrim("PropertyByte div PropertyInt32")
- .is("<<PropertyByte> div <PropertyInt32>>")
- .root().left()
- .isType(PropertyProvider.nameByte)
- .root().right()
- .isType(PropertyProvider.nameInt32);
- testFilter.runOnETAllPrim("PropertyByte div PropertyDecimal")
- .is("<<PropertyByte> div <PropertyDecimal>>")
- .root().left()
- .isType(PropertyProvider.nameByte)
- .root().right()
- .isType(PropertyProvider.nameDecimal);
- testFilter.runOnETAllPrim("PropertyByte div PropertySByte")
- .is("<<PropertyByte> div <PropertySByte>>")
- .root().left()
- .isType(PropertyProvider.nameByte)
- .root().right()
- .isType(PropertyProvider.nameSByte);
-
- testFilter.runOnETAllPrim("PropertyByte div 0")
- .is("<<PropertyByte> div <0>>");
-
- testFilter.runOnETAllPrim("0 div 0")
- .is("<<0> div <0>>");
-
- testFilter.runOnETAllPrim("PropertySByte mod PropertySByte")
- .is("<<PropertySByte> mod <PropertySByte>>")
- .root().left()
- .isType(PropertyProvider.nameSByte)
- .root().right()
- .isType(PropertyProvider.nameSByte);
- testFilter.runOnETAllPrim("PropertyByte mod PropertyByte")
- .is("<<PropertyByte> mod <PropertyByte>>")
- .root().left()
- .isType(PropertyProvider.nameByte)
- .root().right()
- .isType(PropertyProvider.nameByte);
- testFilter.runOnETAllPrim("PropertyInt16 mod PropertyInt16")
- .is("<<PropertyInt16> mod <PropertyInt16>>")
- .root().left()
- .isType(PropertyProvider.nameInt16)
- .root().right()
- .isType(PropertyProvider.nameInt16);
- testFilter.runOnETAllPrim("PropertyInt32 mod PropertyInt32")
- .is("<<PropertyInt32> mod <PropertyInt32>>")
- .root().left()
- .isType(PropertyProvider.nameInt32)
- .root().right()
- .isType(PropertyProvider.nameInt32);
- testFilter.runOnETAllPrim("PropertyInt64 mod PropertyInt64")
- .is("<<PropertyInt64> mod <PropertyInt64>>")
- .root().left()
- .isType(PropertyProvider.nameInt64)
- .root().right()
- .isType(PropertyProvider.nameInt64);
- testFilter.runOnETAllPrim("PropertySingle mod PropertySingle")
- .is("<<PropertySingle> mod <PropertySingle>>")
- .root().left()
- .isType(PropertyProvider.nameSingle)
- .root().right()
- .isType(PropertyProvider.nameSingle);
- testFilter.runOnETAllPrim("PropertyDouble mod PropertyDouble")
- .is("<<PropertyDouble> mod <PropertyDouble>>")
- .root().left()
- .isType(PropertyProvider.nameDouble)
- .root().right()
- .isType(PropertyProvider.nameDouble);
- testFilter.runOnETAllPrim("PropertyDecimal mod PropertyDecimal")
- .is("<<PropertyDecimal> mod <PropertyDecimal>>")
- .root().left()
- .isType(PropertyProvider.nameDecimal)
- .root().right()
- .isType(PropertyProvider.nameDecimal);
+ .left().isType(PropertyProvider.nameSByte)
+ .root().right().isType(PropertyProvider.nameSByte);
+
+ testFilter.runOnETAllPrim("PropertySByte add PropertySByte gt 0")
+ .is("<<<PropertySByte> add <PropertySByte>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameSByte)
+ .root().left().right().isType(PropertyProvider.nameSByte);
+
+ testFilter.runOnETAllPrim("PropertyByte add PropertyByte gt 0")
+ .is("<<<PropertyByte> add <PropertyByte>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameByte)
+ .root().left().right().isType(PropertyProvider.nameByte);
+ testFilter.runOnETAllPrim("PropertyInt16 add PropertyInt16 gt 0")
+ .is("<<<PropertyInt16> add <PropertyInt16>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameInt16)
+ .root().left().right().isType(PropertyProvider.nameInt16);
+ testFilter.runOnETAllPrim("PropertyInt32 add PropertyInt32 gt 0")
+ .is("<<<PropertyInt32> add <PropertyInt32>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameInt32)
+ .root().left().right().isType(PropertyProvider.nameInt32);
+ testFilter.runOnETAllPrim("PropertyInt64 add PropertyInt64 gt 0")
+ .is("<<<PropertyInt64> add <PropertyInt64>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameInt64)
+ .root().left().right().isType(PropertyProvider.nameInt64);
+ testFilter.runOnETAllPrim("PropertySingle add PropertySingle gt 0")
+ .is("<<<PropertySingle> add <PropertySingle>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameSingle)
+ .root().left().right().isType(PropertyProvider.nameSingle);
+ testFilter.runOnETAllPrim("PropertyDouble add PropertyDouble gt 0")
+ .is("<<<PropertyDouble> add <PropertyDouble>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameDouble)
+ .root().left().right().isType(PropertyProvider.nameDouble);
+ testFilter.runOnETAllPrim("PropertyDecimal add PropertyDecimal gt 0")
+ .is("<<<PropertyDecimal> add <PropertyDecimal>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameDecimal)
+ .root().left().right().isType(PropertyProvider.nameDecimal);
+ testFilter.runOnETAllPrim("PropertySByte add PropertyDecimal gt 0")
+ .is("<<<PropertySByte> add <PropertyDecimal>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameSByte)
+ .root().left().right().isType(PropertyProvider.nameDecimal);
+ testFilter.runOnETAllPrim("PropertySByte add PropertyInt32 gt 0")
+ .is("<<<PropertySByte> add <PropertyInt32>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameSByte)
+ .root().left().right().isType(PropertyProvider.nameInt32);
+ testFilter.runOnETAllPrim("PropertySByte add PropertyInt64 gt 0")
+ .is("<<<PropertySByte> add <PropertyInt64>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameSByte)
+ .root().left().right().isType(PropertyProvider.nameInt64);
+ testFilter.runOnETAllPrim("PropertyDateTimeOffset add PropertyDuration ne null")
+ .is("<<<PropertyDateTimeOffset> add <PropertyDuration>> ne <null>>")
+ .left().left().isType(PropertyProvider.nameDateTimeOffset)
+ .root().left().right().isType(PropertyProvider.nameDuration);
+ testFilter.runOnETAllPrim("PropertyDuration add PropertyDuration ne null")
+ .is("<<<PropertyDuration> add <PropertyDuration>> ne <null>>")
+ .left().left().isType(PropertyProvider.nameDuration)
+ .root().left().right().isType(PropertyProvider.nameDuration);
+ testFilter.runOnETAllPrim("PropertyDate add PropertyDuration ne null")
+ .is("<<<PropertyDate> add <PropertyDuration>> ne <null>>")
+ .left().left().isType(PropertyProvider.nameDate)
+ .root().left().right().isType(PropertyProvider.nameDuration);
+ testFilter.runOnETAllPrim("PropertySByte sub PropertySByte gt 0")
+ .is("<<<PropertySByte> sub <PropertySByte>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameSByte)
+ .root().left().right().isType(PropertyProvider.nameSByte);
+ testFilter.runOnETAllPrim("PropertyByte sub PropertyByte gt 0")
+ .is("<<<PropertyByte> sub <PropertyByte>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameByte)
+ .root().left().right().isType(PropertyProvider.nameByte);
+ testFilter.runOnETAllPrim("PropertyInt16 sub PropertyInt16 gt 0")
+ .is("<<<PropertyInt16> sub <PropertyInt16>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameInt16)
+ .root().left().right().isType(PropertyProvider.nameInt16);
+ testFilter.runOnETAllPrim("PropertyInt32 sub PropertyInt32 gt 0")
+ .is("<<<PropertyInt32> sub <PropertyInt32>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameInt32)
+ .root().left().right().isType(PropertyProvider.nameInt32);
+ testFilter.runOnETAllPrim("PropertyInt64 sub PropertyInt64 gt 0")
+ .is("<<<PropertyInt64> sub <PropertyInt64>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameInt64)
+ .root().left().right().isType(PropertyProvider.nameInt64);
+ testFilter.runOnETAllPrim("PropertySingle sub PropertySingle gt 0")
+ .is("<<<PropertySingle> sub <PropertySingle>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameSingle)
+ .root().left().right().isType(PropertyProvider.nameSingle);
+ testFilter.runOnETAllPrim("PropertyDouble sub PropertyDouble gt 0")
+ .is("<<<PropertyDouble> sub <PropertyDouble>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameDouble)
+ .root().left().right().isType(PropertyProvider.nameDouble);
+ testFilter.runOnETAllPrim("PropertyDecimal sub PropertyDecimal gt 0")
+ .is("<<<PropertyDecimal> sub <PropertyDecimal>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameDecimal)
+ .root().left().right().isType(PropertyProvider.nameDecimal);
+ testFilter.runOnETAllPrim("PropertyDecimal sub PropertyInt32 gt 0")
+ .is("<<<PropertyDecimal> sub <PropertyInt32>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameDecimal)
+ .root().left().right().isType(PropertyProvider.nameInt32);
+ testFilter.runOnETAllPrim("PropertyDecimal sub PropertyInt64 gt 0")
+ .is("<<<PropertyDecimal> sub <PropertyInt64>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameDecimal)
+ .root().left().right().isType(PropertyProvider.nameInt64);
+ testFilter.runOnETAllPrim("PropertyDecimal sub PropertyByte gt 0")
+ .is("<<<PropertyDecimal> sub <PropertyByte>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameDecimal)
+ .root().left().right().isType(PropertyProvider.nameByte);
+ testFilter.runOnETAllPrim("PropertyDateTimeOffset sub PropertyDuration ne null")
+ .is("<<<PropertyDateTimeOffset> sub <PropertyDuration>> ne <null>>")
+ .left().left().isType(PropertyProvider.nameDateTimeOffset)
+ .root().left().right().isType(PropertyProvider.nameDuration);
+ testFilter.runOnETAllPrim("PropertyDuration sub PropertyDuration ne null")
+ .is("<<<PropertyDuration> sub <PropertyDuration>> ne <null>>")
+ .left().left().isType(PropertyProvider.nameDuration)
+ .root().left().right().isType(PropertyProvider.nameDuration);
+ testFilter.runOnETAllPrim("PropertyDateTimeOffset sub PropertyDateTimeOffset ne null")
+ .is("<<<PropertyDateTimeOffset> sub <PropertyDateTimeOffset>> ne <null>>")
+ .left().left().isType(PropertyProvider.nameDateTimeOffset)
+ .root().left().right().isType(PropertyProvider.nameDateTimeOffset);
+ testFilter.runOnETAllPrim("PropertyDate sub PropertyDuration ne null")
+ .is("<<<PropertyDate> sub <PropertyDuration>> ne <null>>")
+ .left().left().isType(PropertyProvider.nameDate)
+ .root().left().right().isType(PropertyProvider.nameDuration);
+ testFilter.runOnETAllPrim("PropertyDate sub PropertyDate ne null")
+ .is("<<<PropertyDate> sub <PropertyDate>> ne <null>>")
+ .left().left().isType(PropertyProvider.nameDate)
+ .root().left().right().isType(PropertyProvider.nameDate);
+ testFilter.runOnETAllPrim("PropertySByte mul PropertySByte gt 0")
+ .is("<<<PropertySByte> mul <PropertySByte>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameSByte)
+ .root().left().right().isType(PropertyProvider.nameSByte);
+ testFilter.runOnETAllPrim("PropertyByte mul PropertyByte gt 0")
+ .is("<<<PropertyByte> mul <PropertyByte>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameByte)
+ .root().left().right().isType(PropertyProvider.nameByte);
+ testFilter.runOnETAllPrim("PropertyInt16 mul PropertyInt16 gt 0")
+ .is("<<<PropertyInt16> mul <PropertyInt16>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameInt16)
+ .root().left().right().isType(PropertyProvider.nameInt16);
+ testFilter.runOnETAllPrim("PropertyInt32 mul PropertyInt32 gt 0")
+ .is("<<<PropertyInt32> mul <PropertyInt32>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameInt32)
+ .root().left().right().isType(PropertyProvider.nameInt32);
+ testFilter.runOnETAllPrim("PropertyInt64 mul PropertyInt64 gt 0")
+ .is("<<<PropertyInt64> mul <PropertyInt64>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameInt64)
+ .root().left().right().isType(PropertyProvider.nameInt64);
+ testFilter.runOnETAllPrim("PropertySingle mul PropertySingle gt 0")
+ .is("<<<PropertySingle> mul <PropertySingle>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameSingle)
+ .root().left().right().isType(PropertyProvider.nameSingle);
+ testFilter.runOnETAllPrim("PropertyDouble mul PropertyDouble gt 0")
+ .is("<<<PropertyDouble> mul <PropertyDouble>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameDouble)
+ .root().left().right().isType(PropertyProvider.nameDouble);
+ testFilter.runOnETAllPrim("PropertyDecimal mul PropertyDecimal gt 0")
+ .is("<<<PropertyDecimal> mul <PropertyDecimal>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameDecimal)
+ .root().left().right().isType(PropertyProvider.nameDecimal);
+ testFilter.runOnETAllPrim("PropertyInt64 mul PropertyInt32 gt 0")
+ .is("<<<PropertyInt64> mul <PropertyInt32>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameInt64)
+ .root().left().right().isType(PropertyProvider.nameInt32);
+ testFilter.runOnETAllPrim("PropertyInt64 mul PropertySByte gt 0")
+ .is("<<<PropertyInt64> mul <PropertySByte>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameInt64)
+ .root().left().right().isType(PropertyProvider.nameSByte);
+ testFilter.runOnETAllPrim("PropertyInt64 mul PropertyDecimal gt 0")
+ .is("<<<PropertyInt64> mul <PropertyDecimal>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameInt64)
+ .root().left().right().isType(PropertyProvider.nameDecimal);
+ testFilter.runOnETAllPrim("PropertySByte div PropertySByte gt 0")
+ .is("<<<PropertySByte> div <PropertySByte>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameSByte)
+ .root().left().right().isType(PropertyProvider.nameSByte);
+ testFilter.runOnETAllPrim("PropertyByte div PropertyByte gt 0")
+ .is("<<<PropertyByte> div <PropertyByte>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameByte)
+ .root().left().right().isType(PropertyProvider.nameByte);
+ testFilter.runOnETAllPrim("PropertyInt16 div PropertyInt16 gt 0")
+ .is("<<<PropertyInt16> div <PropertyInt16>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameInt16)
+ .root().left().right().isType(PropertyProvider.nameInt16);
+ testFilter.runOnETAllPrim("PropertyInt32 div PropertyInt32 gt 0")
+ .is("<<<PropertyInt32> div <PropertyInt32>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameInt32)
+ .root().left().right().isType(PropertyProvider.nameInt32);
+ testFilter.runOnETAllPrim("PropertyInt64 div PropertyInt64 gt 0")
+ .is("<<<PropertyInt64> div <PropertyInt64>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameInt64)
+ .root().left().right().isType(PropertyProvider.nameInt64);
+ testFilter.runOnETAllPrim("PropertySingle div PropertySingle gt 0")
+ .is("<<<PropertySingle> div <PropertySingle>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameSingle)
+ .root().left().right().isType(PropertyProvider.nameSingle);
+ testFilter.runOnETAllPrim("PropertyDouble div PropertyDouble gt 0")
+ .is("<<<PropertyDouble> div <PropertyDouble>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameDouble)
+ .root().left().right().isType(PropertyProvider.nameDouble);
+ testFilter.runOnETAllPrim("PropertyDecimal div PropertyDecimal gt 0")
+ .is("<<<PropertyDecimal> div <PropertyDecimal>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameDecimal)
+ .root().left().right().isType(PropertyProvider.nameDecimal);
+ testFilter.runOnETAllPrim("PropertyByte div PropertyInt32 gt 0")
+ .is("<<<PropertyByte> div <PropertyInt32>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameByte)
+ .root().left().right().isType(PropertyProvider.nameInt32);
+ testFilter.runOnETAllPrim("PropertyByte div PropertyDecimal gt 0")
+ .is("<<<PropertyByte> div <PropertyDecimal>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameByte)
+ .root().left().right().isType(PropertyProvider.nameDecimal);
+ testFilter.runOnETAllPrim("PropertyByte div PropertySByte gt 0")
+ .is("<<<PropertyByte> div <PropertySByte>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameByte)
+ .root().left().right().isType(PropertyProvider.nameSByte);
+
+ testFilter.runOnETAllPrim("PropertyByte div 0 gt 0")
+ .is("<<<PropertyByte> div <0>> gt <0>>");
+
+ testFilter.runOnETAllPrim("0 div 0 gt 0")
+ .is("<<<0> div <0>> gt <0>>");
+
+ testFilter.runOnETAllPrim("PropertySByte mod PropertySByte gt 0")
+ .is("<<<PropertySByte> mod <PropertySByte>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameSByte)
+ .root().left().right().isType(PropertyProvider.nameSByte);
+ testFilter.runOnETAllPrim("PropertyByte mod PropertyByte gt 0")
+ .is("<<<PropertyByte> mod <PropertyByte>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameByte)
+ .root().left().right().isType(PropertyProvider.nameByte);
+ testFilter.runOnETAllPrim("PropertyInt16 mod PropertyInt16 gt 0")
+ .is("<<<PropertyInt16> mod <PropertyInt16>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameInt16)
+ .root().left().right().isType(PropertyProvider.nameInt16);
+ testFilter.runOnETAllPrim("PropertyInt32 mod PropertyInt32 gt 0")
+ .is("<<<PropertyInt32> mod <PropertyInt32>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameInt32)
+ .root().left().right().isType(PropertyProvider.nameInt32);
+ testFilter.runOnETAllPrim("PropertyInt64 mod PropertyInt64 gt 0")
+ .is("<<<PropertyInt64> mod <PropertyInt64>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameInt64)
+ .root().left().right().isType(PropertyProvider.nameInt64);
+ testFilter.runOnETAllPrim("PropertySingle mod PropertySingle gt 0")
+ .is("<<<PropertySingle> mod <PropertySingle>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameSingle)
+ .root().left().right().isType(PropertyProvider.nameSingle);
+ testFilter.runOnETAllPrim("PropertyDouble mod PropertyDouble gt 0")
+ .is("<<<PropertyDouble> mod <PropertyDouble>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameDouble)
+ .root().left().right().isType(PropertyProvider.nameDouble);
+ testFilter.runOnETAllPrim("PropertyDecimal mod PropertyDecimal gt 0")
+ .is("<<<PropertyDecimal> mod <PropertyDecimal>> gt <0>>")
+ .left().left().isType(PropertyProvider.nameDecimal)
+ .root().left().right().isType(PropertyProvider.nameDecimal);
testFilter.runOnETAllPrim("PropertyDecimal ge PropertyDecimal")
.is("<<PropertyDecimal> ge <PropertyDecimal>>")
.isBinary(BinaryOperatorKind.GE)
- .root().left()
- .isType(PropertyProvider.nameDecimal)
- .root().right()
- .isType(PropertyProvider.nameDecimal);
+ .left().isType(PropertyProvider.nameDecimal)
+ .root().right().isType(PropertyProvider.nameDecimal);
testFilter.runOnETAllPrim("PropertyDecimal lt PropertyDecimal")
.is("<<PropertyDecimal> lt <PropertyDecimal>>")
.isBinary(BinaryOperatorKind.LT)
- .root().left()
- .isType(PropertyProvider.nameDecimal)
- .root().right()
- .isType(PropertyProvider.nameDecimal);
+ .left().isType(PropertyProvider.nameDecimal)
+ .root().right().isType(PropertyProvider.nameDecimal);
testFilter.runOnETAllPrim("PropertyDecimal le PropertyDecimal")
.is("<<PropertyDecimal> le <PropertyDecimal>>")
.isBinary(BinaryOperatorKind.LE)
- .root().left()
- .isType(PropertyProvider.nameDecimal)
- .root().right()
- .isType(PropertyProvider.nameDecimal);
+ .left().isType(PropertyProvider.nameDecimal)
+ .root().right().isType(PropertyProvider.nameDecimal);
- // Numeric promotion: Double is considered the widest type
- testFilter.runOnETAllPrim("PropertyDecimal sub NaN")
+ // Numeric promotion: Double is considered the widest type.
+ testFilter.runOnETAllPrim("PropertyDecimal ne NaN")
.right().isLiteral("NaN").isType(PropertyProvider.nameDouble);
- testFilter.runOnETAllPrim("PropertyDecimal sub -INF")
+ testFilter.runOnETAllPrim("PropertyDecimal gt -INF")
.right().isLiteral("-INF").isType(PropertyProvider.nameDouble);
- testFilter.runOnETAllPrim("PropertyDecimal sub INF")
+ testFilter.runOnETAllPrim("PropertyDecimal lt INF")
.right().isLiteral("INF").isType(PropertyProvider.nameDouble);
}
- // TODO
@Test
- @Ignore
public void filterProperties() throws Exception {
testFilter.runOnETAllPrim("PropertyBoolean eq true")
.is("<<PropertyBoolean> eq <true>>")
.isBinary(BinaryOperatorKind.EQ)
.root().left().goPath().isPrimitiveProperty("PropertyBoolean", PropertyProvider.nameBoolean, false)
.goUpFilterValidator()
- .root().right().isTrue();
+ .root().right().isLiteral("true");
testFilter.runOnETAllPrim("PropertyDecimal eq 1.25")
.is("<<PropertyDecimal> eq <1.25>>")
@@ -3917,37 +3759,43 @@ public class TestFullResourcePath {
.first().isComplex("PropertyCompMixedEnumDef")
.n().isPrimitiveProperty("PropertyEnumString", EnumTypeProvider.nameENString, false);
- testFilter.runOnETAllPrim("PropertyByte mod 0")
- .is("<<PropertyByte> mod <0>>");
+ testFilter.runOnETAllPrim("PropertyByte mod 0 gt 0")
+ .is("<<<PropertyByte> mod <0>> gt <0>>");
+ }
- testFilter.runOnETAllPrim("olingo.odata.test1.UFCRTETTwoKeyNavParamCTTwoPrim(ParameterCTTwoPrim=@ParamAlias)")
- .is("<UFCRTETTwoKeyNavParamCTTwoPrim>")
- .goPath()
+ @Test
+ public void filterFunctions() throws Exception {
+ testFilter.runOnETAllPrim(
+ "olingo.odata.test1.UFCRTETTwoKeyNavParamCTTwoPrim(ParameterCTTwoPrim=@ParamAlias) eq null")
+ .is("<<UFCRTETTwoKeyNavParamCTTwoPrim> eq <null>>")
+ .left().goPath()
.first()
.isFunction("UFCRTETTwoKeyNavParamCTTwoPrim")
.isParameterAlias(0, "ParameterCTTwoPrim", "@ParamAlias");
- testFilter.runOnETTwoKeyNav("PropertyComp/olingo.odata.test1.BFCCTPrimCompRTESTwoKeyNavParam"
- + "(ParameterString=PropertyComp/PropertyComp/PropertyString)(PropertyInt16=1,PropertyString='2')"
- + "/PropertyString eq 'SomeString'")
- .is("<<PropertyComp/BFCCTPrimCompRTESTwoKeyNavParam/PropertyString> eq <'SomeString'>>")
+ testFilter.runOnETTwoKeyNav("PropertyComp/olingo.odata.test1.BFCCTPrimCompRTETTwoKeyNavParam"
+ + "(ParameterString=PropertyComp/PropertyComp/PropertyString)/PropertyString eq 'SomeString'")
+ .is("<<PropertyComp/BFCCTPrimCompRTETTwoKeyNavParam/PropertyString> eq <'SomeString'>>")
.root().left().goPath()
- .first()
- .isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTPrimComp, false)
- .n()
- .isFunction("BFCCTPrimCompRTESTwoKeyNavParam")
- .isParameter(0, "ParameterString", "PropertyComp/PropertyComp/PropertyString")
- .goParameter(0)
- .isMember()
+ .first().isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTPrimComp, false)
+ .n().isFunction("BFCCTPrimCompRTETTwoKeyNavParam")
+ .goParameter(0).isMember()
.goPath()
- .first().isComplex("PropertyComp")
- .n().isComplex("PropertyComp")
- .n().isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false).goUpFilterValidator()
- .goUpToResourceValidator()
+ .first().isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTPrimComp, false)
+ .n().isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTAllPrim, false)
+ .n().isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false)
+ .goUpFilterValidator().goUpToResourceValidator()
+ .n().isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false);
+
+ testFilter.runOnETTwoKeyNav("PropertyComp/olingo.odata.test1.BFCCTPrimCompRTESTwoKeyNav()"
+ + "(PropertyInt16=1,PropertyString='2')/PropertyString eq 'SomeString'")
+ .is("<<PropertyComp/BFCCTPrimCompRTESTwoKeyNav/PropertyString> eq <'SomeString'>>")
+ .root().left().goPath()
+ .first().isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTPrimComp, false)
+ .n().isFunction("BFCCTPrimCompRTESTwoKeyNav")
.isKeyPredicate(0, "PropertyInt16", "1")
.isKeyPredicate(1, "PropertyString", "'2'")
- .n()
- .isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false);
+ .n().isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false);
testFilter.runOnETTwoKeyNav("PropertyComp/olingo.odata.test1.BFCCTPrimCompRTETTwoKeyNavParam"
+ "(ParameterString=null)/PropertyString eq 'SomeString'")
@@ -3957,9 +3805,7 @@ public class TestFullResourcePath {
.isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTPrimComp, false)
.n()
.isFunction("BFCCTPrimCompRTETTwoKeyNavParam")
- .goParameter(0)
- .isNull()
- .goUpToResourceValidator()
+ .isParameter(0, "ParameterString", null)
.n()
.isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false);
@@ -3969,59 +3815,43 @@ public class TestFullResourcePath {
.root().left().goPath()
.first()
.isNavProperty("NavPropertyETTwoKeyNavMany", EntityTypeProvider.nameETTwoKeyNav, true)
- .n()
- .isFunction("BFCESTwoKeyNavRTString");
+ .n().isFunction("BFCESTwoKeyNavRTString");
- testFilter.runOnETTwoKeyNav("$it/olingo.odata.test1.BFESTwoKeyNavRTESTwoKeyNav()/PropertyString eq 'SomeString'")
- .is("<<$it/BFESTwoKeyNavRTESTwoKeyNav/PropertyString> eq <'SomeString'>>")
+ testFilter.runOnETKeyNav("$it/olingo.odata.test1.BFCETKeyNavRTETKeyNav()/PropertyString eq 'SomeString'")
+ .is("<<$it/BFCETKeyNavRTETKeyNav/PropertyString> eq <'SomeString'>>")
.root().left().goPath()
- .first()
- .isIt()
- .n()
- .isFunction("BFESTwoKeyNavRTESTwoKeyNav")
- .n()
- .isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false);
+ .first().isIt()
+ .n().isFunction("BFCETKeyNavRTETKeyNav")
+ .n().isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false);
- testFilter.runOnETTwoKeyNav("olingo.odata.test1.BFESTwoKeyNavRTESTwoKeyNav()/PropertyString eq 'SomeString'")
- .is("<<BFESTwoKeyNavRTESTwoKeyNav/PropertyString> eq <'SomeString'>>")
+ testFilter.runOnETTwoKeyNav("olingo.odata.test1.BFCESTwoKeyNavRTCTTwoPrim()/PropertyString eq 'SomeString'")
+ .is("<<BFCESTwoKeyNavRTCTTwoPrim/PropertyString> eq <'SomeString'>>")
.root().left().goPath()
- .first()
- .isFunction("BFESTwoKeyNavRTESTwoKeyNav")
- .n()
- .isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false);
+ .first().isFunction("BFCESTwoKeyNavRTCTTwoPrim")
+ .n().isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false);
testFilter.runOnETTwoKeyNav("NavPropertyETTwoKeyNavOne/olingo.odata.test1.BFCETTwoKeyNavRTETTwoKeyNav()"
+ "/PropertyComp/PropertyComp/PropertyString eq 'Walldorf'")
.is("<<NavPropertyETTwoKeyNavOne/BFCETTwoKeyNavRTETTwoKeyNav/PropertyComp/PropertyComp/PropertyString> "
+ "eq <'Walldorf'>>")
.root().left().goPath()
- .first()
- .isNavProperty("NavPropertyETTwoKeyNavOne", EntityTypeProvider.nameETTwoKeyNav, false)
- .n()
- .isFunction("BFCETTwoKeyNavRTETTwoKeyNav")
- .n()
- .isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTPrimComp, false)
- .n()
- .isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTAllPrim, false)
- .n()
- .isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false);
+ .first().isNavProperty("NavPropertyETTwoKeyNavOne", EntityTypeProvider.nameETTwoKeyNav, false)
+ .n().isFunction("BFCETTwoKeyNavRTETTwoKeyNav")
+ .n().isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTPrimComp, false)
+ .n().isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTAllPrim, false)
+ .n().isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false);
- testFilter.runOnETTwoKeyNav("PropertyComp/olingo.odata.test1.BFCCTPrimCompRTESTwoKeyNavParam"
- + "(ParameterString='1')"
- + "/olingo.odata.test1.ETBaseTwoKeyNav(PropertyInt16=2,PropertyString='3')"
- + "/PropertyString eq 'SomeString'")
- .is("<<PropertyComp/BFCCTPrimCompRTESTwoKeyNavParam/olingo.odata.test1.ETBaseTwoKeyNav/PropertyString> "
+ testFilter.runOnETTwoKeyNav("PropertyComp/olingo.odata.test1.BFCCTPrimCompRTESTwoKeyNav()"
+ + "/olingo.odata.test1.ETBaseTwoKeyNav(PropertyInt16=2,PropertyString='3')/PropertyString eq 'SomeString'")
+ .is("<<PropertyComp/BFCCTPrimCompRTESTwoKeyNav/olingo.odata.test1.ETBaseTwoKeyNav/PropertyString> "
+ "eq <'SomeString'>>")
.root().left().goPath()
- .first()
- .isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTPrimComp, false)
- .n()
- .isFunction("BFCCTPrimCompRTESTwoKeyNavParam")
- .isTypeFilterOnCollection(EntityTypeProvider.nameETBaseTwoKeyNav)
+ .first().isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTPrimComp, false)
+ .n().isFunction("BFCCTPrimCompRTESTwoKeyNav")
+ .isTypeFilterOnEntry(EntityTypeProvider.nameETBaseTwoKeyNav)
.isKeyPredicate(0, "PropertyInt16", "2")
.isKeyPredicate(1, "PropertyString", "'3'")
- .n()
- .isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false);
+ .n().isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false);
testFilter.runOnETTwoKeyNavSingle("$it/olingo.odata.test1.BFCETTwoKeyNavRTCTTwoPrim()/olingo.odata.test1.CTBase"
+ "/PropertyString eq 'SomeString'")
@@ -4071,59 +3901,58 @@ public class TestFullResourcePath {
.root().left().goPath()
.first()
.isFunction("UFCRTETTwoKeyNavParam")
- .isParameter(0, "ParameterInt16", "PropertyInt16")
- .n()
- .isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTPrimComp, false)
- .n()
- .isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTAllPrim, false)
- .n()
- .isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false);
+ .goParameter(0)
+ .isMember().goPath().first().isPrimitiveProperty("PropertyInt16", PropertyProvider.nameInt16, false)
+ .goUpFilterValidator().goUpToResourceValidator()
+ .n().isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTPrimComp, false)
+ .n().isComplexProperty("PropertyComp", ComplexTypeProvider.nameCTAllPrim, false)
+ .n().isPrimitiveProperty("PropertyString", PropertyProvider.nameString, false);
}
@Test
public void methods() throws Exception {
testFilter.runOnETKeyNav("indexof(PropertyString,'47') eq 5")
.is("<<indexof(<PropertyString>,<'47'>)> eq <5>>")
- .root().left()
+ .left()
.isMethod(MethodKind.INDEXOF, 2)
.isParameterText(0, "<PropertyString>")
.isParameterText(1, "<'47'>");
testFilter.runOnETKeyNav("tolower(PropertyString) eq 'foo'")
.is("<<tolower(<PropertyString>)> eq <'foo'>>")
- .root().left()
+ .left()
.isMethod(MethodKind.TOLOWER, 1)
.isParameterText(0, "<PropertyString>");
testFilter.runOnETKeyNav("toupper(PropertyString) eq 'FOO'")
.is("<<toupper(<PropertyString>)> eq <'FOO'>>")
- .root().left()
+ .left()
.isMethod(MethodKind.TOUPPER, 1)
.isParameterText(0, "<PropertyString>");
testFilter.runOnETKeyNav("trim(PropertyString) eq 'fooba'")
.is("<<trim(<PropertyString>)> eq <'fooba'>>")
- .root().left()
+ .left()
.isMethod(MethodKind.TRIM, 1)
.isParameterText(0, "<PropertyString>");
testFilter.runOnETKeyNav("substring(PropertyString,4) eq 'foo'")
.is("<<substring(<PropertyString>,<4>)> eq <'foo'>>")
- .root().left()
+ .left()
.isMethod(MethodKind.SUBSTRING, 2)
.isParameterText(0, "<PropertyString>")
.isParameterText(1, "<4>");
testFilter.runOnETKeyNav("substring(PropertyString,4) eq 'foo'")
.is("<<substring(<PropertyString>,<4>)> eq <'foo'>>")
- .root().left()
+ .left()
.isMethod(MethodKind.SUBSTRING, 2)
.isParameterText(0, "<PropertyString>")
.isParameterText(1, "<4>");
testFilter.runOnETKeyNav("substring(PropertyString,2,4) eq 'foo'")
.is("<<substring(<PropertyString>,<2>,<4>)> eq <'foo'>>")
- .root().left()
+ .left()
.isMethod(MethodKind.SUBSTRING, 3)
.isParameterText(0, "<PropertyString>")
.isParameterText(1, "<2>")
@@ -4131,355 +3960,355 @@ public class TestFullResourcePath {
testFilter.runOnETKeyNav("concat(PropertyString,PropertyCompTwoPrim/PropertyString) eq 'foo'")
.is("<<concat(<PropertyString>,<PropertyCompTwoPrim/PropertyString>)> eq <'foo'>>")
- .root().left()
+ .left()
.isMethod(MethodKind.CONCAT, 2)
.isParameterText(0, "<PropertyString>")
.isParameterText(1, "<PropertyCompTwoPrim/PropertyString>");
testFilter.runOnETKeyNav("concat(PropertyString,'bar') eq 'foobar'")
.is("<<concat(<PropertyString>,<'bar'>)> eq <'foobar'>>")
- .root().left()
+ .left()
.isMethod(MethodKind.CONCAT, 2)
.isParameterText(0, "<PropertyString>")
.isParameterText(1, "<'bar'>");
testFilter.runOnETKeyNav("concat(PropertyString,'bar') eq 'foobar'")
.is("<<concat(<PropertyString>,<'bar'>)> eq <'foobar'>>")
- .root().left()
+ .left()
.isMethod(MethodKind.CONCAT, 2)
.isParameterText(0, "<PropertyString>")
.isParameterText(1, "<'bar'>");
testFilter.runOnETKeyNav("length(PropertyString) eq 32")
.is("<<length(<PropertyString>)> eq <32>>")
- .root().left()
+ .left()
.isMethod(MethodKind.LENGTH, 1)
.isParameterText(0, "<PropertyString>");
testFilter.runOnETAllPrim("year(PropertyDate) eq 2013")
.is("<<year(<PropertyDate>)> eq <2013>>")
- .root().left()
+ .left()
.isMethod(MethodKind.YEAR, 1)
.isParameterText(0, "<PropertyDate>");
testFilter.runOnETAllPrim("year(2013-09-25) eq 2013")
.is("<<year(<2013-09-25>)> eq <2013>>")
- .root().left()
+ .left()
.isMethod(MethodKind.YEAR, 1)
.isParameterText(0, "<2013-09-25>");
testFilter.runOnETAllPrim("year(PropertyDateTimeOffset) eq 2013")
.is("<<year(<PropertyDateTimeOffset>)> eq <2013>>")
- .root().left()
+ .left()
.isMethod(MethodKind.YEAR, 1)
.isParameterText(0, "<PropertyDateTimeOffset>");
testFilter.runOnETAllPrim("year(2013-09-25T12:34:56.123456789012-10:24) eq 2013")
.is("<<year(<2013-09-25T12:34:56.123456789012-10:24>)> eq <2013>>")
- .root().left()
+ .left()
.isMethod(MethodKind.YEAR, 1)
.isParameterText(0, "<2013-09-25T12:34:56.123456789012-10:24>");
testFilter.runOnETAllPrim("month(PropertyDate) eq 9")
.is("<<month(<PropertyDate>)> eq <9>>")
- .root().left()
+ .left()
.isMethod(MethodKind.MONTH, 1)
.isParameterText(0, "<PropertyDate>");
testFilter.runOnETAllPrim("month(2013-09-25) eq 9")
.is("<<month(<2013-09-25>)> eq <9>>")
- .root().left()
+ .left()
.isMethod(MethodKind.MONTH, 1)
.isParameterText(0, "<2013-09-25>");
testFilter.runOnETAllPrim("month(PropertyDateTimeOffset) eq 9")
.is("<<month(<PropertyDateTimeOffset>)> eq <9>>")
- .root().left()
+ .left()
.isMethod(MethodKind.MONTH, 1)
.isParameterText(0, "<PropertyDateTimeOffset>");
testFilter.runOnETAllPrim("month(2013-09-25T12:34:56.123456789012-10:24) eq 9")
.is("<<month(<2013-09-25T12:34:56.123456789012-10:24>)> eq <9>>")
- .root().left()
+ .left()
.isMethod(MethodKind.MONTH, 1)
.isParameterText(0, "<2013-09-25T12:34:56.123456789012-10:24>");
testFilter.runOnETAllPrim("day(PropertyDate) eq 25")
.is("<<day(<PropertyDate>)> eq <25>>")
- .root().left()
+ .left()
.isMethod(MethodKind.DAY, 1)
.isParameterText(0, "<PropertyDate>");
testFilter.runOnETAllPrim("day(2013-09-25) eq 25")
.is("<<day(<2013-09-25>)> eq <25>>")
- .root().left()
+ .left()
.isMethod(MethodKind.DAY, 1)
.isParameterText(0, "<2013-09-25>");
testFilter.runOnETAllPrim("day(PropertyDateTimeOffset) eq 25")
.is("<<day(<PropertyDateTimeOffset>)> eq <25>>")
- .root().left()
+ .left()
.isMethod(MethodKind.DAY, 1)
.isParameterText(0, "<PropertyDateTimeOffset>");
testFilter.runOnETAllPrim("day(2013-09-25T12:34:56.123456789012-10:24) eq 25")
.is("<<day(<2013-09-25T12:34:56.123456789012-10:24>)> eq <25>>")
- .root().left()
+ .left()
.isMethod(MethodKind.DAY, 1)
.isParameterText(0, "<2013-09-25T12:34:56.123456789012-10:24>");
testFilter.runOnETAllPrim("hour(PropertyDateTimeOffset) eq 2")
.is("<<hour(<PropertyDateTimeOffset>)> eq <2>>")
- .root().left()
+ .left()
.isMethod(MethodKind.HOUR, 1)
.isParameterText(0, "<PropertyDateTimeOffset>");
testFilter.runOnETAllPrim("hour(PropertyDateTimeOffset) eq 2")
.is("<<hour(<PropertyDateTimeOffset>)> eq <2>>")
- .root().left()
+ .left()
.isMethod(MethodKind.HOUR, 1)
.isParameterText(0, "<PropertyDateTimeOffset>");
testFilter.runOnETAllPrim("hour(2013-09-25T12:34:56.123456789012-10:24) eq 2")
.is("<<hour(<2013-09-25T12:34:56.123456789012-10:24>)> eq <2>>")
- .root().left()
+ .left()
.isMethod(MethodKind.HOUR, 1)
.isParameterText(0, "<2013-09-25T12:34:56.123456789012-10:24>");
testFilter.runOnETAllPrim("hour(PropertyTimeOfDay) eq 2")
.is("<<hour(<PropertyTimeOfDay>)> eq <2>>")
- .root().left()
+ .left()
.isMethod(MethodKind.HOUR, 1)
.isParameterText(0, "<PropertyTimeOfDay>");
testFilter.runOnETAllPrim("hour(12:34:55.123456789012) eq 12")
.is("<<hour(<12:34:55.123456789012>)> eq <12>>")
- .root().left()
+ .left()
.isMethod(MethodKind.HOUR, 1)
.isParameterText(0, "<12:34:55.123456789012>");
testFilter.runOnETAllPrim("minute(PropertyDateTimeOffset) eq 34")
.is("<<minute(<PropertyDateTimeOffset>)> eq <34>>")
- .root().left()
+ .left()
.isMethod(MethodKind.MINUTE, 1)
.isParameterText(0, "<PropertyDateTimeOffset>");
testFilter.runOnETAllPrim("minute(2013-09-25T12:34:56.123456789012-10:24) eq 34")
.is("<<minute(<2013-09-25T12:34:56.123456789012-10:24>)> eq <34>>")
- .root().left()
+ .left()
.isMethod(MethodKind.MINUTE, 1)
.isParameterText(0, "<2013-09-25T12:34:56.123456789012-10:24>");
testFilter.runOnETAllPrim("minute(PropertyTimeOfDay) eq 34")
.is("<<minute(<PropertyTimeOfDay>)> eq <34>>")
- .root().left()
+ .left()
.isMethod(MethodKind.MINUTE, 1)
.isParameterText(0, "<PropertyTimeOfDay>");
testFilter.runOnETAllPrim("minute(12:34:55.123456789012) eq 34")
.is("<<minute(<12:34:55.123456789012>)> eq <34>>")
- .root().left()
+ .left()
.isMethod(MethodKind.MINUTE, 1)
.isParameterText(0, "<12:34:55.123456789012>");
testFilter.runOnETAllPrim("second(PropertyDateTimeOffset) eq 56")
.is("<<second(<PropertyDateTimeOffset>)> eq <56>>")
- .root().left()
+ .left()
.isMethod(MethodKind.SECOND, 1)
.isParameterText(0, "<PropertyDateTimeOffset>");
testFilter.runOnETAllPrim("second(2013-09-25T12:34:56.123456789012-10:24) eq 56")
.is("<<second(<2013-09-25T12:34:56.123456789012-10:24>)> eq <56>>")
- .root().left()
+ .left()
.isMethod(MethodKind.SECOND, 1)
.isParameterText(0, "<2013-09-25T12:34:56.123456789012-10:24>");
testFilter.runOnETAllPrim("second(PropertyTimeOfDay) eq 56")
.is("<<second(<PropertyTimeOfDay>)> eq <56>>")
- .root().left()
+ .left()
.isMethod(MethodKind.SECOND, 1)
.isParameterText(0, "<PropertyTimeOfDay>");
testFilter.runOnETAllPrim("second(12:34:55.123456789012) eq 56")
.is("<<second(<12:34:55.123456789012>)> eq <56>>")
- .root().left()
+ .left()
.isMethod(MethodKind.SECOND, 1)
.isParameterText(0, "<12:34:55.123456789012>");
testFilter.runOnETAllPrim("fractionalseconds(PropertyDateTimeOffset) eq 123456789012")
.is("<<fractionalseconds(<PropertyDateTimeOffset>)> eq <123456789012>>")
- .root().left()
+ .left()
.isMethod(MethodKind.FRACTIONALSECONDS, 1)
.isParameterText(0, "<PropertyDateTimeOffset>");
testFilter.runOnETAllPrim("fractionalseconds(2013-09-25T12:34:56.123456789012-10:24) eq 123456789012")
.is("<<fractionalseconds(<2013-09-25T12:34:56.123456789012-10:24>)> eq <123456789012>>")
- .root().left()
+ .left()
.isMethod(MethodKind.FRACTIONALSECONDS, 1)
.isParameterText(0, "<2013-09-25T12:34:56.123456789012-10:24>");
testFilter.runOnETAllPrim("fractionalseconds(PropertyTimeOfDay) eq 123456789012")
.is("<<fractionalseconds(<PropertyTimeOfDay>)> eq <123456789012>>")
- .root().left()
+ .left()
.isMethod(MethodKind.FRACTIONALSECONDS, 1)
.isParameterText(0, "<PropertyTimeOfDay>");
testFilter.runOnETAllPrim("fractionalseconds(12:34:55.123456789012) eq 123456789012")
.is("<<fractionalseconds(<12:34:55.123456789012>)> eq <123456789012>>")
- .root().left()
+ .left()
.isMethod(MethodKind.FRACTIONALSECONDS, 1)
.isParameterText(0, "<12:34:55.123456789012>");
testFilter.runOnETAllPrim("totalseconds(PropertyDuration) eq 4711")
.is("<<totalseconds(<PropertyDuration>)> eq <4711>>")
- .root().left()
+ .left()
.isMethod(MethodKind.TOTALSECONDS, 1)
.isParameterText(0, "<PropertyDuration>");
testFilter.runOnETAllPrim("totalseconds(duration'P10DT5H34M21.123456789012S') eq 4711")
.is("<<totalseconds(<duration'P10DT5H34M21.123456789012S'>)> eq <4711>>")
- .root().left()
+ .left()
.isMethod(MethodKind.TOTALSECONDS, 1)
.isParameterText(0, "<duration'P10DT5H34M21.123456789012S'>");
testFilter.runOnETAllPrim("date(PropertyDateTimeOffset) eq 2013-09-25")
.is("<<date(<PropertyDateTimeOffset>)> eq <2013-09-25>>")
- .root().left()
+ .left()
.isMethod(MethodKind.DATE, 1)
.isParameterText(0, "<PropertyDateTimeOffset>");
testFilter.runOnETAllPrim("date(2013-09-25T12:34:56.123456789012-10:24) eq 2013-09-25")
.is("<<date(<2013-09-25T12:34:56.123456789012-10:24>)> eq <2013-09-25>>")
- .root().left()
+ .left()
.isMethod(MethodKind.DATE, 1)
.isParameterText(0, "<2013-09-25T12:34:56.123456789012-10:24>");
testFilter.runOnETAllPrim("time(PropertyDateTimeOffset) eq 12:34:55.123456789012")
.is("<<time(<PropertyDateTimeOffset>)> eq <12:34:55.123456789012>>")
- .root().left()
+ .left()
.isMethod(MethodKind.TIME, 1)
.isParameterText(0, "<PropertyDateTimeOffset>");
testFilter.runOnETAllPrim("time(2013-09-25T12:34:56.123456789012-10:24) eq 12:34:55.123456789012")
.is("<<time(<2013-09-25T12:34:56.123456789012-10:24>)> eq <12:34:55.123456789012>>")
- .root().left()
+ .left()
.isMethod(MethodKind.TIME, 1)
.isParameterText(0, "<2013-09-25T12:34:56.123456789012-10:24>");
testFilter.runOnETAllPrim("round(PropertyDouble) eq 17")
.is("<<round(<PropertyDouble>)> eq <17>>")
- .root().left()
+ .left()
.isMethod(MethodKind.ROUND, 1)
.isParameterText(0, "<PropertyDouble>");
testFilter.runOnETAllPrim("round(17.45e1) eq 17")
.is("<<round(<17.45e1>)> eq <17>>")
- .root().left()
+ .left()
.isMethod(MethodKind.ROUND, 1)
.isParameterText(0, "<17.45e1>");
testFilter.runOnETAllPrim("round(PropertyDecimal) eq 17")
.is("<<round(<PropertyDecimal>)> eq <17>>")
- .root().left()
+ .left()
.isMethod(MethodKind.ROUND, 1)
.isParameterText(0, "<PropertyDecimal>");
testFilter.runOnETAllPrim("round(17.45) eq 17")
.is("<<round(<17.45>)> eq <17>>")
- .root().left()
+ .left()
.isMethod(MethodKind.ROUND, 1)
.isParameterText(0, "<17.45>");
testFilter.runOnETAllPrim("floor(PropertyDouble) eq 17")
.is("<<floor(<PropertyDouble>)> eq <17>>")
- .root().left()
+ .left()
.isMethod(MethodKind.FLOOR, 1)
.isParameterText(0, "<PropertyDouble>");
testFilter.runOnETAllPrim("floor(17.45e1) eq 17")
.is("<<floor(<17.45e1>)> eq <17>>")
- .root().left()
+ .left()
.isMethod(MethodKind.FLOOR, 1)
.isParameterText(0, "<17.45e1>");
testFilter.runOnETAllPrim("floor(PropertyDecimal) eq 17")
.is("<<floor(<PropertyDecimal>)> eq <17>>")
- .root().left()
+ .left()
.isMethod(MethodKind.FLOOR, 1)
.isParameterText(0, "<PropertyDecimal>");
testFilter.runOnETAllPrim("floor(17.45) eq 17")
.is("<<floor(<17.45>)> eq <17>>")
- .root().left()
+ .left()
.isMethod(MethodKind.FLOOR, 1)
.isParameterText(0, "<17.45>");
testFilter.runOnETAllPrim("ceiling(PropertyDouble) eq 18")
.is("<<ceiling(<PropertyDouble>)> eq <18>>")
- .root().left()
+ .left()
.isMethod(MethodKind.CEILING, 1)
.isParameterText(0, "<PropertyDouble>");
testFilter.runOnETAllPrim("ceiling(17.55e1) eq 18")
.is("<<ceiling(<17.55e1>)> eq <18>>")
- .root().left()
+ .left()
.isMethod(MethodKind.CEILING, 1)
.isParameterText(0, "<17.55e1>");
testFilter.runOnETAllPrim("ceiling(PropertyDecimal) eq 18")
.is("<<ceiling(<PropertyDecimal>)> eq <18>>")
- .root().left()
+ .left()
.isMethod(MethodKind.CEILING, 1)
.isParameterText(0, "<PropertyDecimal>");
testFilter.runOnETAllPrim("ceiling(17.55) eq 18")
.is("<<ceiling(<17.55>)> eq <18>>")
- .root().left()
+ .left()
.isMethod(MethodKind.CEILING, 1)
.isParameterText(0, "<17.55>");
testFilter.runOnETAllPrim("totaloffsetminutes(PropertyDateTimeOffset) eq 4711")
.is("<<totaloffsetminutes(<PropertyDateTimeOffset>)> eq <4711>>")
- .root().left()
+ .left()
.isMethod(MethodKind.TOTALOFFSETMINUTES, 1)
.isParameterText(0, "<PropertyDateTimeOffset>");
testFilter.runOnETAllPrim("totaloffsetminutes(2013-09-25T12:34:56.123456789012-10:24) eq 4711")
.is("<<totaloffsetminutes(<2013-09-25T12:34:56.123456789012-10:24>)> eq <4711>>")
- .root().left()
+ .left()
.isMethod(MethodKind.TOTALOFFSETMINUTES, 1)
.isParameterText(0, "<2013-09-25T12:34:56.123456789012-10:24>");
- testFilter.runOnETAllPrim("mindatetime()")
- .is("<mindatetime()>")
- .isMethod(MethodKind.MINDATETIME, 0);
+ testFilter.runOnETAllPrim("mindatetime() ne null")
+ .is("<<mindatetime()> ne <null>>")
+ .left().isMethod(MethodKind.MINDATETIME, 0);
testFilter.runOnETAllPrim("mindatetime() eq 2013-09-25T12:34:56.123456789012-10:24")
.is("<<mindatetime()> eq <2013-09-25T12:34:56.123456789012-10:24>>")
- .root().left()
+ .left()
.isMethod(MethodKind.MINDATETIME, 0);
- testFilter.runOnETAllPrim("maxdatetime()")
- .is("<maxdatetime()>")
- .isMethod(MethodKind.MAXDATETIME, 0);
+ testFilter.runOnETAllPrim("maxdatetime() ne null")
+ .is("<<maxdatetime()> ne <null>>")
+ .left().isMethod(MethodKind.MAXDATETIME, 0);
testFilter.runOnETAllPrim("maxdatetime() eq 2013-09-25T12:34:56.123456789012-10:24")
.is("<<maxdatetime()> eq <2013-09-25T12:34:56.123456789012-10:24>>")
- .root().left()
+ .left()
.isMethod(MethodKind.MAXDATETIME, 0);
- testFilter.runOnETAllPrim("now()")
- .is("<now()>")
- .isMethod(MethodKind.NOW, 0);
+ testFilter.runOnETAllPrim("now() ne null")
+ .is("<<now()> ne <null>>")
+ .left().isMethod(MethodKind.NOW, 0);
testFilter.runOnETAllPrim("now() eq 2013-09-25T12:34:56.123456789012-10:24")
.is("<<now()> eq <2013-09-25T12:34:56.123456789012-10:24>>")
- .root().left()
+ .left()
.isMethod(MethodKind.NOW, 0);
testFilter.runOnETTwoKeyNav("$it/PropertyString eq 'SomeString'")
.is("<<$it/PropertyString> eq <'SomeString'>>")
- .root().left()
+ .left()
.goPath()
.first().isUriPathInfoKind(UriResourceKind.it)
.isType(EntityTypeProvider.nameETTwoKeyNav, false)
@@ -4487,7 +4316,7 @@ public class TestFullResourcePath {
testFilter.runOnCTTwoPrim("$it/PropertyString eq 'SomeString'")
.is("<<$it/PropertyString> eq <'SomeString'>>")
- .root().left()
+ .left()
.goPath()
.first().isUriPathInfoKind(UriResourceKind.it)
.isType(ComplexTypeProvider.nameCTTwoPrim, false)
@@ -4495,7 +4324,7 @@ public class TestFullResourcePath {
testFilter.runOnString("$it eq 'Walldorf'")
.is("<<$it> eq <'Walldorf'>>")
- .root().left()
+ .left()
.goPath()
.first().isUriPathInfoKind(UriResourceKind.it)
.isType(PropertyProvider.nameString, false);
@@ -4512,7 +4341,7 @@ public class TestFullResourcePath {
testFilter.runOnString("endswith($it,'sap.com') eq false")
.is("<<endswith(<$it>,<'sap.com'>)> eq <false>>")
- .root().left()
+ .left()
.isMethod(MethodKind.ENDSWITH, 2)
.isParameterText(0, "<$it>")
.isParameterText(1, "<'sap.com'>")
@@ -4644,44 +4473,42 @@ public class TestFullResourcePath {
.n().isPrimitiveProperty("PropertyInt16", PropertyProvider.nameInt16, false);
}
- // TODO: Implement cast method.
@Test
public void castMethod() throws Exception {
- testFilter.runOnETKeyNav("cast(olingo.odata.test1.ETBaseTwoKeyNav)")
- .is("<cast(<olingo.odata.test1.ETBaseTwoKeyNav>)>")
- .root()
+ testFilter.runOnETKeyNav("cast(olingo.odata.test1.ETBaseTwoKeyNav) ne null")
+ .is("<<cast(<olingo.odata.test1.ETBaseTwoKeyNav>)> ne <n
<TRUNCATED>
[3/6] olingo-odata4 git commit: [OLINGO-834] $expand parser in Java +
clean-up
Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java
index f505a21..3b673a6 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java
@@ -40,6 +40,15 @@ public class UriTokenizer {
ROOT,
IT,
+ EXPAND,
+ FILTER,
+ LEVELS,
+ ORDERBY,
+ SEARCH,
+ SELECT,
+ SKIP,
+ TOP,
+
ANY,
ALL,
@@ -53,8 +62,9 @@ public class UriTokenizer {
EQ,
STAR,
PLUS,
- MINUS,
+
NULL,
+ MAX,
// variable-value tokens (convention: mixed case)
ODataIdentifier,
@@ -76,6 +86,13 @@ public class UriTokenizer {
jsonArrayOrObject,
+ Word,
+ Phrase,
+
+ OrOperatorSearch,
+ AndOperatorSearch,
+ NotOperatorSearch,
+
OrOperator,
AndOperator,
EqualsOperator,
@@ -90,6 +107,7 @@ public class UriTokenizer {
MulOperator,
DivOperator,
ModOperator,
+ MinusOperator,
NotOperator,
CastMethod,
@@ -161,6 +179,10 @@ public class UriTokenizer {
boolean found = false;
final int previousIndex = index;
switch (allowedTokenKind) {
+ case EOF:
+ found = index >= parseString.length();
+ break;
+
// Constants
case REF:
found = nextConstant("$ref");
@@ -181,6 +203,31 @@ public class UriTokenizer {
found = nextConstant("$it");
break;
+ case EXPAND:
+ found = nextConstant("$expand");
+ break;
+ case FILTER:
+ found = nextConstant("$filter");
+ break;
+ case LEVELS:
+ found = nextConstant("$levels");
+ break;
+ case ORDERBY:
+ found = nextConstant("$orderby");
+ break;
+ case SEARCH:
+ found = nextConstant("$search");
+ break;
+ case SELECT:
+ found = nextConstant("$select");
+ break;
+ case SKIP:
+ found = nextConstant("$skip");
+ break;
+ case TOP:
+ found = nextConstant("$top");
+ break;
+
case ANY:
found = nextConstant("any");
break;
@@ -218,14 +265,12 @@ public class UriTokenizer {
case PLUS:
found = nextCharacter('+');
break;
- case MINUS:
- found = nextMinus();
- break;
+
case NULL:
found = nextConstant("null");
break;
- case EOF:
- found = index >= parseString.length();
+ case MAX:
+ found = nextConstant("max");
break;
// Identifiers
@@ -282,6 +327,25 @@ public class UriTokenizer {
found = nextJsonArrayOrObject();
break;
+ // Search
+ case Word:
+ found = nextWord();
+ break;
+ case Phrase:
+ found = nextPhrase();
+ break;
+
+ // Operators in Search Expressions
+ case OrOperatorSearch:
+ found = nextBinaryOperator("OR");
+ break;
+ case AndOperatorSearch:
+ found = nextAndOperatorSearch();
+ break;
+ case NotOperatorSearch:
+ found = nextUnaryOperator("NOT");
+ break;
+
// Operators
case OrOperator:
found = nextBinaryOperator("or");
@@ -325,8 +389,12 @@ public class UriTokenizer {
case ModOperator:
found = nextBinaryOperator("mod");
break;
+ case MinusOperator:
+ // To avoid unnecessary minus operators for negative numbers, we have to check what follows the minus sign.
+ found = nextCharacter('-') && !nextDigit() && !nextConstant("INF");
+ break;
case NotOperator:
- found = nextConstant("not") && nextWhitespace();
+ found = nextUnaryOperator("not");
break;
// Methods
@@ -444,27 +512,6 @@ public class UriTokenizer {
return found;
}
- private boolean nextMinus() {
- if(parseString.startsWith("-", index)) {
- final int lastGoodIndex = index;
-
- if(nextDoubleValue()) {
- index = lastGoodIndex;
- return false;
- } else if(nextDecimalValue()) {
- index = lastGoodIndex;
- return false;
- } else if(nextIntegerValue(true)) {
- index = lastGoodIndex;
- return false;
- } else {
- index++;
- return true;
- }
- }
- return false;
- }
-
/**
* Moves past the given string constant if found; otherwise leaves the index unchanged.
* @return whether the constant has been found at the current index
@@ -569,34 +616,6 @@ public class UriTokenizer {
}
return count > 0;
}
-
- /**
- * Moves past the given whitespace-surrounded operator constant if found;
- * otherwise leaves the index unchanged.
- * @return whether the operator has been found at the current index
- */
- private boolean nextBinaryOperator(final String operator) {
- return nextWhitespace() && nextConstant(operator) && nextWhitespace();
- }
-
- /**
- * Moves past the given method name and its immediately following opening parenthesis if found;
- * otherwise leaves the index unchanged.
- * @return whether the method has been found at the current index
- */
- private boolean nextMethod(final String methodName) {
- return nextConstant(methodName) && nextCharacter('(');
- }
-
- /**
- * Moves past (required) whitespace and the given suffix name if found;
- * otherwise leaves the index unchanged.
- * @return whether the suffix has been found at the current index
- */
- private boolean nextSuffix(final String suffixName) {
- return nextWhitespace() && nextConstant(suffixName);
- }
-
/**
* Moves past an OData identifier if found; otherwise leaves the index unchanged.
* @return whether an OData identifier has been found at the current index
@@ -650,6 +669,38 @@ public class UriTokenizer {
}
}
+ /**
+ * Moves past the given whitespace-surrounded operator constant if found.
+ * @return whether the operator has been found at the current index
+ */
+ private boolean nextBinaryOperator(final String operator) {
+ return nextWhitespace() && nextConstant(operator) && nextWhitespace();
+ }
+
+ /**
+ * Moves past the given whitespace-suffixed operator constant if found.
+ * @return whether the operator has been found at the current index
+ */
+ private boolean nextUnaryOperator(final String operator) {
+ return nextConstant(operator) && nextWhitespace();
+ }
+
+ /**
+ * Moves past the given method name and its immediately following opening parenthesis if found.
+ * @return whether the method has been found at the current index
+ */
+ private boolean nextMethod(final String methodName) {
+ return nextConstant(methodName) && nextCharacter('(');
+ }
+
+ /**
+ * Moves past (required) whitespace and the given suffix name if found.
+ * @return whether the suffix has been found at the current index
+ */
+ private boolean nextSuffix(final String suffixName) {
+ return nextWhitespace() && nextConstant(suffixName);
+ }
+
private boolean nextParameterAliasName() {
return nextCharacter('@') && nextODataIdentifier();
}
@@ -978,4 +1029,52 @@ public class UriTokenizer {
return false;
}
}
+
+ private boolean nextAndOperatorSearch() {
+ if (nextWhitespace()) {
+ final int lastGoodIndex = index;
+ if (nextUnaryOperator("OR")) {
+ return false;
+ } else if (!(nextUnaryOperator("AND"))) {
+ index = lastGoodIndex;
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private boolean nextWord() {
+ int count = 0;
+ while (index < parseString.length()) {
+ final int code = parseString.codePointAt(index);
+ if (Character.isUnicodeIdentifierStart(code)) {
+ count++;
+ // Unicode characters outside of the Basic Multilingual Plane are represented as two Java characters.
+ index += Character.isSupplementaryCodePoint(code) ? 2 : 1;
+ } else {
+ break;
+ }
+ }
+ final String word = parseString.substring(index - count, index);
+ return count > 0 && !("OR".equals(word) || "AND".equals(word) || "NOT".equals(word));
+ }
+
+ private boolean nextPhrase() {
+ if (nextCharacter('"')) {
+ do {
+ if (nextCharacter('\\')) {
+ if (!(nextCharacter('\\') || nextCharacter('"'))) {
+ return false;
+ }
+ } else if (nextCharacter('"')) {
+ return true;
+ } else {
+ index++;
+ }
+ } while (index < parseString.length());
+ return false;
+ }
+ return false;
+ }
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/AliasImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/AliasImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/AliasImpl.java
index c7d7c20..8c8dab9 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/AliasImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/AliasImpl.java
@@ -41,4 +41,8 @@ public class AliasImpl implements Alias {
return visitor.visitAlias(parameterName);
}
+ @Override
+ public String toString() {
+ return parameterName;
+ }
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/EnumerationImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/EnumerationImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/EnumerationImpl.java
index 256b8d1..a238104 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/EnumerationImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/EnumerationImpl.java
@@ -53,4 +53,10 @@ public class EnumerationImpl implements Enumeration {
public <T> T accept(final ExpressionVisitor<T> visitor) throws ExpressionVisitException, ODataApplicationException {
return visitor.visitEnum(type, values);
}
+
+ @Override
+ public String toString() {
+ return type == null ? null :
+ type.getFullQualifiedName().getFullQualifiedNameAsString() + getValues();
+ }
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/LambdaRefImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/LambdaRefImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/LambdaRefImpl.java
index 824943a..16232b8 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/LambdaRefImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/LambdaRefImpl.java
@@ -40,4 +40,9 @@ public class LambdaRefImpl implements LambdaRef {
public <T> T accept(final ExpressionVisitor<T> visitor) throws ExpressionVisitException, ODataApplicationException {
return visitor.visitLambdaReference(variableText);
}
+
+ @Override
+ public String toString() {
+ return variableText;
+ }
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/TypeLiteralImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/TypeLiteralImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/TypeLiteralImpl.java
index 336c203..6a2a1c6 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/TypeLiteralImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/expression/TypeLiteralImpl.java
@@ -41,4 +41,9 @@ public class TypeLiteralImpl implements TypeLiteral {
public <T> T accept(final ExpressionVisitor<T> visitor) throws ExpressionVisitException, ODataApplicationException {
return visitor.visitTypeLiteral(type);
}
+
+ @Override
+ public String toString() {
+ return type == null ? null : type.getFullQualifiedName().getFullQualifiedNameAsString();
+ }
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties b/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties
index 0b43f70..e178fed 100644
--- a/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties
+++ b/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties
@@ -81,11 +81,11 @@ UriParserSemanticException.COMPLEX_PROPERTY_OF_ENTITY_TYPE_EXPECTED=A complex pr
UriParserSemanticException.NOT_FOR_ENTITY_TYPE=Not allowed for entity type.
UriParserSemanticException.PREVIOUS_PART_TYPED=The previous part is typed.
UriParserSemanticException.RESOURCE_NOT_FOUND=Cannot find EntitySet, Singleton, ActionImport or FunctionImport with name '%1$s'.
-UriParserSemanticException.NOT_IMPLEMENTED=%1$s is not implemented!
-UriParserSemanticException.NAMESPACE_NOT_ALLOWED_AT_FIRST_ELEMENT=Namespace is not allowed for Entity Sets, Singeltons, Action Imports and Function Imports. Found '%1$s'.
-UriParserSemanticException.COMPLEX_PARAMETER_IN_RESOURCE_PATH=Complex parameters must not appear in resource path segments. Found: '%1$s'.
+UriParserSemanticException.NOT_IMPLEMENTED='%1$s' is not implemented!
+UriParserSemanticException.NAMESPACE_NOT_ALLOWED_AT_FIRST_ELEMENT=Namespace is not allowed for Entity Sets, Singletons, Action Imports and Function Imports; found '%1$s'.
+UriParserSemanticException.COMPLEX_PARAMETER_IN_RESOURCE_PATH=Complex parameters must not appear in resource path segments; found: '%1$s'.
UriParserSemanticException.FUNCTION_IMPORT_NOT_ALLOWED=Function Imports are not allowed in $filter or $orderby. Found: '%1$s'.
-UriParserSemanticException.TYPES_NOT_COMPATIBLE=Types are not compatible. Left type: '%1$s', right type: '%1$s'.
+UriParserSemanticException.TYPES_NOT_COMPATIBLE=The types '%1$s' and '%2$s' are not compatible.
UriValidationException.UNSUPPORTED_QUERY_OPTION=The query option '%1$s' is not supported.
UriValidationException.UNSUPPORTED_URI_KIND=The URI kind '%1$s' is not supported.
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java
index 4ab7fce..94d5373 100644
--- a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java
+++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java
@@ -22,9 +22,11 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
import java.util.Locale;
+import org.apache.olingo.commons.api.edm.Edm;
import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
import org.apache.olingo.server.core.uri.parser.UriTokenizer.TokenKind;
@@ -260,9 +262,17 @@ public class ExpressionParserTest {
expression = parseMethod(TokenKind.SubstringMethod, "'abc'", "1");
assertEquals("{substring ['abc', 1]}", expression.toString());
+ assertEquals("{cast [Edm.SByte]}", parseMethod(TokenKind.CastMethod, "Edm.SByte").toString());
+ assertEquals("{cast [42, Edm.SByte]}", parseMethod(TokenKind.CastMethod, "42", "Edm.SByte").toString());
+
+ assertEquals("{isof [Edm.SByte]}", parseMethod(TokenKind.IsofMethod, "Edm.SByte").toString());
+ assertEquals("{isof [42, Edm.SByte]}", parseMethod(TokenKind.IsofMethod, "42", "Edm.SByte").toString());
+
wrongExpression("substring('abc')");
wrongExpression("substring('abc',1,2,3)");
wrongExpression("substring(1,2)");
+ wrongExpression("cast(1,2)");
+ wrongExpression("isof(Edm.Int16,2)");
}
private Expression parseMethod(TokenKind kind, String... parameters)
@@ -288,7 +298,7 @@ public class ExpressionParserTest {
private Expression parseExpression(final String expressionString)
throws UriParserException, UriValidationException {
UriTokenizer tokenizer = new UriTokenizer(expressionString);
- Expression expression = new ExpressionParser(null, odata).parse(tokenizer, null, null);
+ Expression expression = new ExpressionParser(mock(Edm.class), odata).parse(tokenizer, null, null);
assertNotNull(expression);
assertTrue(tokenizer.next(TokenKind.EOF));
return expression;
@@ -296,7 +306,7 @@ public class ExpressionParserTest {
private void wrongExpression(final String expressionString) {
try {
- new ExpressionParser(null, odata).parse(new UriTokenizer(expressionString), null, null);
+ new ExpressionParser(mock(Edm.class), odata).parse(new UriTokenizer(expressionString), null, null);
fail("Expected exception not thrown.");
} catch (final UriParserException e) {
assertNotNull(e);
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java
index af45e80..e130457 100644
--- a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java
+++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java
@@ -76,7 +76,7 @@ public class UriTokenizerTest {
assertTrue(tokenizer.next(TokenKind.STAR));
assertTrue(tokenizer.next(TokenKind.SLASH));
assertTrue(tokenizer.next(TokenKind.PLUS));
- assertTrue(tokenizer.next(TokenKind.MINUS));
+ assertTrue(tokenizer.next(TokenKind.MinusOperator));
assertTrue(tokenizer.next(TokenKind.EOF));
tokenizer = new UriTokenizer("any(a:true) or all(b:false)");
@@ -97,6 +97,45 @@ public class UriTokenizerTest {
}
@Test
+ public void systemQueryOptions() {
+ UriTokenizer tokenizer = new UriTokenizer("$expand=*;$filter=true;$levels=max;$orderby=false");
+ assertTrue(tokenizer.next(TokenKind.EXPAND));
+ assertTrue(tokenizer.next(TokenKind.EQ));
+ assertTrue(tokenizer.next(TokenKind.STAR));
+ assertTrue(tokenizer.next(TokenKind.SEMI));
+ assertTrue(tokenizer.next(TokenKind.FILTER));
+ assertTrue(tokenizer.next(TokenKind.EQ));
+ assertTrue(tokenizer.next(TokenKind.BooleanValue));
+ assertTrue(tokenizer.next(TokenKind.SEMI));
+ assertTrue(tokenizer.next(TokenKind.LEVELS));
+ assertTrue(tokenizer.next(TokenKind.EQ));
+ assertTrue(tokenizer.next(TokenKind.MAX));
+ assertTrue(tokenizer.next(TokenKind.SEMI));
+ assertTrue(tokenizer.next(TokenKind.ORDERBY));
+ assertTrue(tokenizer.next(TokenKind.EQ));
+ assertTrue(tokenizer.next(TokenKind.BooleanValue));
+ assertTrue(tokenizer.next(TokenKind.EOF));
+
+ tokenizer = new UriTokenizer("$search=A;$select=*;$skip=1;$top=2");
+ assertTrue(tokenizer.next(TokenKind.SEARCH));
+ assertTrue(tokenizer.next(TokenKind.EQ));
+ assertTrue(tokenizer.next(TokenKind.ODataIdentifier));
+ assertTrue(tokenizer.next(TokenKind.SEMI));
+ assertTrue(tokenizer.next(TokenKind.SELECT));
+ assertTrue(tokenizer.next(TokenKind.EQ));
+ assertTrue(tokenizer.next(TokenKind.STAR));
+ assertTrue(tokenizer.next(TokenKind.SEMI));
+ assertTrue(tokenizer.next(TokenKind.SKIP));
+ assertTrue(tokenizer.next(TokenKind.EQ));
+ assertTrue(tokenizer.next(TokenKind.IntegerValue));
+ assertTrue(tokenizer.next(TokenKind.SEMI));
+ assertTrue(tokenizer.next(TokenKind.TOP));
+ assertTrue(tokenizer.next(TokenKind.EQ));
+ assertTrue(tokenizer.next(TokenKind.IntegerValue));
+ assertTrue(tokenizer.next(TokenKind.EOF));
+ }
+
+ @Test
public void identifier() {
assertTrue(new UriTokenizer("name").next(TokenKind.ODataIdentifier));
assertTrue(new UriTokenizer("_name").next(TokenKind.ODataIdentifier));
@@ -390,11 +429,11 @@ public class UriTokenizerTest {
assertTrue(tokenizer.next(TokenKind.IntegerValue));
assertTrue(tokenizer.next(TokenKind.EOF));
- tokenizer = new UriTokenizer("1ne 2");
+ tokenizer = new UriTokenizer("-1ne 2");
assertTrue(tokenizer.next(TokenKind.IntegerValue));
assertFalse(tokenizer.next(TokenKind.NotEqualsOperator));
- tokenizer = new UriTokenizer("1 ne2");
+ tokenizer = new UriTokenizer("1 ne-2");
assertTrue(tokenizer.next(TokenKind.IntegerValue));
assertFalse(tokenizer.next(TokenKind.NotEqualsOperator));
@@ -404,6 +443,11 @@ public class UriTokenizerTest {
assertTrue(tokenizer.next(TokenKind.IntegerValue));
assertTrue(tokenizer.next(TokenKind.EOF));
+ assertTrue(new UriTokenizer("-x").next(TokenKind.MinusOperator));
+ assertFalse(new UriTokenizer("-1").next(TokenKind.MinusOperator));
+ assertFalse(new UriTokenizer("-INF").next(TokenKind.MinusOperator));
+ assertFalse(new UriTokenizer("+").next(TokenKind.MinusOperator));
+
assertFalse(new UriTokenizer("nottrue").next(TokenKind.NotOperator));
assertFalse(new UriTokenizer("no true").next(TokenKind.NotOperator));
@@ -484,6 +528,38 @@ public class UriTokenizerTest {
wrongToken(TokenKind.DescSuffix, " desc", 'D');
}
+ @Test
+ public void search() {
+ UriTokenizer tokenizer = new UriTokenizer("a AND b OR NOT \"c\" d");
+ assertTrue(tokenizer.next(TokenKind.Word));
+ assertTrue(tokenizer.next(TokenKind.AndOperatorSearch));
+ assertTrue(tokenizer.next(TokenKind.Word));
+ assertFalse(tokenizer.next(TokenKind.AndOperatorSearch));
+ assertTrue(tokenizer.next(TokenKind.OrOperatorSearch));
+ assertTrue(tokenizer.next(TokenKind.NotOperatorSearch));
+ assertTrue(tokenizer.next(TokenKind.Phrase));
+ assertTrue(tokenizer.next(TokenKind.AndOperatorSearch));
+ assertTrue(tokenizer.next(TokenKind.Word));
+ assertFalse(tokenizer.next(TokenKind.AndOperatorSearch));
+ assertFalse(tokenizer.next(TokenKind.Word));
+ assertFalse(tokenizer.next(TokenKind.Phrase));
+ assertTrue(tokenizer.next(TokenKind.EOF));
+
+ assertTrue(new UriTokenizer("\"a\\\\x\\\"\"").next(TokenKind.Phrase));
+ assertFalse(new UriTokenizer("\"a\\\"").next(TokenKind.Phrase));
+ assertFalse(new UriTokenizer("\"a\\x\"").next(TokenKind.Phrase));
+ wrongToken(TokenKind.Phrase, "\"a\"", '\\');
+
+ final String outsideBmpLetter = String.valueOf(Character.toChars(0x10330));
+ assertTrue(new UriTokenizer("\"" + outsideBmpLetter + "\"").next(TokenKind.Phrase));
+
+ assertTrue(new UriTokenizer(outsideBmpLetter).next(TokenKind.Word));
+ assertFalse(new UriTokenizer("1").next(TokenKind.Word));
+ assertFalse(new UriTokenizer("AND").next(TokenKind.Word));
+ assertFalse(new UriTokenizer("OR").next(TokenKind.Word));
+ assertFalse(new UriTokenizer("NOT").next(TokenKind.Word));
+ }
+
private void wrongToken(final TokenKind kind, final String value, final char disturbCharacter) {
assertFalse(new UriTokenizer(disturbCharacter + value).next(kind));
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8925274c/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/search/SearchParserAndTokenizerTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/search/SearchParserAndTokenizerTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/search/SearchParserAndTokenizerTest.java
index e028cfe..f3e50a2 100644
--- a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/search/SearchParserAndTokenizerTest.java
+++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/search/SearchParserAndTokenizerTest.java
@@ -35,7 +35,7 @@ public class SearchParserAndTokenizerTest {
assertQuery("a AND b AND c").resultsIn("{{'a' AND 'b'} AND 'c'}");
assertQuery("a OR b").resultsIn("{'a' OR 'b'}");
assertQuery("a OR b OR c").resultsIn("{{'a' OR 'b'} OR 'c'}");
-
+
assertQuery("NOT a NOT b").resultsIn("{{NOT 'a'} AND {NOT 'b'}}");
assertQuery("NOT a AND NOT b").resultsIn("{{NOT 'a'} AND {NOT 'b'}}");
assertQuery("NOT a OR NOT b").resultsIn("{{NOT 'a'} OR {NOT 'b'}}");
@@ -59,16 +59,16 @@ public class SearchParserAndTokenizerTest {
assertQuery("a AND (b OR c)").resultsIn("{'a' AND {'b' OR 'c'}}");
assertQuery("(a OR b) AND NOT c").resultsIn("{{'a' OR 'b'} AND {NOT 'c'}}");
assertQuery("(a OR B) AND (c OR d AND NOT e OR (f))")
- .resultsIn("{{'a' OR 'B'} AND {{'c' OR {'d' AND {NOT 'e'}}} OR 'f'}}");
+ .resultsIn("{{'a' OR 'B'} AND {{'c' OR {'d' AND {NOT 'e'}}} OR 'f'}}");
assertQuery("(a OR B) (c OR d NOT e OR (f))")
- .resultsIn("{{'a' OR 'B'} AND {{'c' OR {'d' AND {NOT 'e'}}} OR 'f'}}");
+ .resultsIn("{{'a' OR 'B'} AND {{'c' OR {'d' AND {NOT 'e'}}} OR 'f'}}");
assertQuery("((((a))))").resultsIn("'a'");
assertQuery("((((a)))) ((((a))))").resultsIn("{'a' AND 'a'}");
assertQuery("((((a)))) OR ((((a))))").resultsIn("{'a' OR 'a'}");
assertQuery("((((((a)))) ((((c))) OR (((C)))) ((((a))))))").resultsIn("{{'a' AND {'c' OR 'C'}} AND 'a'}");
assertQuery("((((\"a\")))) OR ((((\"a\"))))").resultsIn("{'a' OR 'a'}");
}
-
+
@Test
public void parseImplicitAnd() throws Exception {
assertQuery("a b").resultsIn("{'a' AND 'b'}");
@@ -103,7 +103,7 @@ public class SearchParserAndTokenizerTest {
assertQuery("((a AND b OR c)").resultsIn(SearchParserException.MessageKeys.MISSING_CLOSE);
assertQuery("a AND (b OR c").resultsIn(SearchParserException.MessageKeys.MISSING_CLOSE);
assertQuery("(a AND ((b OR c)").resultsIn(SearchParserException.MessageKeys.MISSING_CLOSE);
-
+
assertQuery("NOT NOT a").resultsIn(SearchParserException.MessageKeys.INVALID_NOT_OPERAND);
assertQuery("NOT (a)").resultsIn(SearchParserException.MessageKeys.TOKENIZER_EXCEPTION);
}
@@ -186,7 +186,6 @@ public class SearchParserAndTokenizerTest {
// <Input>http://serviceRoot/Products?$search=blue</Input>
assertQuery("blue").resultsIn("'blue'");
-
// below cases can not be tested here
// <TestCase Name="5.1.7 Search - on entity container" Rule="odataUri">
// <Input>http://serviceRoot/Model.Container/$all?$search=blue</Input>
@@ -194,68 +193,47 @@ public class SearchParserAndTokenizerTest {
// <Input>http://serviceRoot/$all?$search=blue</Input>
}
-
private static Validator assertQuery(String searchQuery) {
- return Validator.init(searchQuery);
+ return new Validator(searchQuery);
}
private static class Validator {
- private boolean log;
private final String searchQuery;
private Validator(String searchQuery) {
this.searchQuery = searchQuery;
}
- private static Validator init(String searchQuery) {
- return new Validator(searchQuery);
- }
-
- @SuppressWarnings("unused")
- private Validator withLogging() {
- log = true;
- return this;
- }
-
- private void resultsIn(SearchParserException.MessageKey key)
- throws SearchTokenizerException {
+ private void resultsIn(SearchParserException.MessageKey key) throws SearchTokenizerException {
try {
resultsIn(searchQuery);
} catch (SearchParserException e) {
Assert.assertEquals("SearchParserException with unexpected message '" + e.getMessage() +
"' was thrown.", key, e.getMessageKey());
- if(log) {
- System.out.println("Caught SearchParserException with message key " +
- e.getMessageKey() + " and message " + e.getMessage());
- }
return;
}
Assert.fail("SearchParserException with message key " + key.getKey() + " was not thrown.");
}
-
+
public void resultsInExpectedTerm(final String actualToken) throws SearchTokenizerException {
try {
resultsIn(searchQuery);
- } catch(SearchParserException e) {
+ } catch (SearchParserException e) {
Assert.assertEquals(SearchParserException.MessageKeys.EXPECTED_DIFFERENT_TOKEN, e.getMessageKey());
Assert.assertEquals("Expected PHRASE||WORD found: " + actualToken, e.getMessage());
}
}
-
+
private void resultsIn(String expectedSearchExpression) throws SearchTokenizerException, SearchParserException {
final SearchExpression searchExpression = getSearchExpression();
Assert.assertEquals(expectedSearchExpression, searchExpression.toString());
}
private SearchExpression getSearchExpression() throws SearchParserException, SearchTokenizerException {
- SearchParser tokenizer = new SearchParser();
- SearchOption result = tokenizer.parse(searchQuery);
+ SearchOption result = new SearchParser().parse(searchQuery);
Assert.assertNotNull(result);
final SearchExpression searchExpression = result.getSearchExpression();
Assert.assertNotNull(searchExpression);
- if (log) {
- System.out.println(searchExpression);
- }
return searchExpression;
}
}