[OLINGO-568] Added missing SearchParser parse paths
Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/cef72e45 Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/cef72e45 Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/cef72e45 Branch: refs/heads/master Commit: cef72e45ab0509310ed46c26d0c3df4a30885d5f Parents: 40962a9 Author: mibo <[email protected]> Authored: Fri Nov 13 08:16:15 2015 +0100 Committer: mibo <[email protected]> Committed: Fri Nov 13 08:16:15 2015 +0100 ---------------------------------------------------------------------- .../core/uri/parser/search/SearchParser.java | 99 +++++++++++++------- .../search/SearchParserAndTokenizerTest.java | 19 +++- .../uri/parser/search/SearchParserTest.java | 9 +- 3 files changed, 85 insertions(+), 42 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/cef72e45/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/search/SearchParser.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/search/SearchParser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/search/SearchParser.java index 25c52f2..d5109a5 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/search/SearchParser.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/search/SearchParser.java @@ -29,20 +29,20 @@ import java.util.List; public class SearchParser { private Iterator<SearchQueryToken> tokens; - private SearchExpression root; private SearchQueryToken token; public SearchOption parse(String path, String value) { SearchTokenizer tokenizer = new SearchTokenizer(); + SearchExpression searchExpression; try { tokens = tokenizer.tokenize(value).iterator(); nextToken(); - root = processSearchExpression(null); + searchExpression = processSearchExpression(null); } catch (SearchTokenizerException e) { return null; } final SearchOptionImpl searchOption = new SearchOptionImpl(); - searchOption.setSearchExpression(root); + searchOption.setSearchExpression(searchExpression); return searchOption; } @@ -57,26 +57,47 @@ public class SearchParser { return left; } - if(token.getToken() == SearchQueryToken.Token.OPEN) { + SearchExpression expression = left; + if(isToken(SearchQueryToken.Token.OPEN)) { processOpen(); - throw illegalState(); - } else if(token.getToken() == SearchQueryToken.Token.CLOSE) { - processClose(); - throw illegalState(); - } else if(token.getToken() == SearchQueryToken.Token.NOT) { - processNot(); - } else if(token.getToken() == SearchQueryToken.Token.PHRASE || - token.getToken() == SearchQueryToken.Token.WORD) { - return processSearchExpression(processTerm()); - } else if(token.getToken() == SearchQueryToken.Token.AND) { - SearchExpression se = processAnd(left); - return processSearchExpression(se); - } else if(token.getToken() == SearchQueryToken.Token.OR) { - return processOr(left); - } else { + expression = processSearchExpression(left); + validateToken(SearchQueryToken.Token.CLOSE); + processClose(); + } else if(isTerm()) { + expression = processTerm(); + } + + if(isToken(SearchQueryToken.Token.AND) || isTerm()) { + expression = processAnd(expression); + } else if(isToken(SearchQueryToken.Token.OR)) { + expression = processOr(expression); + } else if(isEof()) { + return expression; + } + return expression; + } + + private boolean isTerm() { + return isToken(SearchQueryToken.Token.NOT) + || isToken(SearchQueryToken.Token.PHRASE) + || isToken(SearchQueryToken.Token.WORD); + } + + private boolean isEof() { + return token == null; + } + + private boolean isToken(SearchQueryToken.Token toCheckToken) { + if(token == null) { + return false; + } + return token.getToken() == toCheckToken; + } + + private void validateToken(SearchQueryToken.Token toValidateToken) { + if(!isToken(toValidateToken)) { throw illegalState(); } - throw illegalState(); } private void processClose() { @@ -88,13 +109,24 @@ public class SearchParser { } private SearchExpression processAnd(SearchExpression left) { - nextToken(); - SearchExpression se = processTerm(); - return new SearchBinaryImpl(left, SearchBinaryOperatorKind.AND, se); + if(isToken(SearchQueryToken.Token.AND)) { + nextToken(); + } + SearchExpression se = left; + if(isTerm()) { + se = processTerm(); + se = new SearchBinaryImpl(left, SearchBinaryOperatorKind.AND, se); + return processSearchExpression(se); + } else { + se = processSearchExpression(se); + return new SearchBinaryImpl(left, SearchBinaryOperatorKind.AND, se); + } } public SearchExpression processOr(SearchExpression left) { - nextToken(); + if(isToken(SearchQueryToken.Token.OR)) { + nextToken(); + } SearchExpression se = processSearchExpression(left); return new SearchBinaryImpl(left, SearchBinaryOperatorKind.OR, se); } @@ -103,8 +135,13 @@ public class SearchParser { return new RuntimeException(); } - private void processNot() { + private SearchExpression processNot() { nextToken(); + SearchExpression searchExpression = processTerm(); + if(searchExpression.isSearchTerm()) { + return new SearchUnaryImpl(searchExpression.asSearchTerm()); + } + throw illegalState(); } private void nextToken() { @@ -113,20 +150,18 @@ public class SearchParser { } else { token = null; } -// return null; } private SearchExpression processTerm() { - if(token.getToken() == SearchQueryToken.Token.NOT) { - return new SearchUnaryImpl(processPhrase()); + if(isToken(SearchQueryToken.Token.NOT)) { + return processNot(); } - if(token.getToken() == SearchQueryToken.Token.PHRASE) { + if(isToken(SearchQueryToken.Token.PHRASE)) { return processPhrase(); - } - if(token.getToken() == SearchQueryToken.Token.WORD) { + } else if(isToken(SearchQueryToken.Token.WORD)) { return processWord(); } - return null; + throw illegalState(); } private SearchTermImpl processWord() { http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/cef72e45/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 3ecd517..271b617 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 @@ -34,9 +34,6 @@ public class SearchParserAndTokenizerTest { @Test public void basicParsing() throws SearchTokenizerException { -// SearchExpressionValidator.init("a AND b OR c").enableLogging() -// .validate(with("a")); - SearchExpressionValidator.init("a") .validate(with("a")); SearchExpressionValidator.init("a AND b") @@ -57,6 +54,22 @@ public class SearchParserAndTokenizerTest { .validate("{'a' OR {'b' AND 'c'}}"); } + @Test + public void notParsing() throws Exception { + SearchExpressionValidator.init("NOT a AND b OR c") + .validate("{{{NOT 'a'} AND 'b'} OR 'c'}"); + SearchExpressionValidator.init("a OR b AND NOT c") + .validate("{'a' OR {'b' AND {NOT 'c'}}}"); + } + + @Test + public void parenthesesParsing() throws Exception { + SearchExpressionValidator.init("a AND (b OR c)") + .validate("{'a' AND {'b' OR 'c'}}"); + SearchExpressionValidator.init("(a OR b) AND NOT c") + .validate("{{'a' OR 'b'} AND {NOT 'c'}}"); + } + @Ignore @Test public void sebuilder() { http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/cef72e45/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/search/SearchParserTest.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/search/SearchParserTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/search/SearchParserTest.java index ce37f3d..89b59b4 100644 --- a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/search/SearchParserTest.java +++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/search/SearchParserTest.java @@ -83,7 +83,6 @@ public class SearchParserTest extends SearchParser { assertEquals("phrase2", se.asSearchBinary().getRightOperand().asSearchTerm().getSearchTerm()); } - @Ignore @Test public void simpleImplicitAnd() { SearchExpression se = run(Token.WORD, Token.WORD); @@ -101,7 +100,6 @@ public class SearchParserTest extends SearchParser { assertEquals("phrase2", se.asSearchBinary().getRightOperand().asSearchTerm().getSearchTerm()); } - @Ignore @Test public void simpleBrackets() { SearchExpression se = run(Token.OPEN, Token.WORD, Token.CLOSE); @@ -115,7 +113,6 @@ public class SearchParserTest extends SearchParser { assertEquals("phrase1", se.asSearchTerm().getSearchTerm()); } - @Ignore @Test public void simpleNot() { SearchExpression se = run(Token.NOT, Token.WORD); @@ -123,13 +120,12 @@ public class SearchParserTest extends SearchParser { assertTrue(se.isSearchUnary()); assertEquals("word1", se.asSearchUnary().getOperand().asSearchTerm().getSearchTerm()); - se = run(Token.NOT, Token.WORD); - assertEquals("'phrase1'", se.toString()); + se = run(Token.NOT, Token.PHRASE); + assertEquals("{NOT 'phrase1'}", se.toString()); assertTrue(se.isSearchUnary()); assertEquals("phrase1", se.asSearchUnary().getOperand().asSearchTerm().getSearchTerm()); } - @Ignore @Test public void precedenceLast() { //word1 AND (word2 AND word3) @@ -137,7 +133,6 @@ public class SearchParserTest extends SearchParser { assertEquals("{'word1' AND {'word2' AND 'word3'}}", se.toString()); } - @Ignore @Test public void precedenceFirst() { //(word1 AND word2) AND word3
