From 266e0f636251ccc754a2d89a7963927df998cda1 Mon Sep 17 00:00:00 2001 From: Shivasurya Date: Fri, 2 Aug 2024 20:51:54 -0400 Subject: [PATCH] Enhanced query parser: Added ANTLR parser for query lang (#49) * Added ANTLR parser for query lang - Now query parsing and conversion should be handled by ANTLR defined grammar * Added robust condition based filtering support * Stage 1: Commit for preserving last changes * Added expr-lang with antlr expr-lang helps in evaluating conditions and antlr in parsing query * incorporating antlr replacing query parser and condition eval * hooked antlr expression, alias, select into entity filtering This is now effectively bridged between ANTLR parser and Source Code struct * make lint happy :smile: * make test happy again :rocket: * Fix go version * Add few more testcases * Mapped filtering methods to the expr-lang :rocket: * Create alias based method invocation * Added progress bar and multiple workers to parse the source code * few cleanup * Update query entity to include the methods * Update query methods * Add few testcase and make lint happy * Add testcase files --- .github/workflows/build.yml | 2 +- .gitignore | 1 - sourcecode-parser/antlr/Query.g4 | 25 + sourcecode-parser/antlr/Query.interp | 72 + sourcecode-parser/antlr/Query.tokens | 39 + sourcecode-parser/antlr/QueryLexer.interp | 83 + sourcecode-parser/antlr/QueryLexer.tokens | 39 + sourcecode-parser/antlr/listener_impl.go | 93 + .../antlr/query_base_listener.go | 124 + sourcecode-parser/antlr/query_lexer.go | 187 ++ sourcecode-parser/antlr/query_listener.go | 112 + sourcecode-parser/antlr/query_parser.go | 2528 +++++++++++++++++ sourcecode-parser/api.go | 50 - sourcecode-parser/construct.go | 149 +- sourcecode-parser/go.mod | 11 +- sourcecode-parser/go.sum | 17 +- sourcecode-parser/go.work | 7 +- sourcecode-parser/go.work.sum | 23 +- sourcecode-parser/main.go | 189 +- sourcecode-parser/main_test.go | 90 +- sourcecode-parser/query.go | 240 ++ sourcecode-parser/queryparser/go.mod | 3 - sourcecode-parser/queryparser/lexer.go | 90 - sourcecode-parser/queryparser/parser.go | 178 -- sourcecode-parser/queryparser/tokenizer.go | 79 - sourcecode-parser/source_sink.go | 152 - .../android/app/src/main/AndroidManifest.xml | 33 + .../udacity/adapter/movieGeneralAdapter.java | 86 + .../udacity/adapter/movieGeneralHolder.java | 34 + .../com/ivb/udacity/constants/constant.java | 8 + .../database/favouritesSqliteHelper.java | 91 + .../java/com/ivb/udacity/modal/Results.java | 153 + .../com/ivb/udacity/modal/movieGeneral.java | 53 + .../ivb/udacity/modal/movieGeneralModal.java | 63 + .../com/ivb/udacity/modal/review/Results.java | 51 + .../ivb/udacity/modal/review/movieReview.java | 61 + .../ivb/udacity/modal/trailer/Results.java | 81 + .../modal/trailer/movieYoutubeModal.java | 32 + .../com/ivb/udacity/movieDetailActivity.java | 63 + .../com/ivb/udacity/movieDetailFragment.java | 266 ++ .../com/ivb/udacity/movieListActivity.java | 239 ++ .../com/ivb/udacity/network/MovieAPI.java | 40 + .../com/ivb/udacity/network/NetworkAPI.java | 22 + .../app/src/main/res/drawable/calendar.png | Bin 0 -> 304 bytes .../app/src/main/res/drawable/groups.png | Bin 0 -> 416 bytes .../app/src/main/res/drawable/ic_action.png | Bin 0 -> 1675 bytes .../app/src/main/res/drawable/ic_launcher.png | Bin 0 -> 3205 bytes .../app/src/main/res/drawable/menu_main.png | Bin 0 -> 385 bytes .../app/src/main/res/drawable/mqdefault.jpg | Bin 0 -> 13058 bytes .../app/src/main/res/drawable/review.png | Bin 0 -> 479 bytes .../src/main/res/layout-w900dp/movie_list.xml | 36 + .../main/res/layout/activity_movie_detail.xml | 14 + .../main/res/layout/activity_movie_list.xml | 46 + .../app/src/main/res/layout/movie_cards.xml | 47 + .../app/src/main/res/layout/movie_detail.xml | 252 ++ .../app/src/main/res/layout/movie_list.xml | 10 + .../android/app/src/main/res/menu/detail.xml | 9 + .../android/app/src/main/res/menu/main.xml | 9 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 550 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 366 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 726 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 1316 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 1813 bytes .../app/src/main/res/values-v21/styles.xml | 9 + .../app/src/main/res/values-w820dp/dimens.xml | 6 + .../app/src/main/res/values/colors.xml | 18 + .../app/src/main/res/values/dimens.xml | 9 + .../app/src/main/res/values/strings.xml | 20 + .../app/src/main/res/values/styles.xml | 27 + 69 files changed, 5768 insertions(+), 703 deletions(-) create mode 100644 sourcecode-parser/antlr/Query.g4 create mode 100644 sourcecode-parser/antlr/Query.interp create mode 100644 sourcecode-parser/antlr/Query.tokens create mode 100644 sourcecode-parser/antlr/QueryLexer.interp create mode 100644 sourcecode-parser/antlr/QueryLexer.tokens create mode 100644 sourcecode-parser/antlr/listener_impl.go create mode 100644 sourcecode-parser/antlr/query_base_listener.go create mode 100644 sourcecode-parser/antlr/query_lexer.go create mode 100644 sourcecode-parser/antlr/query_listener.go create mode 100644 sourcecode-parser/antlr/query_parser.go delete mode 100644 sourcecode-parser/api.go create mode 100644 sourcecode-parser/query.go delete mode 100644 sourcecode-parser/queryparser/go.mod delete mode 100644 sourcecode-parser/queryparser/lexer.go delete mode 100644 sourcecode-parser/queryparser/parser.go delete mode 100644 sourcecode-parser/queryparser/tokenizer.go create mode 100644 test-src/android/app/src/main/AndroidManifest.xml create mode 100644 test-src/android/app/src/main/java/com/ivb/udacity/adapter/movieGeneralAdapter.java create mode 100644 test-src/android/app/src/main/java/com/ivb/udacity/adapter/movieGeneralHolder.java create mode 100644 test-src/android/app/src/main/java/com/ivb/udacity/constants/constant.java create mode 100644 test-src/android/app/src/main/java/com/ivb/udacity/database/favouritesSqliteHelper.java create mode 100644 test-src/android/app/src/main/java/com/ivb/udacity/modal/Results.java create mode 100644 test-src/android/app/src/main/java/com/ivb/udacity/modal/movieGeneral.java create mode 100644 test-src/android/app/src/main/java/com/ivb/udacity/modal/movieGeneralModal.java create mode 100644 test-src/android/app/src/main/java/com/ivb/udacity/modal/review/Results.java create mode 100644 test-src/android/app/src/main/java/com/ivb/udacity/modal/review/movieReview.java create mode 100644 test-src/android/app/src/main/java/com/ivb/udacity/modal/trailer/Results.java create mode 100644 test-src/android/app/src/main/java/com/ivb/udacity/modal/trailer/movieYoutubeModal.java create mode 100644 test-src/android/app/src/main/java/com/ivb/udacity/movieDetailActivity.java create mode 100644 test-src/android/app/src/main/java/com/ivb/udacity/movieDetailFragment.java create mode 100644 test-src/android/app/src/main/java/com/ivb/udacity/movieListActivity.java create mode 100644 test-src/android/app/src/main/java/com/ivb/udacity/network/MovieAPI.java create mode 100644 test-src/android/app/src/main/java/com/ivb/udacity/network/NetworkAPI.java create mode 100644 test-src/android/app/src/main/res/drawable/calendar.png create mode 100644 test-src/android/app/src/main/res/drawable/groups.png create mode 100644 test-src/android/app/src/main/res/drawable/ic_action.png create mode 100644 test-src/android/app/src/main/res/drawable/ic_launcher.png create mode 100644 test-src/android/app/src/main/res/drawable/menu_main.png create mode 100644 test-src/android/app/src/main/res/drawable/mqdefault.jpg create mode 100644 test-src/android/app/src/main/res/drawable/review.png create mode 100644 test-src/android/app/src/main/res/layout-w900dp/movie_list.xml create mode 100644 test-src/android/app/src/main/res/layout/activity_movie_detail.xml create mode 100644 test-src/android/app/src/main/res/layout/activity_movie_list.xml create mode 100644 test-src/android/app/src/main/res/layout/movie_cards.xml create mode 100644 test-src/android/app/src/main/res/layout/movie_detail.xml create mode 100644 test-src/android/app/src/main/res/layout/movie_list.xml create mode 100644 test-src/android/app/src/main/res/menu/detail.xml create mode 100644 test-src/android/app/src/main/res/menu/main.xml create mode 100644 test-src/android/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 test-src/android/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 test-src/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 test-src/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 test-src/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 test-src/android/app/src/main/res/values-v21/styles.xml create mode 100644 test-src/android/app/src/main/res/values-w820dp/dimens.xml create mode 100644 test-src/android/app/src/main/res/values/colors.xml create mode 100644 test-src/android/app/src/main/res/values/dimens.xml create mode 100644 test-src/android/app/src/main/res/values/strings.xml create mode 100644 test-src/android/app/src/main/res/values/styles.xml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bc778a2..2f1d564 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -14,7 +14,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v4 with: - go-version: '1.20' + go-version: '1.22.0' - name: Check out code uses: actions/checkout@v3 diff --git a/.gitignore b/.gitignore index e492922..32db93e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ example-java-project/ -main sourcecode-parser/pathfinder .idea/ .gradle/ diff --git a/sourcecode-parser/antlr/Query.g4 b/sourcecode-parser/antlr/Query.g4 new file mode 100644 index 0000000..fc1cb31 --- /dev/null +++ b/sourcecode-parser/antlr/Query.g4 @@ -0,0 +1,25 @@ +grammar Query; + +query : 'FIND' select_list ('WHERE' expression)? ; +select_list : select_item (',' select_item)* ; +select_item : entity 'AS' alias ; +entity : IDENTIFIER ; +alias : IDENTIFIER ; +expression : orExpression ; +orExpression : andExpression ( '||' andExpression )* ; +andExpression : primary ( '&&' primary )* ; +primary : condition + | '(' expression ')' ; +condition : alias '.' method_chain comparator (value | method_chain | '(' value_list ')') ; +method_chain : method_or_variable ('.' method_or_variable)* ; +method_or_variable : method | variable ; +method : IDENTIFIER '(' ')' ; +variable : IDENTIFIER ; +comparator : '==' | '!=' | '<' | '>' | '<=' | '>=' | 'LIKE' | 'IN' ; +value : STRING | NUMBER | STRING_WITH_WILDCARD ; +value_list : value (',' value)* ; +STRING : '"' ( ~('"' | '\\') | '\\' . )* '"' ; +STRING_WITH_WILDCARD : '"' ( ~('"' | '\\') | '\\' . | '%' )* '"' ; +NUMBER : [0-9]+ ('.' [0-9]+)? ; +IDENTIFIER : [a-zA-Z_][a-zA-Z0-9_]* ; +WS : [ \t\r\n]+ -> skip ; diff --git a/sourcecode-parser/antlr/Query.interp b/sourcecode-parser/antlr/Query.interp new file mode 100644 index 0000000..0e8e493 --- /dev/null +++ b/sourcecode-parser/antlr/Query.interp @@ -0,0 +1,72 @@ +token literal names: +null +'FIND' +'WHERE' +',' +'AS' +'||' +'&&' +'(' +')' +'.' +'==' +'!=' +'<' +'>' +'<=' +'>=' +'LIKE' +'IN' +null +null +null +null +null + +token symbolic names: +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +STRING +STRING_WITH_WILDCARD +NUMBER +IDENTIFIER +WS + +rule names: +query +select_list +select_item +entity +alias +expression +orExpression +andExpression +primary +condition +method_chain +method_or_variable +method +variable +comparator +value +value_list + + +atn: +[4, 1, 22, 124, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 1, 0, 1, 0, 1, 0, 1, 0, 3, 0, 39, 8, 0, 1, 1, 1, 1, 1, 1, 5, 1, 44, 8, 1, 10, 1, 12, 1, 47, 9, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 4, 1, 4, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 5, 6, 62, 8, 6, 10, 6, 12, 6, 65, 9, 6, 1, 7, 1, 7, 1, 7, 5, 7, 70, 8, 7, 10, 7, 12, 7, 73, 9, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 3, 8, 80, 8, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 3, 9, 92, 8, 9, 1, 10, 1, 10, 1, 10, 5, 10, 97, 8, 10, 10, 10, 12, 10, 100, 9, 10, 1, 11, 1, 11, 3, 11, 104, 8, 11, 1, 12, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 14, 1, 14, 1, 15, 1, 15, 1, 16, 1, 16, 1, 16, 5, 16, 119, 8, 16, 10, 16, 12, 16, 122, 9, 16, 1, 16, 0, 0, 17, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 0, 2, 1, 0, 10, 17, 1, 0, 18, 20, 116, 0, 34, 1, 0, 0, 0, 2, 40, 1, 0, 0, 0, 4, 48, 1, 0, 0, 0, 6, 52, 1, 0, 0, 0, 8, 54, 1, 0, 0, 0, 10, 56, 1, 0, 0, 0, 12, 58, 1, 0, 0, 0, 14, 66, 1, 0, 0, 0, 16, 79, 1, 0, 0, 0, 18, 81, 1, 0, 0, 0, 20, 93, 1, 0, 0, 0, 22, 103, 1, 0, 0, 0, 24, 105, 1, 0, 0, 0, 26, 109, 1, 0, 0, 0, 28, 111, 1, 0, 0, 0, 30, 113, 1, 0, 0, 0, 32, 115, 1, 0, 0, 0, 34, 35, 5, 1, 0, 0, 35, 38, 3, 2, 1, 0, 36, 37, 5, 2, 0, 0, 37, 39, 3, 10, 5, 0, 38, 36, 1, 0, 0, 0, 38, 39, 1, 0, 0, 0, 39, 1, 1, 0, 0, 0, 40, 45, 3, 4, 2, 0, 41, 42, 5, 3, 0, 0, 42, 44, 3, 4, 2, 0, 43, 41, 1, 0, 0, 0, 44, 47, 1, 0, 0, 0, 45, 43, 1, 0, 0, 0, 45, 46, 1, 0, 0, 0, 46, 3, 1, 0, 0, 0, 47, 45, 1, 0, 0, 0, 48, 49, 3, 6, 3, 0, 49, 50, 5, 4, 0, 0, 50, 51, 3, 8, 4, 0, 51, 5, 1, 0, 0, 0, 52, 53, 5, 21, 0, 0, 53, 7, 1, 0, 0, 0, 54, 55, 5, 21, 0, 0, 55, 9, 1, 0, 0, 0, 56, 57, 3, 12, 6, 0, 57, 11, 1, 0, 0, 0, 58, 63, 3, 14, 7, 0, 59, 60, 5, 5, 0, 0, 60, 62, 3, 14, 7, 0, 61, 59, 1, 0, 0, 0, 62, 65, 1, 0, 0, 0, 63, 61, 1, 0, 0, 0, 63, 64, 1, 0, 0, 0, 64, 13, 1, 0, 0, 0, 65, 63, 1, 0, 0, 0, 66, 71, 3, 16, 8, 0, 67, 68, 5, 6, 0, 0, 68, 70, 3, 16, 8, 0, 69, 67, 1, 0, 0, 0, 70, 73, 1, 0, 0, 0, 71, 69, 1, 0, 0, 0, 71, 72, 1, 0, 0, 0, 72, 15, 1, 0, 0, 0, 73, 71, 1, 0, 0, 0, 74, 80, 3, 18, 9, 0, 75, 76, 5, 7, 0, 0, 76, 77, 3, 10, 5, 0, 77, 78, 5, 8, 0, 0, 78, 80, 1, 0, 0, 0, 79, 74, 1, 0, 0, 0, 79, 75, 1, 0, 0, 0, 80, 17, 1, 0, 0, 0, 81, 82, 3, 8, 4, 0, 82, 83, 5, 9, 0, 0, 83, 84, 3, 20, 10, 0, 84, 91, 3, 28, 14, 0, 85, 92, 3, 30, 15, 0, 86, 92, 3, 20, 10, 0, 87, 88, 5, 7, 0, 0, 88, 89, 3, 32, 16, 0, 89, 90, 5, 8, 0, 0, 90, 92, 1, 0, 0, 0, 91, 85, 1, 0, 0, 0, 91, 86, 1, 0, 0, 0, 91, 87, 1, 0, 0, 0, 92, 19, 1, 0, 0, 0, 93, 98, 3, 22, 11, 0, 94, 95, 5, 9, 0, 0, 95, 97, 3, 22, 11, 0, 96, 94, 1, 0, 0, 0, 97, 100, 1, 0, 0, 0, 98, 96, 1, 0, 0, 0, 98, 99, 1, 0, 0, 0, 99, 21, 1, 0, 0, 0, 100, 98, 1, 0, 0, 0, 101, 104, 3, 24, 12, 0, 102, 104, 3, 26, 13, 0, 103, 101, 1, 0, 0, 0, 103, 102, 1, 0, 0, 0, 104, 23, 1, 0, 0, 0, 105, 106, 5, 21, 0, 0, 106, 107, 5, 7, 0, 0, 107, 108, 5, 8, 0, 0, 108, 25, 1, 0, 0, 0, 109, 110, 5, 21, 0, 0, 110, 27, 1, 0, 0, 0, 111, 112, 7, 0, 0, 0, 112, 29, 1, 0, 0, 0, 113, 114, 7, 1, 0, 0, 114, 31, 1, 0, 0, 0, 115, 120, 3, 30, 15, 0, 116, 117, 5, 3, 0, 0, 117, 119, 3, 30, 15, 0, 118, 116, 1, 0, 0, 0, 119, 122, 1, 0, 0, 0, 120, 118, 1, 0, 0, 0, 120, 121, 1, 0, 0, 0, 121, 33, 1, 0, 0, 0, 122, 120, 1, 0, 0, 0, 9, 38, 45, 63, 71, 79, 91, 98, 103, 120] \ No newline at end of file diff --git a/sourcecode-parser/antlr/Query.tokens b/sourcecode-parser/antlr/Query.tokens new file mode 100644 index 0000000..aa6805e --- /dev/null +++ b/sourcecode-parser/antlr/Query.tokens @@ -0,0 +1,39 @@ +T__0=1 +T__1=2 +T__2=3 +T__3=4 +T__4=5 +T__5=6 +T__6=7 +T__7=8 +T__8=9 +T__9=10 +T__10=11 +T__11=12 +T__12=13 +T__13=14 +T__14=15 +T__15=16 +T__16=17 +STRING=18 +STRING_WITH_WILDCARD=19 +NUMBER=20 +IDENTIFIER=21 +WS=22 +'FIND'=1 +'WHERE'=2 +','=3 +'AS'=4 +'||'=5 +'&&'=6 +'('=7 +')'=8 +'.'=9 +'=='=10 +'!='=11 +'<'=12 +'>'=13 +'<='=14 +'>='=15 +'LIKE'=16 +'IN'=17 diff --git a/sourcecode-parser/antlr/QueryLexer.interp b/sourcecode-parser/antlr/QueryLexer.interp new file mode 100644 index 0000000..5ea6f50 --- /dev/null +++ b/sourcecode-parser/antlr/QueryLexer.interp @@ -0,0 +1,83 @@ +token literal names: +null +'FIND' +'WHERE' +',' +'AS' +'||' +'&&' +'(' +')' +'.' +'==' +'!=' +'<' +'>' +'<=' +'>=' +'LIKE' +'IN' +null +null +null +null +null + +token symbolic names: +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +STRING +STRING_WITH_WILDCARD +NUMBER +IDENTIFIER +WS + +rule names: +T__0 +T__1 +T__2 +T__3 +T__4 +T__5 +T__6 +T__7 +T__8 +T__9 +T__10 +T__11 +T__12 +T__13 +T__14 +T__15 +T__16 +STRING +STRING_WITH_WILDCARD +NUMBER +IDENTIFIER +WS + +channel names: +DEFAULT_TOKEN_CHANNEL +HIDDEN + +mode names: +DEFAULT_MODE + +atn: +[4, 0, 22, 147, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 7, 1, 7, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 14, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 16, 1, 17, 1, 17, 1, 17, 1, 17, 5, 17, 102, 8, 17, 10, 17, 12, 17, 105, 9, 17, 1, 17, 1, 17, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 5, 18, 114, 8, 18, 10, 18, 12, 18, 117, 9, 18, 1, 18, 1, 18, 1, 19, 4, 19, 122, 8, 19, 11, 19, 12, 19, 123, 1, 19, 1, 19, 4, 19, 128, 8, 19, 11, 19, 12, 19, 129, 3, 19, 132, 8, 19, 1, 20, 1, 20, 5, 20, 136, 8, 20, 10, 20, 12, 20, 139, 9, 20, 1, 21, 4, 21, 142, 8, 21, 11, 21, 12, 21, 143, 1, 21, 1, 21, 0, 0, 22, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 21, 11, 23, 12, 25, 13, 27, 14, 29, 15, 31, 16, 33, 17, 35, 18, 37, 19, 39, 20, 41, 21, 43, 22, 1, 0, 5, 2, 0, 34, 34, 92, 92, 1, 0, 48, 57, 3, 0, 65, 90, 95, 95, 97, 122, 4, 0, 48, 57, 65, 90, 95, 95, 97, 122, 3, 0, 9, 10, 13, 13, 32, 32, 156, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, 0, 0, 0, 0, 39, 1, 0, 0, 0, 0, 41, 1, 0, 0, 0, 0, 43, 1, 0, 0, 0, 1, 45, 1, 0, 0, 0, 3, 50, 1, 0, 0, 0, 5, 56, 1, 0, 0, 0, 7, 58, 1, 0, 0, 0, 9, 61, 1, 0, 0, 0, 11, 64, 1, 0, 0, 0, 13, 67, 1, 0, 0, 0, 15, 69, 1, 0, 0, 0, 17, 71, 1, 0, 0, 0, 19, 73, 1, 0, 0, 0, 21, 76, 1, 0, 0, 0, 23, 79, 1, 0, 0, 0, 25, 81, 1, 0, 0, 0, 27, 83, 1, 0, 0, 0, 29, 86, 1, 0, 0, 0, 31, 89, 1, 0, 0, 0, 33, 94, 1, 0, 0, 0, 35, 97, 1, 0, 0, 0, 37, 108, 1, 0, 0, 0, 39, 121, 1, 0, 0, 0, 41, 133, 1, 0, 0, 0, 43, 141, 1, 0, 0, 0, 45, 46, 5, 70, 0, 0, 46, 47, 5, 73, 0, 0, 47, 48, 5, 78, 0, 0, 48, 49, 5, 68, 0, 0, 49, 2, 1, 0, 0, 0, 50, 51, 5, 87, 0, 0, 51, 52, 5, 72, 0, 0, 52, 53, 5, 69, 0, 0, 53, 54, 5, 82, 0, 0, 54, 55, 5, 69, 0, 0, 55, 4, 1, 0, 0, 0, 56, 57, 5, 44, 0, 0, 57, 6, 1, 0, 0, 0, 58, 59, 5, 65, 0, 0, 59, 60, 5, 83, 0, 0, 60, 8, 1, 0, 0, 0, 61, 62, 5, 124, 0, 0, 62, 63, 5, 124, 0, 0, 63, 10, 1, 0, 0, 0, 64, 65, 5, 38, 0, 0, 65, 66, 5, 38, 0, 0, 66, 12, 1, 0, 0, 0, 67, 68, 5, 40, 0, 0, 68, 14, 1, 0, 0, 0, 69, 70, 5, 41, 0, 0, 70, 16, 1, 0, 0, 0, 71, 72, 5, 46, 0, 0, 72, 18, 1, 0, 0, 0, 73, 74, 5, 61, 0, 0, 74, 75, 5, 61, 0, 0, 75, 20, 1, 0, 0, 0, 76, 77, 5, 33, 0, 0, 77, 78, 5, 61, 0, 0, 78, 22, 1, 0, 0, 0, 79, 80, 5, 60, 0, 0, 80, 24, 1, 0, 0, 0, 81, 82, 5, 62, 0, 0, 82, 26, 1, 0, 0, 0, 83, 84, 5, 60, 0, 0, 84, 85, 5, 61, 0, 0, 85, 28, 1, 0, 0, 0, 86, 87, 5, 62, 0, 0, 87, 88, 5, 61, 0, 0, 88, 30, 1, 0, 0, 0, 89, 90, 5, 76, 0, 0, 90, 91, 5, 73, 0, 0, 91, 92, 5, 75, 0, 0, 92, 93, 5, 69, 0, 0, 93, 32, 1, 0, 0, 0, 94, 95, 5, 73, 0, 0, 95, 96, 5, 78, 0, 0, 96, 34, 1, 0, 0, 0, 97, 103, 5, 34, 0, 0, 98, 102, 8, 0, 0, 0, 99, 100, 5, 92, 0, 0, 100, 102, 9, 0, 0, 0, 101, 98, 1, 0, 0, 0, 101, 99, 1, 0, 0, 0, 102, 105, 1, 0, 0, 0, 103, 101, 1, 0, 0, 0, 103, 104, 1, 0, 0, 0, 104, 106, 1, 0, 0, 0, 105, 103, 1, 0, 0, 0, 106, 107, 5, 34, 0, 0, 107, 36, 1, 0, 0, 0, 108, 115, 5, 34, 0, 0, 109, 114, 8, 0, 0, 0, 110, 111, 5, 92, 0, 0, 111, 114, 9, 0, 0, 0, 112, 114, 5, 37, 0, 0, 113, 109, 1, 0, 0, 0, 113, 110, 1, 0, 0, 0, 113, 112, 1, 0, 0, 0, 114, 117, 1, 0, 0, 0, 115, 113, 1, 0, 0, 0, 115, 116, 1, 0, 0, 0, 116, 118, 1, 0, 0, 0, 117, 115, 1, 0, 0, 0, 118, 119, 5, 34, 0, 0, 119, 38, 1, 0, 0, 0, 120, 122, 7, 1, 0, 0, 121, 120, 1, 0, 0, 0, 122, 123, 1, 0, 0, 0, 123, 121, 1, 0, 0, 0, 123, 124, 1, 0, 0, 0, 124, 131, 1, 0, 0, 0, 125, 127, 5, 46, 0, 0, 126, 128, 7, 1, 0, 0, 127, 126, 1, 0, 0, 0, 128, 129, 1, 0, 0, 0, 129, 127, 1, 0, 0, 0, 129, 130, 1, 0, 0, 0, 130, 132, 1, 0, 0, 0, 131, 125, 1, 0, 0, 0, 131, 132, 1, 0, 0, 0, 132, 40, 1, 0, 0, 0, 133, 137, 7, 2, 0, 0, 134, 136, 7, 3, 0, 0, 135, 134, 1, 0, 0, 0, 136, 139, 1, 0, 0, 0, 137, 135, 1, 0, 0, 0, 137, 138, 1, 0, 0, 0, 138, 42, 1, 0, 0, 0, 139, 137, 1, 0, 0, 0, 140, 142, 7, 4, 0, 0, 141, 140, 1, 0, 0, 0, 142, 143, 1, 0, 0, 0, 143, 141, 1, 0, 0, 0, 143, 144, 1, 0, 0, 0, 144, 145, 1, 0, 0, 0, 145, 146, 6, 21, 0, 0, 146, 44, 1, 0, 0, 0, 10, 0, 101, 103, 113, 115, 123, 129, 131, 137, 143, 1, 6, 0, 0] \ No newline at end of file diff --git a/sourcecode-parser/antlr/QueryLexer.tokens b/sourcecode-parser/antlr/QueryLexer.tokens new file mode 100644 index 0000000..aa6805e --- /dev/null +++ b/sourcecode-parser/antlr/QueryLexer.tokens @@ -0,0 +1,39 @@ +T__0=1 +T__1=2 +T__2=3 +T__3=4 +T__4=5 +T__5=6 +T__6=7 +T__7=8 +T__8=9 +T__9=10 +T__10=11 +T__11=12 +T__12=13 +T__13=14 +T__14=15 +T__15=16 +T__16=17 +STRING=18 +STRING_WITH_WILDCARD=19 +NUMBER=20 +IDENTIFIER=21 +WS=22 +'FIND'=1 +'WHERE'=2 +','=3 +'AS'=4 +'||'=5 +'&&'=6 +'('=7 +')'=8 +'.'=9 +'=='=10 +'!='=11 +'<'=12 +'>'=13 +'<='=14 +'>='=15 +'LIKE'=16 +'IN'=17 diff --git a/sourcecode-parser/antlr/listener_impl.go b/sourcecode-parser/antlr/listener_impl.go new file mode 100644 index 0000000..e909ef9 --- /dev/null +++ b/sourcecode-parser/antlr/listener_impl.go @@ -0,0 +1,93 @@ +package parser + +import ( + "strings" + + "github.com/antlr4-go/antlr/v4" +) + +type Query struct { + SelectList []SelectList + Expression string +} + +type CustomQueryListener struct { + BaseQueryListener + expression strings.Builder + selectList []SelectList +} + +type SelectList struct { + Entity string + Alias string +} + +func NewCustomQueryListener() *CustomQueryListener { + return &CustomQueryListener{ + BaseQueryListener: BaseQueryListener{}, + } +} + +//nolint:all +func (l *CustomQueryListener) EnterSelect_list(ctx *Select_listContext) { + for i := 0; i < ctx.GetChildCount(); i++ { + child := ctx.GetChild(i).(antlr.ParseTree) + if child, ok := child.(ISelect_itemContext); ok { + l.selectList = append(l.selectList, SelectList{ + Entity: child.Entity().GetText(), + Alias: child.Alias().GetText(), + }) + } + } +} + +func (l *CustomQueryListener) EnterExpression(ctx *ExpressionContext) { + if l.expression.Len() > 0 { + l.expression.WriteString(" ") + } + l.expression.WriteString(ctx.GetText()) +} + +func (l *CustomQueryListener) ExitOrExpression(ctx *OrExpressionContext) { + if ctx.GetChildCount() > 1 { + var result strings.Builder + for i := 0; i < ctx.GetChildCount(); i++ { + child := ctx.GetChild(i).(antlr.ParseTree) //nolint:all + if child.GetText() == "||" { + result.WriteString(" || ") + } else { + result.WriteString(child.GetText()) + } + } + l.expression.Reset() + l.expression.WriteString(result.String()) + } +} + +func (l *CustomQueryListener) ExitAndExpression(ctx *AndExpressionContext) { + if ctx.GetChildCount() > 1 { + var result strings.Builder + for i := 0; i < ctx.GetChildCount(); i++ { + child := ctx.GetChild(i).(antlr.ParseTree) //nolint:all + if child.GetText() == "&&" { + result.WriteString(" && ") + } else { + result.WriteString(child.GetText()) + } + } + l.expression.Reset() + l.expression.WriteString(result.String()) + } +} + +func ParseQuery(inputQuery string) Query { + inputStream := antlr.NewInputStream(inputQuery) + lexer := NewQueryLexer(inputStream) + stream := antlr.NewCommonTokenStream(lexer, antlr.TokenDefaultChannel) + p := NewQueryParser(stream) + + listener := NewCustomQueryListener() + antlr.ParseTreeWalkerDefault.Walk(listener, p.Query()) + + return Query{SelectList: listener.selectList, Expression: listener.expression.String()} +} diff --git a/sourcecode-parser/antlr/query_base_listener.go b/sourcecode-parser/antlr/query_base_listener.go new file mode 100644 index 0000000..d44a8d9 --- /dev/null +++ b/sourcecode-parser/antlr/query_base_listener.go @@ -0,0 +1,124 @@ +// Code generated from Query.g4 by ANTLR 4.13.1. DO NOT EDIT. + +package parser // Query + +import "github.com/antlr4-go/antlr/v4" + +// BaseQueryListener is a complete listener for a parse tree produced by QueryParser. +type BaseQueryListener struct{} + +var _ QueryListener = &BaseQueryListener{} + +// VisitTerminal is called when a terminal node is visited. +func (s *BaseQueryListener) VisitTerminal(node antlr.TerminalNode) {} + +// VisitErrorNode is called when an error node is visited. +func (s *BaseQueryListener) VisitErrorNode(node antlr.ErrorNode) {} + +// EnterEveryRule is called when any rule is entered. +func (s *BaseQueryListener) EnterEveryRule(ctx antlr.ParserRuleContext) {} + +// ExitEveryRule is called when any rule is exited. +func (s *BaseQueryListener) ExitEveryRule(ctx antlr.ParserRuleContext) {} + +// EnterQuery is called when production query is entered. +func (s *BaseQueryListener) EnterQuery(ctx *QueryContext) {} + +// ExitQuery is called when production query is exited. +func (s *BaseQueryListener) ExitQuery(ctx *QueryContext) {} + +// EnterSelect_list is called when production select_list is entered. +func (s *BaseQueryListener) EnterSelect_list(ctx *Select_listContext) {} + +// ExitSelect_list is called when production select_list is exited. +func (s *BaseQueryListener) ExitSelect_list(ctx *Select_listContext) {} + +// EnterSelect_item is called when production select_item is entered. +func (s *BaseQueryListener) EnterSelect_item(ctx *Select_itemContext) {} + +// ExitSelect_item is called when production select_item is exited. +func (s *BaseQueryListener) ExitSelect_item(ctx *Select_itemContext) {} + +// EnterEntity is called when production entity is entered. +func (s *BaseQueryListener) EnterEntity(ctx *EntityContext) {} + +// ExitEntity is called when production entity is exited. +func (s *BaseQueryListener) ExitEntity(ctx *EntityContext) {} + +// EnterAlias is called when production alias is entered. +func (s *BaseQueryListener) EnterAlias(ctx *AliasContext) {} + +// ExitAlias is called when production alias is exited. +func (s *BaseQueryListener) ExitAlias(ctx *AliasContext) {} + +// EnterExpression is called when production expression is entered. +func (s *BaseQueryListener) EnterExpression(ctx *ExpressionContext) {} + +// ExitExpression is called when production expression is exited. +func (s *BaseQueryListener) ExitExpression(ctx *ExpressionContext) {} + +// EnterOrExpression is called when production orExpression is entered. +func (s *BaseQueryListener) EnterOrExpression(ctx *OrExpressionContext) {} + +// ExitOrExpression is called when production orExpression is exited. +func (s *BaseQueryListener) ExitOrExpression(ctx *OrExpressionContext) {} + +// EnterAndExpression is called when production andExpression is entered. +func (s *BaseQueryListener) EnterAndExpression(ctx *AndExpressionContext) {} + +// ExitAndExpression is called when production andExpression is exited. +func (s *BaseQueryListener) ExitAndExpression(ctx *AndExpressionContext) {} + +// EnterPrimary is called when production primary is entered. +func (s *BaseQueryListener) EnterPrimary(ctx *PrimaryContext) {} + +// ExitPrimary is called when production primary is exited. +func (s *BaseQueryListener) ExitPrimary(ctx *PrimaryContext) {} + +// EnterCondition is called when production condition is entered. +func (s *BaseQueryListener) EnterCondition(ctx *ConditionContext) {} + +// ExitCondition is called when production condition is exited. +func (s *BaseQueryListener) ExitCondition(ctx *ConditionContext) {} + +// EnterMethod_chain is called when production method_chain is entered. +func (s *BaseQueryListener) EnterMethod_chain(ctx *Method_chainContext) {} + +// ExitMethod_chain is called when production method_chain is exited. +func (s *BaseQueryListener) ExitMethod_chain(ctx *Method_chainContext) {} + +// EnterMethod_or_variable is called when production method_or_variable is entered. +func (s *BaseQueryListener) EnterMethod_or_variable(ctx *Method_or_variableContext) {} + +// ExitMethod_or_variable is called when production method_or_variable is exited. +func (s *BaseQueryListener) ExitMethod_or_variable(ctx *Method_or_variableContext) {} + +// EnterMethod is called when production method is entered. +func (s *BaseQueryListener) EnterMethod(ctx *MethodContext) {} + +// ExitMethod is called when production method is exited. +func (s *BaseQueryListener) ExitMethod(ctx *MethodContext) {} + +// EnterVariable is called when production variable is entered. +func (s *BaseQueryListener) EnterVariable(ctx *VariableContext) {} + +// ExitVariable is called when production variable is exited. +func (s *BaseQueryListener) ExitVariable(ctx *VariableContext) {} + +// EnterComparator is called when production comparator is entered. +func (s *BaseQueryListener) EnterComparator(ctx *ComparatorContext) {} + +// ExitComparator is called when production comparator is exited. +func (s *BaseQueryListener) ExitComparator(ctx *ComparatorContext) {} + +// EnterValue is called when production value is entered. +func (s *BaseQueryListener) EnterValue(ctx *ValueContext) {} + +// ExitValue is called when production value is exited. +func (s *BaseQueryListener) ExitValue(ctx *ValueContext) {} + +// EnterValue_list is called when production value_list is entered. +func (s *BaseQueryListener) EnterValue_list(ctx *Value_listContext) {} + +// ExitValue_list is called when production value_list is exited. +func (s *BaseQueryListener) ExitValue_list(ctx *Value_listContext) {} diff --git a/sourcecode-parser/antlr/query_lexer.go b/sourcecode-parser/antlr/query_lexer.go new file mode 100644 index 0000000..fb03e7e --- /dev/null +++ b/sourcecode-parser/antlr/query_lexer.go @@ -0,0 +1,187 @@ +// Code generated from Query.g4 by ANTLR 4.13.1. DO NOT EDIT. + +package parser + +import ( + "fmt" + "github.com/antlr4-go/antlr/v4" + "sync" + "unicode" +) + +// Suppress unused import error +var _ = fmt.Printf +var _ = sync.Once{} +var _ = unicode.IsLetter + +type QueryLexer struct { + *antlr.BaseLexer + channelNames []string + modeNames []string + // TODO: EOF string +} + +var QueryLexerLexerStaticData struct { + once sync.Once + serializedATN []int32 + ChannelNames []string + ModeNames []string + LiteralNames []string + SymbolicNames []string + RuleNames []string + PredictionContextCache *antlr.PredictionContextCache + atn *antlr.ATN + decisionToDFA []*antlr.DFA +} + +func querylexerLexerInit() { + staticData := &QueryLexerLexerStaticData + staticData.ChannelNames = []string{ + "DEFAULT_TOKEN_CHANNEL", "HIDDEN", + } + staticData.ModeNames = []string{ + "DEFAULT_MODE", + } + staticData.LiteralNames = []string{ + "", "'FIND'", "'WHERE'", "','", "'AS'", "'||'", "'&&'", "'('", "')'", + "'.'", "'=='", "'!='", "'<'", "'>'", "'<='", "'>='", "'LIKE'", "'IN'", + } + staticData.SymbolicNames = []string{ + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "STRING", "STRING_WITH_WILDCARD", "NUMBER", "IDENTIFIER", "WS", + } + staticData.RuleNames = []string{ + "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "T__8", + "T__9", "T__10", "T__11", "T__12", "T__13", "T__14", "T__15", "T__16", + "STRING", "STRING_WITH_WILDCARD", "NUMBER", "IDENTIFIER", "WS", + } + staticData.PredictionContextCache = antlr.NewPredictionContextCache() + staticData.serializedATN = []int32{ + 4, 0, 22, 147, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, + 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, + 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, + 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, + 20, 2, 21, 7, 21, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, + 1, 5, 1, 6, 1, 6, 1, 7, 1, 7, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, + 1, 10, 1, 11, 1, 11, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, + 14, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 16, 1, 17, 1, 17, + 1, 17, 1, 17, 5, 17, 102, 8, 17, 10, 17, 12, 17, 105, 9, 17, 1, 17, 1, + 17, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 5, 18, 114, 8, 18, 10, 18, 12, 18, + 117, 9, 18, 1, 18, 1, 18, 1, 19, 4, 19, 122, 8, 19, 11, 19, 12, 19, 123, + 1, 19, 1, 19, 4, 19, 128, 8, 19, 11, 19, 12, 19, 129, 3, 19, 132, 8, 19, + 1, 20, 1, 20, 5, 20, 136, 8, 20, 10, 20, 12, 20, 139, 9, 20, 1, 21, 4, + 21, 142, 8, 21, 11, 21, 12, 21, 143, 1, 21, 1, 21, 0, 0, 22, 1, 1, 3, 2, + 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 21, 11, 23, 12, 25, + 13, 27, 14, 29, 15, 31, 16, 33, 17, 35, 18, 37, 19, 39, 20, 41, 21, 43, + 22, 1, 0, 5, 2, 0, 34, 34, 92, 92, 1, 0, 48, 57, 3, 0, 65, 90, 95, 95, + 97, 122, 4, 0, 48, 57, 65, 90, 95, 95, 97, 122, 3, 0, 9, 10, 13, 13, 32, + 32, 156, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, + 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, + 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, + 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, + 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, 0, 0, + 0, 0, 39, 1, 0, 0, 0, 0, 41, 1, 0, 0, 0, 0, 43, 1, 0, 0, 0, 1, 45, 1, 0, + 0, 0, 3, 50, 1, 0, 0, 0, 5, 56, 1, 0, 0, 0, 7, 58, 1, 0, 0, 0, 9, 61, 1, + 0, 0, 0, 11, 64, 1, 0, 0, 0, 13, 67, 1, 0, 0, 0, 15, 69, 1, 0, 0, 0, 17, + 71, 1, 0, 0, 0, 19, 73, 1, 0, 0, 0, 21, 76, 1, 0, 0, 0, 23, 79, 1, 0, 0, + 0, 25, 81, 1, 0, 0, 0, 27, 83, 1, 0, 0, 0, 29, 86, 1, 0, 0, 0, 31, 89, + 1, 0, 0, 0, 33, 94, 1, 0, 0, 0, 35, 97, 1, 0, 0, 0, 37, 108, 1, 0, 0, 0, + 39, 121, 1, 0, 0, 0, 41, 133, 1, 0, 0, 0, 43, 141, 1, 0, 0, 0, 45, 46, + 5, 70, 0, 0, 46, 47, 5, 73, 0, 0, 47, 48, 5, 78, 0, 0, 48, 49, 5, 68, 0, + 0, 49, 2, 1, 0, 0, 0, 50, 51, 5, 87, 0, 0, 51, 52, 5, 72, 0, 0, 52, 53, + 5, 69, 0, 0, 53, 54, 5, 82, 0, 0, 54, 55, 5, 69, 0, 0, 55, 4, 1, 0, 0, + 0, 56, 57, 5, 44, 0, 0, 57, 6, 1, 0, 0, 0, 58, 59, 5, 65, 0, 0, 59, 60, + 5, 83, 0, 0, 60, 8, 1, 0, 0, 0, 61, 62, 5, 124, 0, 0, 62, 63, 5, 124, 0, + 0, 63, 10, 1, 0, 0, 0, 64, 65, 5, 38, 0, 0, 65, 66, 5, 38, 0, 0, 66, 12, + 1, 0, 0, 0, 67, 68, 5, 40, 0, 0, 68, 14, 1, 0, 0, 0, 69, 70, 5, 41, 0, + 0, 70, 16, 1, 0, 0, 0, 71, 72, 5, 46, 0, 0, 72, 18, 1, 0, 0, 0, 73, 74, + 5, 61, 0, 0, 74, 75, 5, 61, 0, 0, 75, 20, 1, 0, 0, 0, 76, 77, 5, 33, 0, + 0, 77, 78, 5, 61, 0, 0, 78, 22, 1, 0, 0, 0, 79, 80, 5, 60, 0, 0, 80, 24, + 1, 0, 0, 0, 81, 82, 5, 62, 0, 0, 82, 26, 1, 0, 0, 0, 83, 84, 5, 60, 0, + 0, 84, 85, 5, 61, 0, 0, 85, 28, 1, 0, 0, 0, 86, 87, 5, 62, 0, 0, 87, 88, + 5, 61, 0, 0, 88, 30, 1, 0, 0, 0, 89, 90, 5, 76, 0, 0, 90, 91, 5, 73, 0, + 0, 91, 92, 5, 75, 0, 0, 92, 93, 5, 69, 0, 0, 93, 32, 1, 0, 0, 0, 94, 95, + 5, 73, 0, 0, 95, 96, 5, 78, 0, 0, 96, 34, 1, 0, 0, 0, 97, 103, 5, 34, 0, + 0, 98, 102, 8, 0, 0, 0, 99, 100, 5, 92, 0, 0, 100, 102, 9, 0, 0, 0, 101, + 98, 1, 0, 0, 0, 101, 99, 1, 0, 0, 0, 102, 105, 1, 0, 0, 0, 103, 101, 1, + 0, 0, 0, 103, 104, 1, 0, 0, 0, 104, 106, 1, 0, 0, 0, 105, 103, 1, 0, 0, + 0, 106, 107, 5, 34, 0, 0, 107, 36, 1, 0, 0, 0, 108, 115, 5, 34, 0, 0, 109, + 114, 8, 0, 0, 0, 110, 111, 5, 92, 0, 0, 111, 114, 9, 0, 0, 0, 112, 114, + 5, 37, 0, 0, 113, 109, 1, 0, 0, 0, 113, 110, 1, 0, 0, 0, 113, 112, 1, 0, + 0, 0, 114, 117, 1, 0, 0, 0, 115, 113, 1, 0, 0, 0, 115, 116, 1, 0, 0, 0, + 116, 118, 1, 0, 0, 0, 117, 115, 1, 0, 0, 0, 118, 119, 5, 34, 0, 0, 119, + 38, 1, 0, 0, 0, 120, 122, 7, 1, 0, 0, 121, 120, 1, 0, 0, 0, 122, 123, 1, + 0, 0, 0, 123, 121, 1, 0, 0, 0, 123, 124, 1, 0, 0, 0, 124, 131, 1, 0, 0, + 0, 125, 127, 5, 46, 0, 0, 126, 128, 7, 1, 0, 0, 127, 126, 1, 0, 0, 0, 128, + 129, 1, 0, 0, 0, 129, 127, 1, 0, 0, 0, 129, 130, 1, 0, 0, 0, 130, 132, + 1, 0, 0, 0, 131, 125, 1, 0, 0, 0, 131, 132, 1, 0, 0, 0, 132, 40, 1, 0, + 0, 0, 133, 137, 7, 2, 0, 0, 134, 136, 7, 3, 0, 0, 135, 134, 1, 0, 0, 0, + 136, 139, 1, 0, 0, 0, 137, 135, 1, 0, 0, 0, 137, 138, 1, 0, 0, 0, 138, + 42, 1, 0, 0, 0, 139, 137, 1, 0, 0, 0, 140, 142, 7, 4, 0, 0, 141, 140, 1, + 0, 0, 0, 142, 143, 1, 0, 0, 0, 143, 141, 1, 0, 0, 0, 143, 144, 1, 0, 0, + 0, 144, 145, 1, 0, 0, 0, 145, 146, 6, 21, 0, 0, 146, 44, 1, 0, 0, 0, 10, + 0, 101, 103, 113, 115, 123, 129, 131, 137, 143, 1, 6, 0, 0, + } + deserializer := antlr.NewATNDeserializer(nil) + staticData.atn = deserializer.Deserialize(staticData.serializedATN) + atn := staticData.atn + staticData.decisionToDFA = make([]*antlr.DFA, len(atn.DecisionToState)) + decisionToDFA := staticData.decisionToDFA + for index, state := range atn.DecisionToState { + decisionToDFA[index] = antlr.NewDFA(state, index) + } +} + +// QueryLexerInit initializes any static state used to implement QueryLexer. By default the +// static state used to implement the lexer is lazily initialized during the first call to +// NewQueryLexer(). You can call this function if you wish to initialize the static state ahead +// of time. +func QueryLexerInit() { + staticData := &QueryLexerLexerStaticData + staticData.once.Do(querylexerLexerInit) +} + +// NewQueryLexer produces a new lexer instance for the optional input antlr.CharStream. +func NewQueryLexer(input antlr.CharStream) *QueryLexer { + QueryLexerInit() + l := new(QueryLexer) + l.BaseLexer = antlr.NewBaseLexer(input) + staticData := &QueryLexerLexerStaticData + l.Interpreter = antlr.NewLexerATNSimulator(l, staticData.atn, staticData.decisionToDFA, staticData.PredictionContextCache) + l.channelNames = staticData.ChannelNames + l.modeNames = staticData.ModeNames + l.RuleNames = staticData.RuleNames + l.LiteralNames = staticData.LiteralNames + l.SymbolicNames = staticData.SymbolicNames + l.GrammarFileName = "Query.g4" + // TODO: l.EOF = antlr.TokenEOF + + return l +} + +// QueryLexer tokens. +const ( + QueryLexerT__0 = 1 + QueryLexerT__1 = 2 + QueryLexerT__2 = 3 + QueryLexerT__3 = 4 + QueryLexerT__4 = 5 + QueryLexerT__5 = 6 + QueryLexerT__6 = 7 + QueryLexerT__7 = 8 + QueryLexerT__8 = 9 + QueryLexerT__9 = 10 + QueryLexerT__10 = 11 + QueryLexerT__11 = 12 + QueryLexerT__12 = 13 + QueryLexerT__13 = 14 + QueryLexerT__14 = 15 + QueryLexerT__15 = 16 + QueryLexerT__16 = 17 + QueryLexerSTRING = 18 + QueryLexerSTRING_WITH_WILDCARD = 19 + QueryLexerNUMBER = 20 + QueryLexerIDENTIFIER = 21 + QueryLexerWS = 22 +) diff --git a/sourcecode-parser/antlr/query_listener.go b/sourcecode-parser/antlr/query_listener.go new file mode 100644 index 0000000..29301cf --- /dev/null +++ b/sourcecode-parser/antlr/query_listener.go @@ -0,0 +1,112 @@ +// Code generated from Query.g4 by ANTLR 4.13.1. DO NOT EDIT. + +package parser // Query + +import "github.com/antlr4-go/antlr/v4" + +// QueryListener is a complete listener for a parse tree produced by QueryParser. +type QueryListener interface { + antlr.ParseTreeListener + + // EnterQuery is called when entering the query production. + EnterQuery(c *QueryContext) + + // EnterSelect_list is called when entering the select_list production. + EnterSelect_list(c *Select_listContext) + + // EnterSelect_item is called when entering the select_item production. + EnterSelect_item(c *Select_itemContext) + + // EnterEntity is called when entering the entity production. + EnterEntity(c *EntityContext) + + // EnterAlias is called when entering the alias production. + EnterAlias(c *AliasContext) + + // EnterExpression is called when entering the expression production. + EnterExpression(c *ExpressionContext) + + // EnterOrExpression is called when entering the orExpression production. + EnterOrExpression(c *OrExpressionContext) + + // EnterAndExpression is called when entering the andExpression production. + EnterAndExpression(c *AndExpressionContext) + + // EnterPrimary is called when entering the primary production. + EnterPrimary(c *PrimaryContext) + + // EnterCondition is called when entering the condition production. + EnterCondition(c *ConditionContext) + + // EnterMethod_chain is called when entering the method_chain production. + EnterMethod_chain(c *Method_chainContext) + + // EnterMethod_or_variable is called when entering the method_or_variable production. + EnterMethod_or_variable(c *Method_or_variableContext) + + // EnterMethod is called when entering the method production. + EnterMethod(c *MethodContext) + + // EnterVariable is called when entering the variable production. + EnterVariable(c *VariableContext) + + // EnterComparator is called when entering the comparator production. + EnterComparator(c *ComparatorContext) + + // EnterValue is called when entering the value production. + EnterValue(c *ValueContext) + + // EnterValue_list is called when entering the value_list production. + EnterValue_list(c *Value_listContext) + + // ExitQuery is called when exiting the query production. + ExitQuery(c *QueryContext) + + // ExitSelect_list is called when exiting the select_list production. + ExitSelect_list(c *Select_listContext) + + // ExitSelect_item is called when exiting the select_item production. + ExitSelect_item(c *Select_itemContext) + + // ExitEntity is called when exiting the entity production. + ExitEntity(c *EntityContext) + + // ExitAlias is called when exiting the alias production. + ExitAlias(c *AliasContext) + + // ExitExpression is called when exiting the expression production. + ExitExpression(c *ExpressionContext) + + // ExitOrExpression is called when exiting the orExpression production. + ExitOrExpression(c *OrExpressionContext) + + // ExitAndExpression is called when exiting the andExpression production. + ExitAndExpression(c *AndExpressionContext) + + // ExitPrimary is called when exiting the primary production. + ExitPrimary(c *PrimaryContext) + + // ExitCondition is called when exiting the condition production. + ExitCondition(c *ConditionContext) + + // ExitMethod_chain is called when exiting the method_chain production. + ExitMethod_chain(c *Method_chainContext) + + // ExitMethod_or_variable is called when exiting the method_or_variable production. + ExitMethod_or_variable(c *Method_or_variableContext) + + // ExitMethod is called when exiting the method production. + ExitMethod(c *MethodContext) + + // ExitVariable is called when exiting the variable production. + ExitVariable(c *VariableContext) + + // ExitComparator is called when exiting the comparator production. + ExitComparator(c *ComparatorContext) + + // ExitValue is called when exiting the value production. + ExitValue(c *ValueContext) + + // ExitValue_list is called when exiting the value_list production. + ExitValue_list(c *Value_listContext) +} diff --git a/sourcecode-parser/antlr/query_parser.go b/sourcecode-parser/antlr/query_parser.go new file mode 100644 index 0000000..99cdbce --- /dev/null +++ b/sourcecode-parser/antlr/query_parser.go @@ -0,0 +1,2528 @@ +// Code generated from Query.g4 by ANTLR 4.13.1. DO NOT EDIT. + +package parser // Query + +import ( + "fmt" + "strconv" + "sync" + + "github.com/antlr4-go/antlr/v4" +) + +// Suppress unused import errors +var _ = fmt.Printf +var _ = strconv.Itoa +var _ = sync.Once{} + +type QueryParser struct { + *antlr.BaseParser +} + +var QueryParserStaticData struct { + once sync.Once + serializedATN []int32 + LiteralNames []string + SymbolicNames []string + RuleNames []string + PredictionContextCache *antlr.PredictionContextCache + atn *antlr.ATN + decisionToDFA []*antlr.DFA +} + +func queryParserInit() { + staticData := &QueryParserStaticData + staticData.LiteralNames = []string{ + "", "'FIND'", "'WHERE'", "','", "'AS'", "'||'", "'&&'", "'('", "')'", + "'.'", "'=='", "'!='", "'<'", "'>'", "'<='", "'>='", "'LIKE'", "'IN'", + } + staticData.SymbolicNames = []string{ + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "STRING", "STRING_WITH_WILDCARD", "NUMBER", "IDENTIFIER", "WS", + } + staticData.RuleNames = []string{ + "query", "select_list", "select_item", "entity", "alias", "expression", + "orExpression", "andExpression", "primary", "condition", "method_chain", + "method_or_variable", "method", "variable", "comparator", "value", "value_list", + } + staticData.PredictionContextCache = antlr.NewPredictionContextCache() + staticData.serializedATN = []int32{ + 4, 1, 22, 124, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, + 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, + 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, + 2, 16, 7, 16, 1, 0, 1, 0, 1, 0, 1, 0, 3, 0, 39, 8, 0, 1, 1, 1, 1, 1, 1, + 5, 1, 44, 8, 1, 10, 1, 12, 1, 47, 9, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 3, 1, + 3, 1, 4, 1, 4, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 5, 6, 62, 8, 6, 10, 6, 12, + 6, 65, 9, 6, 1, 7, 1, 7, 1, 7, 5, 7, 70, 8, 7, 10, 7, 12, 7, 73, 9, 7, + 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 3, 8, 80, 8, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, + 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 3, 9, 92, 8, 9, 1, 10, 1, 10, 1, 10, 5, + 10, 97, 8, 10, 10, 10, 12, 10, 100, 9, 10, 1, 11, 1, 11, 3, 11, 104, 8, + 11, 1, 12, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 14, 1, 14, 1, 15, 1, 15, + 1, 16, 1, 16, 1, 16, 5, 16, 119, 8, 16, 10, 16, 12, 16, 122, 9, 16, 1, + 16, 0, 0, 17, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, + 32, 0, 2, 1, 0, 10, 17, 1, 0, 18, 20, 116, 0, 34, 1, 0, 0, 0, 2, 40, 1, + 0, 0, 0, 4, 48, 1, 0, 0, 0, 6, 52, 1, 0, 0, 0, 8, 54, 1, 0, 0, 0, 10, 56, + 1, 0, 0, 0, 12, 58, 1, 0, 0, 0, 14, 66, 1, 0, 0, 0, 16, 79, 1, 0, 0, 0, + 18, 81, 1, 0, 0, 0, 20, 93, 1, 0, 0, 0, 22, 103, 1, 0, 0, 0, 24, 105, 1, + 0, 0, 0, 26, 109, 1, 0, 0, 0, 28, 111, 1, 0, 0, 0, 30, 113, 1, 0, 0, 0, + 32, 115, 1, 0, 0, 0, 34, 35, 5, 1, 0, 0, 35, 38, 3, 2, 1, 0, 36, 37, 5, + 2, 0, 0, 37, 39, 3, 10, 5, 0, 38, 36, 1, 0, 0, 0, 38, 39, 1, 0, 0, 0, 39, + 1, 1, 0, 0, 0, 40, 45, 3, 4, 2, 0, 41, 42, 5, 3, 0, 0, 42, 44, 3, 4, 2, + 0, 43, 41, 1, 0, 0, 0, 44, 47, 1, 0, 0, 0, 45, 43, 1, 0, 0, 0, 45, 46, + 1, 0, 0, 0, 46, 3, 1, 0, 0, 0, 47, 45, 1, 0, 0, 0, 48, 49, 3, 6, 3, 0, + 49, 50, 5, 4, 0, 0, 50, 51, 3, 8, 4, 0, 51, 5, 1, 0, 0, 0, 52, 53, 5, 21, + 0, 0, 53, 7, 1, 0, 0, 0, 54, 55, 5, 21, 0, 0, 55, 9, 1, 0, 0, 0, 56, 57, + 3, 12, 6, 0, 57, 11, 1, 0, 0, 0, 58, 63, 3, 14, 7, 0, 59, 60, 5, 5, 0, + 0, 60, 62, 3, 14, 7, 0, 61, 59, 1, 0, 0, 0, 62, 65, 1, 0, 0, 0, 63, 61, + 1, 0, 0, 0, 63, 64, 1, 0, 0, 0, 64, 13, 1, 0, 0, 0, 65, 63, 1, 0, 0, 0, + 66, 71, 3, 16, 8, 0, 67, 68, 5, 6, 0, 0, 68, 70, 3, 16, 8, 0, 69, 67, 1, + 0, 0, 0, 70, 73, 1, 0, 0, 0, 71, 69, 1, 0, 0, 0, 71, 72, 1, 0, 0, 0, 72, + 15, 1, 0, 0, 0, 73, 71, 1, 0, 0, 0, 74, 80, 3, 18, 9, 0, 75, 76, 5, 7, + 0, 0, 76, 77, 3, 10, 5, 0, 77, 78, 5, 8, 0, 0, 78, 80, 1, 0, 0, 0, 79, + 74, 1, 0, 0, 0, 79, 75, 1, 0, 0, 0, 80, 17, 1, 0, 0, 0, 81, 82, 3, 8, 4, + 0, 82, 83, 5, 9, 0, 0, 83, 84, 3, 20, 10, 0, 84, 91, 3, 28, 14, 0, 85, + 92, 3, 30, 15, 0, 86, 92, 3, 20, 10, 0, 87, 88, 5, 7, 0, 0, 88, 89, 3, + 32, 16, 0, 89, 90, 5, 8, 0, 0, 90, 92, 1, 0, 0, 0, 91, 85, 1, 0, 0, 0, + 91, 86, 1, 0, 0, 0, 91, 87, 1, 0, 0, 0, 92, 19, 1, 0, 0, 0, 93, 98, 3, + 22, 11, 0, 94, 95, 5, 9, 0, 0, 95, 97, 3, 22, 11, 0, 96, 94, 1, 0, 0, 0, + 97, 100, 1, 0, 0, 0, 98, 96, 1, 0, 0, 0, 98, 99, 1, 0, 0, 0, 99, 21, 1, + 0, 0, 0, 100, 98, 1, 0, 0, 0, 101, 104, 3, 24, 12, 0, 102, 104, 3, 26, + 13, 0, 103, 101, 1, 0, 0, 0, 103, 102, 1, 0, 0, 0, 104, 23, 1, 0, 0, 0, + 105, 106, 5, 21, 0, 0, 106, 107, 5, 7, 0, 0, 107, 108, 5, 8, 0, 0, 108, + 25, 1, 0, 0, 0, 109, 110, 5, 21, 0, 0, 110, 27, 1, 0, 0, 0, 111, 112, 7, + 0, 0, 0, 112, 29, 1, 0, 0, 0, 113, 114, 7, 1, 0, 0, 114, 31, 1, 0, 0, 0, + 115, 120, 3, 30, 15, 0, 116, 117, 5, 3, 0, 0, 117, 119, 3, 30, 15, 0, 118, + 116, 1, 0, 0, 0, 119, 122, 1, 0, 0, 0, 120, 118, 1, 0, 0, 0, 120, 121, + 1, 0, 0, 0, 121, 33, 1, 0, 0, 0, 122, 120, 1, 0, 0, 0, 9, 38, 45, 63, 71, + 79, 91, 98, 103, 120, + } + deserializer := antlr.NewATNDeserializer(nil) + staticData.atn = deserializer.Deserialize(staticData.serializedATN) + atn := staticData.atn + staticData.decisionToDFA = make([]*antlr.DFA, len(atn.DecisionToState)) + decisionToDFA := staticData.decisionToDFA + for index, state := range atn.DecisionToState { + decisionToDFA[index] = antlr.NewDFA(state, index) + } +} + +// QueryParserInit initializes any static state used to implement QueryParser. By default the +// static state used to implement the parser is lazily initialized during the first call to +// NewQueryParser(). You can call this function if you wish to initialize the static state ahead +// of time. +func QueryParserInit() { + staticData := &QueryParserStaticData + staticData.once.Do(queryParserInit) +} + +// NewQueryParser produces a new parser instance for the optional input antlr.TokenStream. +func NewQueryParser(input antlr.TokenStream) *QueryParser { + QueryParserInit() + this := new(QueryParser) + this.BaseParser = antlr.NewBaseParser(input) + staticData := &QueryParserStaticData + this.Interpreter = antlr.NewParserATNSimulator(this, staticData.atn, staticData.decisionToDFA, staticData.PredictionContextCache) + this.RuleNames = staticData.RuleNames + this.LiteralNames = staticData.LiteralNames + this.SymbolicNames = staticData.SymbolicNames + this.GrammarFileName = "Query.g4" + + return this +} + +// QueryParser tokens. +const ( + QueryParserEOF = antlr.TokenEOF + QueryParserT__0 = 1 + QueryParserT__1 = 2 + QueryParserT__2 = 3 + QueryParserT__3 = 4 + QueryParserT__4 = 5 + QueryParserT__5 = 6 + QueryParserT__6 = 7 + QueryParserT__7 = 8 + QueryParserT__8 = 9 + QueryParserT__9 = 10 + QueryParserT__10 = 11 + QueryParserT__11 = 12 + QueryParserT__12 = 13 + QueryParserT__13 = 14 + QueryParserT__14 = 15 + QueryParserT__15 = 16 + QueryParserT__16 = 17 + QueryParserSTRING = 18 + QueryParserSTRING_WITH_WILDCARD = 19 + QueryParserNUMBER = 20 + QueryParserIDENTIFIER = 21 + QueryParserWS = 22 +) + +// QueryParser rules. +const ( + QueryParserRULE_query = 0 + QueryParserRULE_select_list = 1 + QueryParserRULE_select_item = 2 + QueryParserRULE_entity = 3 + QueryParserRULE_alias = 4 + QueryParserRULE_expression = 5 + QueryParserRULE_orExpression = 6 + QueryParserRULE_andExpression = 7 + QueryParserRULE_primary = 8 + QueryParserRULE_condition = 9 + QueryParserRULE_method_chain = 10 + QueryParserRULE_method_or_variable = 11 + QueryParserRULE_method = 12 + QueryParserRULE_variable = 13 + QueryParserRULE_comparator = 14 + QueryParserRULE_value = 15 + QueryParserRULE_value_list = 16 +) + +// IQueryContext is an interface to support dynamic dispatch. +type IQueryContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + Select_list() ISelect_listContext + Expression() IExpressionContext + + // IsQueryContext differentiates from other interfaces. + IsQueryContext() +} + +type QueryContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyQueryContext() *QueryContext { + var p = new(QueryContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_query + return p +} + +func InitEmptyQueryContext(p *QueryContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_query +} + +func (*QueryContext) IsQueryContext() {} + +func NewQueryContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *QueryContext { + var p = new(QueryContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryParserRULE_query + + return p +} + +func (s *QueryContext) GetParser() antlr.Parser { return s.parser } + +func (s *QueryContext) Select_list() ISelect_listContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(ISelect_listContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(ISelect_listContext) +} + +func (s *QueryContext) Expression() IExpressionContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IExpressionContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IExpressionContext) +} + +func (s *QueryContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *QueryContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *QueryContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.EnterQuery(s) + } +} + +func (s *QueryContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.ExitQuery(s) + } +} + +func (p *QueryParser) Query() (localctx IQueryContext) { + localctx = NewQueryContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 0, QueryParserRULE_query) + var _la int + + p.EnterOuterAlt(localctx, 1) + { + p.SetState(34) + p.Match(QueryParserT__0) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + { + p.SetState(35) + p.Select_list() + } + p.SetState(38) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + + if _la == QueryParserT__1 { + { + p.SetState(36) + p.Match(QueryParserT__1) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + { + p.SetState(37) + p.Expression() + } + + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// ISelect_listContext is an interface to support dynamic dispatch. +type ISelect_listContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + AllSelect_item() []ISelect_itemContext + Select_item(i int) ISelect_itemContext + + // IsSelect_listContext differentiates from other interfaces. + IsSelect_listContext() +} + +type Select_listContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptySelect_listContext() *Select_listContext { + var p = new(Select_listContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_select_list + return p +} + +func InitEmptySelect_listContext(p *Select_listContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_select_list +} + +func (*Select_listContext) IsSelect_listContext() {} + +func NewSelect_listContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *Select_listContext { + var p = new(Select_listContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryParserRULE_select_list + + return p +} + +func (s *Select_listContext) GetParser() antlr.Parser { return s.parser } + +func (s *Select_listContext) AllSelect_item() []ISelect_itemContext { + children := s.GetChildren() + len := 0 + for _, ctx := range children { + if _, ok := ctx.(ISelect_itemContext); ok { + len++ + } + } + + tst := make([]ISelect_itemContext, len) + i := 0 + for _, ctx := range children { + if t, ok := ctx.(ISelect_itemContext); ok { + tst[i] = t.(ISelect_itemContext) + i++ + } + } + + return tst +} + +func (s *Select_listContext) Select_item(i int) ISelect_itemContext { + var t antlr.RuleContext + j := 0 + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(ISelect_itemContext); ok { + if j == i { + t = ctx.(antlr.RuleContext) + break + } + j++ + } + } + + if t == nil { + return nil + } + + return t.(ISelect_itemContext) +} + +func (s *Select_listContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *Select_listContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *Select_listContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.EnterSelect_list(s) + } +} + +func (s *Select_listContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.ExitSelect_list(s) + } +} + +func (p *QueryParser) Select_list() (localctx ISelect_listContext) { + localctx = NewSelect_listContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 2, QueryParserRULE_select_list) + var _la int + + p.EnterOuterAlt(localctx, 1) + { + p.SetState(40) + p.Select_item() + } + p.SetState(45) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + + for _la == QueryParserT__2 { + { + p.SetState(41) + p.Match(QueryParserT__2) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + { + p.SetState(42) + p.Select_item() + } + + p.SetState(47) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// ISelect_itemContext is an interface to support dynamic dispatch. +type ISelect_itemContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + Entity() IEntityContext + Alias() IAliasContext + + // IsSelect_itemContext differentiates from other interfaces. + IsSelect_itemContext() +} + +type Select_itemContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptySelect_itemContext() *Select_itemContext { + var p = new(Select_itemContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_select_item + return p +} + +func InitEmptySelect_itemContext(p *Select_itemContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_select_item +} + +func (*Select_itemContext) IsSelect_itemContext() {} + +func NewSelect_itemContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *Select_itemContext { + var p = new(Select_itemContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryParserRULE_select_item + + return p +} + +func (s *Select_itemContext) GetParser() antlr.Parser { return s.parser } + +func (s *Select_itemContext) Entity() IEntityContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IEntityContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IEntityContext) +} + +func (s *Select_itemContext) Alias() IAliasContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IAliasContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IAliasContext) +} + +func (s *Select_itemContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *Select_itemContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *Select_itemContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.EnterSelect_item(s) + } +} + +func (s *Select_itemContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.ExitSelect_item(s) + } +} + +func (p *QueryParser) Select_item() (localctx ISelect_itemContext) { + localctx = NewSelect_itemContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 4, QueryParserRULE_select_item) + p.EnterOuterAlt(localctx, 1) + { + p.SetState(48) + p.Entity() + } + { + p.SetState(49) + p.Match(QueryParserT__3) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + { + p.SetState(50) + p.Alias() + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// IEntityContext is an interface to support dynamic dispatch. +type IEntityContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + IDENTIFIER() antlr.TerminalNode + + // IsEntityContext differentiates from other interfaces. + IsEntityContext() +} + +type EntityContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyEntityContext() *EntityContext { + var p = new(EntityContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_entity + return p +} + +func InitEmptyEntityContext(p *EntityContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_entity +} + +func (*EntityContext) IsEntityContext() {} + +func NewEntityContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *EntityContext { + var p = new(EntityContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryParserRULE_entity + + return p +} + +func (s *EntityContext) GetParser() antlr.Parser { return s.parser } + +func (s *EntityContext) IDENTIFIER() antlr.TerminalNode { + return s.GetToken(QueryParserIDENTIFIER, 0) +} + +func (s *EntityContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *EntityContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *EntityContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.EnterEntity(s) + } +} + +func (s *EntityContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.ExitEntity(s) + } +} + +func (p *QueryParser) Entity() (localctx IEntityContext) { + localctx = NewEntityContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 6, QueryParserRULE_entity) + p.EnterOuterAlt(localctx, 1) + { + p.SetState(52) + p.Match(QueryParserIDENTIFIER) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// IAliasContext is an interface to support dynamic dispatch. +type IAliasContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + IDENTIFIER() antlr.TerminalNode + + // IsAliasContext differentiates from other interfaces. + IsAliasContext() +} + +type AliasContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyAliasContext() *AliasContext { + var p = new(AliasContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_alias + return p +} + +func InitEmptyAliasContext(p *AliasContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_alias +} + +func (*AliasContext) IsAliasContext() {} + +func NewAliasContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *AliasContext { + var p = new(AliasContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryParserRULE_alias + + return p +} + +func (s *AliasContext) GetParser() antlr.Parser { return s.parser } + +func (s *AliasContext) IDENTIFIER() antlr.TerminalNode { + return s.GetToken(QueryParserIDENTIFIER, 0) +} + +func (s *AliasContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *AliasContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *AliasContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.EnterAlias(s) + } +} + +func (s *AliasContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.ExitAlias(s) + } +} + +func (p *QueryParser) Alias() (localctx IAliasContext) { + localctx = NewAliasContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 8, QueryParserRULE_alias) + p.EnterOuterAlt(localctx, 1) + { + p.SetState(54) + p.Match(QueryParserIDENTIFIER) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// IExpressionContext is an interface to support dynamic dispatch. +type IExpressionContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + OrExpression() IOrExpressionContext + + // IsExpressionContext differentiates from other interfaces. + IsExpressionContext() +} + +type ExpressionContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyExpressionContext() *ExpressionContext { + var p = new(ExpressionContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_expression + return p +} + +func InitEmptyExpressionContext(p *ExpressionContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_expression +} + +func (*ExpressionContext) IsExpressionContext() {} + +func NewExpressionContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *ExpressionContext { + var p = new(ExpressionContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryParserRULE_expression + + return p +} + +func (s *ExpressionContext) GetParser() antlr.Parser { return s.parser } + +func (s *ExpressionContext) OrExpression() IOrExpressionContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IOrExpressionContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IOrExpressionContext) +} + +func (s *ExpressionContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *ExpressionContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *ExpressionContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.EnterExpression(s) + } +} + +func (s *ExpressionContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.ExitExpression(s) + } +} + +func (p *QueryParser) Expression() (localctx IExpressionContext) { + localctx = NewExpressionContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 10, QueryParserRULE_expression) + p.EnterOuterAlt(localctx, 1) + { + p.SetState(56) + p.OrExpression() + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// IOrExpressionContext is an interface to support dynamic dispatch. +type IOrExpressionContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + AllAndExpression() []IAndExpressionContext + AndExpression(i int) IAndExpressionContext + + // IsOrExpressionContext differentiates from other interfaces. + IsOrExpressionContext() +} + +type OrExpressionContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyOrExpressionContext() *OrExpressionContext { + var p = new(OrExpressionContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_orExpression + return p +} + +func InitEmptyOrExpressionContext(p *OrExpressionContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_orExpression +} + +func (*OrExpressionContext) IsOrExpressionContext() {} + +func NewOrExpressionContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *OrExpressionContext { + var p = new(OrExpressionContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryParserRULE_orExpression + + return p +} + +func (s *OrExpressionContext) GetParser() antlr.Parser { return s.parser } + +func (s *OrExpressionContext) AllAndExpression() []IAndExpressionContext { + children := s.GetChildren() + len := 0 + for _, ctx := range children { + if _, ok := ctx.(IAndExpressionContext); ok { + len++ + } + } + + tst := make([]IAndExpressionContext, len) + i := 0 + for _, ctx := range children { + if t, ok := ctx.(IAndExpressionContext); ok { + tst[i] = t.(IAndExpressionContext) + i++ + } + } + + return tst +} + +func (s *OrExpressionContext) AndExpression(i int) IAndExpressionContext { + var t antlr.RuleContext + j := 0 + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IAndExpressionContext); ok { + if j == i { + t = ctx.(antlr.RuleContext) + break + } + j++ + } + } + + if t == nil { + return nil + } + + return t.(IAndExpressionContext) +} + +func (s *OrExpressionContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *OrExpressionContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *OrExpressionContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.EnterOrExpression(s) + } +} + +func (s *OrExpressionContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.ExitOrExpression(s) + } +} + +func (p *QueryParser) OrExpression() (localctx IOrExpressionContext) { + localctx = NewOrExpressionContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 12, QueryParserRULE_orExpression) + var _la int + + p.EnterOuterAlt(localctx, 1) + { + p.SetState(58) + p.AndExpression() + } + p.SetState(63) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + + for _la == QueryParserT__4 { + { + p.SetState(59) + p.Match(QueryParserT__4) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + { + p.SetState(60) + p.AndExpression() + } + + p.SetState(65) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// IAndExpressionContext is an interface to support dynamic dispatch. +type IAndExpressionContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + AllPrimary() []IPrimaryContext + Primary(i int) IPrimaryContext + + // IsAndExpressionContext differentiates from other interfaces. + IsAndExpressionContext() +} + +type AndExpressionContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyAndExpressionContext() *AndExpressionContext { + var p = new(AndExpressionContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_andExpression + return p +} + +func InitEmptyAndExpressionContext(p *AndExpressionContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_andExpression +} + +func (*AndExpressionContext) IsAndExpressionContext() {} + +func NewAndExpressionContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *AndExpressionContext { + var p = new(AndExpressionContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryParserRULE_andExpression + + return p +} + +func (s *AndExpressionContext) GetParser() antlr.Parser { return s.parser } + +func (s *AndExpressionContext) AllPrimary() []IPrimaryContext { + children := s.GetChildren() + len := 0 + for _, ctx := range children { + if _, ok := ctx.(IPrimaryContext); ok { + len++ + } + } + + tst := make([]IPrimaryContext, len) + i := 0 + for _, ctx := range children { + if t, ok := ctx.(IPrimaryContext); ok { + tst[i] = t.(IPrimaryContext) + i++ + } + } + + return tst +} + +func (s *AndExpressionContext) Primary(i int) IPrimaryContext { + var t antlr.RuleContext + j := 0 + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IPrimaryContext); ok { + if j == i { + t = ctx.(antlr.RuleContext) + break + } + j++ + } + } + + if t == nil { + return nil + } + + return t.(IPrimaryContext) +} + +func (s *AndExpressionContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *AndExpressionContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *AndExpressionContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.EnterAndExpression(s) + } +} + +func (s *AndExpressionContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.ExitAndExpression(s) + } +} + +func (p *QueryParser) AndExpression() (localctx IAndExpressionContext) { + localctx = NewAndExpressionContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 14, QueryParserRULE_andExpression) + var _la int + + p.EnterOuterAlt(localctx, 1) + { + p.SetState(66) + p.Primary() + } + p.SetState(71) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + + for _la == QueryParserT__5 { + { + p.SetState(67) + p.Match(QueryParserT__5) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + { + p.SetState(68) + p.Primary() + } + + p.SetState(73) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// IPrimaryContext is an interface to support dynamic dispatch. +type IPrimaryContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + Condition() IConditionContext + Expression() IExpressionContext + + // IsPrimaryContext differentiates from other interfaces. + IsPrimaryContext() +} + +type PrimaryContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyPrimaryContext() *PrimaryContext { + var p = new(PrimaryContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_primary + return p +} + +func InitEmptyPrimaryContext(p *PrimaryContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_primary +} + +func (*PrimaryContext) IsPrimaryContext() {} + +func NewPrimaryContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *PrimaryContext { + var p = new(PrimaryContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryParserRULE_primary + + return p +} + +func (s *PrimaryContext) GetParser() antlr.Parser { return s.parser } + +func (s *PrimaryContext) Condition() IConditionContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IConditionContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IConditionContext) +} + +func (s *PrimaryContext) Expression() IExpressionContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IExpressionContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IExpressionContext) +} + +func (s *PrimaryContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *PrimaryContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *PrimaryContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.EnterPrimary(s) + } +} + +func (s *PrimaryContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.ExitPrimary(s) + } +} + +func (p *QueryParser) Primary() (localctx IPrimaryContext) { + localctx = NewPrimaryContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 16, QueryParserRULE_primary) + p.SetState(79) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + + switch p.GetTokenStream().LA(1) { + case QueryParserIDENTIFIER: + p.EnterOuterAlt(localctx, 1) + { + p.SetState(74) + p.Condition() + } + + case QueryParserT__6: + p.EnterOuterAlt(localctx, 2) + { + p.SetState(75) + p.Match(QueryParserT__6) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + { + p.SetState(76) + p.Expression() + } + { + p.SetState(77) + p.Match(QueryParserT__7) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + + default: + p.SetError(antlr.NewNoViableAltException(p, nil, nil, nil, nil, nil)) + goto errorExit + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// IConditionContext is an interface to support dynamic dispatch. +type IConditionContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + Alias() IAliasContext + AllMethod_chain() []IMethod_chainContext + Method_chain(i int) IMethod_chainContext + Comparator() IComparatorContext + Value() IValueContext + Value_list() IValue_listContext + + // IsConditionContext differentiates from other interfaces. + IsConditionContext() +} + +type ConditionContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyConditionContext() *ConditionContext { + var p = new(ConditionContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_condition + return p +} + +func InitEmptyConditionContext(p *ConditionContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_condition +} + +func (*ConditionContext) IsConditionContext() {} + +func NewConditionContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *ConditionContext { + var p = new(ConditionContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryParserRULE_condition + + return p +} + +func (s *ConditionContext) GetParser() antlr.Parser { return s.parser } + +func (s *ConditionContext) Alias() IAliasContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IAliasContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IAliasContext) +} + +func (s *ConditionContext) AllMethod_chain() []IMethod_chainContext { + children := s.GetChildren() + len := 0 + for _, ctx := range children { + if _, ok := ctx.(IMethod_chainContext); ok { + len++ + } + } + + tst := make([]IMethod_chainContext, len) + i := 0 + for _, ctx := range children { + if t, ok := ctx.(IMethod_chainContext); ok { + tst[i] = t.(IMethod_chainContext) + i++ + } + } + + return tst +} + +func (s *ConditionContext) Method_chain(i int) IMethod_chainContext { + var t antlr.RuleContext + j := 0 + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IMethod_chainContext); ok { + if j == i { + t = ctx.(antlr.RuleContext) + break + } + j++ + } + } + + if t == nil { + return nil + } + + return t.(IMethod_chainContext) +} + +func (s *ConditionContext) Comparator() IComparatorContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IComparatorContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IComparatorContext) +} + +func (s *ConditionContext) Value() IValueContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IValueContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IValueContext) +} + +func (s *ConditionContext) Value_list() IValue_listContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IValue_listContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IValue_listContext) +} + +func (s *ConditionContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *ConditionContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *ConditionContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.EnterCondition(s) + } +} + +func (s *ConditionContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.ExitCondition(s) + } +} + +func (p *QueryParser) Condition() (localctx IConditionContext) { + localctx = NewConditionContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 18, QueryParserRULE_condition) + p.EnterOuterAlt(localctx, 1) + { + p.SetState(81) + p.Alias() + } + { + p.SetState(82) + p.Match(QueryParserT__8) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + { + p.SetState(83) + p.Method_chain() + } + { + p.SetState(84) + p.Comparator() + } + p.SetState(91) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + + switch p.GetTokenStream().LA(1) { + case QueryParserSTRING, QueryParserSTRING_WITH_WILDCARD, QueryParserNUMBER: + { + p.SetState(85) + p.Value() + } + + case QueryParserIDENTIFIER: + { + p.SetState(86) + p.Method_chain() + } + + case QueryParserT__6: + { + p.SetState(87) + p.Match(QueryParserT__6) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + { + p.SetState(88) + p.Value_list() + } + { + p.SetState(89) + p.Match(QueryParserT__7) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + + default: + p.SetError(antlr.NewNoViableAltException(p, nil, nil, nil, nil, nil)) + goto errorExit + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// IMethod_chainContext is an interface to support dynamic dispatch. +type IMethod_chainContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + AllMethod_or_variable() []IMethod_or_variableContext + Method_or_variable(i int) IMethod_or_variableContext + + // IsMethod_chainContext differentiates from other interfaces. + IsMethod_chainContext() +} + +type Method_chainContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyMethod_chainContext() *Method_chainContext { + var p = new(Method_chainContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_method_chain + return p +} + +func InitEmptyMethod_chainContext(p *Method_chainContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_method_chain +} + +func (*Method_chainContext) IsMethod_chainContext() {} + +func NewMethod_chainContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *Method_chainContext { + var p = new(Method_chainContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryParserRULE_method_chain + + return p +} + +func (s *Method_chainContext) GetParser() antlr.Parser { return s.parser } + +func (s *Method_chainContext) AllMethod_or_variable() []IMethod_or_variableContext { + children := s.GetChildren() + len := 0 + for _, ctx := range children { + if _, ok := ctx.(IMethod_or_variableContext); ok { + len++ + } + } + + tst := make([]IMethod_or_variableContext, len) + i := 0 + for _, ctx := range children { + if t, ok := ctx.(IMethod_or_variableContext); ok { + tst[i] = t.(IMethod_or_variableContext) + i++ + } + } + + return tst +} + +func (s *Method_chainContext) Method_or_variable(i int) IMethod_or_variableContext { + var t antlr.RuleContext + j := 0 + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IMethod_or_variableContext); ok { + if j == i { + t = ctx.(antlr.RuleContext) + break + } + j++ + } + } + + if t == nil { + return nil + } + + return t.(IMethod_or_variableContext) +} + +func (s *Method_chainContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *Method_chainContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *Method_chainContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.EnterMethod_chain(s) + } +} + +func (s *Method_chainContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.ExitMethod_chain(s) + } +} + +func (p *QueryParser) Method_chain() (localctx IMethod_chainContext) { + localctx = NewMethod_chainContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 20, QueryParserRULE_method_chain) + var _la int + + p.EnterOuterAlt(localctx, 1) + { + p.SetState(93) + p.Method_or_variable() + } + p.SetState(98) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + + for _la == QueryParserT__8 { + { + p.SetState(94) + p.Match(QueryParserT__8) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + { + p.SetState(95) + p.Method_or_variable() + } + + p.SetState(100) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// IMethod_or_variableContext is an interface to support dynamic dispatch. +type IMethod_or_variableContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + Method() IMethodContext + Variable() IVariableContext + + // IsMethod_or_variableContext differentiates from other interfaces. + IsMethod_or_variableContext() +} + +type Method_or_variableContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyMethod_or_variableContext() *Method_or_variableContext { + var p = new(Method_or_variableContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_method_or_variable + return p +} + +func InitEmptyMethod_or_variableContext(p *Method_or_variableContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_method_or_variable +} + +func (*Method_or_variableContext) IsMethod_or_variableContext() {} + +func NewMethod_or_variableContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *Method_or_variableContext { + var p = new(Method_or_variableContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryParserRULE_method_or_variable + + return p +} + +func (s *Method_or_variableContext) GetParser() antlr.Parser { return s.parser } + +func (s *Method_or_variableContext) Method() IMethodContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IMethodContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IMethodContext) +} + +func (s *Method_or_variableContext) Variable() IVariableContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IVariableContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IVariableContext) +} + +func (s *Method_or_variableContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *Method_or_variableContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *Method_or_variableContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.EnterMethod_or_variable(s) + } +} + +func (s *Method_or_variableContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.ExitMethod_or_variable(s) + } +} + +func (p *QueryParser) Method_or_variable() (localctx IMethod_or_variableContext) { + localctx = NewMethod_or_variableContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 22, QueryParserRULE_method_or_variable) + p.SetState(103) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + + switch p.GetInterpreter().AdaptivePredict(p.BaseParser, p.GetTokenStream(), 7, p.GetParserRuleContext()) { + case 1: + p.EnterOuterAlt(localctx, 1) + { + p.SetState(101) + p.Method() + } + + case 2: + p.EnterOuterAlt(localctx, 2) + { + p.SetState(102) + p.Variable() + } + + case antlr.ATNInvalidAltNumber: + goto errorExit + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// IMethodContext is an interface to support dynamic dispatch. +type IMethodContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + IDENTIFIER() antlr.TerminalNode + + // IsMethodContext differentiates from other interfaces. + IsMethodContext() +} + +type MethodContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyMethodContext() *MethodContext { + var p = new(MethodContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_method + return p +} + +func InitEmptyMethodContext(p *MethodContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_method +} + +func (*MethodContext) IsMethodContext() {} + +func NewMethodContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *MethodContext { + var p = new(MethodContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryParserRULE_method + + return p +} + +func (s *MethodContext) GetParser() antlr.Parser { return s.parser } + +func (s *MethodContext) IDENTIFIER() antlr.TerminalNode { + return s.GetToken(QueryParserIDENTIFIER, 0) +} + +func (s *MethodContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *MethodContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *MethodContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.EnterMethod(s) + } +} + +func (s *MethodContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.ExitMethod(s) + } +} + +func (p *QueryParser) Method() (localctx IMethodContext) { + localctx = NewMethodContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 24, QueryParserRULE_method) + p.EnterOuterAlt(localctx, 1) + { + p.SetState(105) + p.Match(QueryParserIDENTIFIER) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + { + p.SetState(106) + p.Match(QueryParserT__6) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + { + p.SetState(107) + p.Match(QueryParserT__7) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// IVariableContext is an interface to support dynamic dispatch. +type IVariableContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + IDENTIFIER() antlr.TerminalNode + + // IsVariableContext differentiates from other interfaces. + IsVariableContext() +} + +type VariableContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyVariableContext() *VariableContext { + var p = new(VariableContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_variable + return p +} + +func InitEmptyVariableContext(p *VariableContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_variable +} + +func (*VariableContext) IsVariableContext() {} + +func NewVariableContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *VariableContext { + var p = new(VariableContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryParserRULE_variable + + return p +} + +func (s *VariableContext) GetParser() antlr.Parser { return s.parser } + +func (s *VariableContext) IDENTIFIER() antlr.TerminalNode { + return s.GetToken(QueryParserIDENTIFIER, 0) +} + +func (s *VariableContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *VariableContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *VariableContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.EnterVariable(s) + } +} + +func (s *VariableContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.ExitVariable(s) + } +} + +func (p *QueryParser) Variable() (localctx IVariableContext) { + localctx = NewVariableContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 26, QueryParserRULE_variable) + p.EnterOuterAlt(localctx, 1) + { + p.SetState(109) + p.Match(QueryParserIDENTIFIER) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// IComparatorContext is an interface to support dynamic dispatch. +type IComparatorContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + // IsComparatorContext differentiates from other interfaces. + IsComparatorContext() +} + +type ComparatorContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyComparatorContext() *ComparatorContext { + var p = new(ComparatorContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_comparator + return p +} + +func InitEmptyComparatorContext(p *ComparatorContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_comparator +} + +func (*ComparatorContext) IsComparatorContext() {} + +func NewComparatorContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *ComparatorContext { + var p = new(ComparatorContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryParserRULE_comparator + + return p +} + +func (s *ComparatorContext) GetParser() antlr.Parser { return s.parser } +func (s *ComparatorContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *ComparatorContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *ComparatorContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.EnterComparator(s) + } +} + +func (s *ComparatorContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.ExitComparator(s) + } +} + +func (p *QueryParser) Comparator() (localctx IComparatorContext) { + localctx = NewComparatorContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 28, QueryParserRULE_comparator) + var _la int + + p.EnterOuterAlt(localctx, 1) + { + p.SetState(111) + _la = p.GetTokenStream().LA(1) + + if !((int64(_la) & ^0x3f) == 0 && ((int64(1)<<_la)&261120) != 0) { + p.GetErrorHandler().RecoverInline(p) + } else { + p.GetErrorHandler().ReportMatch(p) + p.Consume() + } + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// IValueContext is an interface to support dynamic dispatch. +type IValueContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + STRING() antlr.TerminalNode + NUMBER() antlr.TerminalNode + STRING_WITH_WILDCARD() antlr.TerminalNode + + // IsValueContext differentiates from other interfaces. + IsValueContext() +} + +type ValueContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyValueContext() *ValueContext { + var p = new(ValueContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_value + return p +} + +func InitEmptyValueContext(p *ValueContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_value +} + +func (*ValueContext) IsValueContext() {} + +func NewValueContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *ValueContext { + var p = new(ValueContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryParserRULE_value + + return p +} + +func (s *ValueContext) GetParser() antlr.Parser { return s.parser } + +func (s *ValueContext) STRING() antlr.TerminalNode { + return s.GetToken(QueryParserSTRING, 0) +} + +func (s *ValueContext) NUMBER() antlr.TerminalNode { + return s.GetToken(QueryParserNUMBER, 0) +} + +func (s *ValueContext) STRING_WITH_WILDCARD() antlr.TerminalNode { + return s.GetToken(QueryParserSTRING_WITH_WILDCARD, 0) +} + +func (s *ValueContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *ValueContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *ValueContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.EnterValue(s) + } +} + +func (s *ValueContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.ExitValue(s) + } +} + +func (p *QueryParser) Value() (localctx IValueContext) { + localctx = NewValueContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 30, QueryParserRULE_value) + var _la int + + p.EnterOuterAlt(localctx, 1) + { + p.SetState(113) + _la = p.GetTokenStream().LA(1) + + if !((int64(_la) & ^0x3f) == 0 && ((int64(1)<<_la)&1835008) != 0) { + p.GetErrorHandler().RecoverInline(p) + } else { + p.GetErrorHandler().ReportMatch(p) + p.Consume() + } + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// IValue_listContext is an interface to support dynamic dispatch. +type IValue_listContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + AllValue() []IValueContext + Value(i int) IValueContext + + // IsValue_listContext differentiates from other interfaces. + IsValue_listContext() +} + +type Value_listContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyValue_listContext() *Value_listContext { + var p = new(Value_listContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_value_list + return p +} + +func InitEmptyValue_listContext(p *Value_listContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryParserRULE_value_list +} + +func (*Value_listContext) IsValue_listContext() {} + +func NewValue_listContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *Value_listContext { + var p = new(Value_listContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryParserRULE_value_list + + return p +} + +func (s *Value_listContext) GetParser() antlr.Parser { return s.parser } + +func (s *Value_listContext) AllValue() []IValueContext { + children := s.GetChildren() + len := 0 + for _, ctx := range children { + if _, ok := ctx.(IValueContext); ok { + len++ + } + } + + tst := make([]IValueContext, len) + i := 0 + for _, ctx := range children { + if t, ok := ctx.(IValueContext); ok { + tst[i] = t.(IValueContext) + i++ + } + } + + return tst +} + +func (s *Value_listContext) Value(i int) IValueContext { + var t antlr.RuleContext + j := 0 + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IValueContext); ok { + if j == i { + t = ctx.(antlr.RuleContext) + break + } + j++ + } + } + + if t == nil { + return nil + } + + return t.(IValueContext) +} + +func (s *Value_listContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *Value_listContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *Value_listContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.EnterValue_list(s) + } +} + +func (s *Value_listContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(QueryListener); ok { + listenerT.ExitValue_list(s) + } +} + +func (p *QueryParser) Value_list() (localctx IValue_listContext) { + localctx = NewValue_listContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 32, QueryParserRULE_value_list) + var _la int + + p.EnterOuterAlt(localctx, 1) + { + p.SetState(115) + p.Value() + } + p.SetState(120) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + + for _la == QueryParserT__2 { + { + p.SetState(116) + p.Match(QueryParserT__2) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + { + p.SetState(117) + p.Value() + } + + p.SetState(122) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} diff --git a/sourcecode-parser/api.go b/sourcecode-parser/api.go deleted file mode 100644 index e12735c..0000000 --- a/sourcecode-parser/api.go +++ /dev/null @@ -1,50 +0,0 @@ -// api.go - -package main - -import ( - "encoding/json" - "net/http" -) - -func StartServer(graph *CodeGraph) { - http.HandleFunc("/nodes", func(w http.ResponseWriter, _ *http.Request) { - // For simplicity, let's return all nodes. You can add query params to filter nodes. - err := json.NewEncoder(w).Encode(graph.Nodes) - if err != nil { - return - } - }) - - http.HandleFunc("/source-sink-analysis", func(w http.ResponseWriter, r *http.Request) { - query := r.URL.Query() - sourceMethod := query.Get("sourceMethod") - sinkMethod := query.Get("sinkMethod") - - if sourceMethod == "" || sinkMethod == "" { - http.Error(w, "sinkMethod and sourceMethod query parameters are required", http.StatusBadRequest) - return - } - - result := AnalyzeSourceSinkPatterns(graph, sourceMethod, sinkMethod) - // Return the result as JSON - // set json content type - w.Header().Set("Content-Type", "application/json") - err := json.NewEncoder(w).Encode(result) - if err != nil { - return - } - }) - - // create a http handler to respond with index.html file content - http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - // Read the index.html file from html directory - http.ServeFile(w, r, "html/index.html") - }) - - //nolint:all - err := http.ListenAndServe(":8080", nil) - if err != nil { - return - } -} diff --git a/sourcecode-parser/construct.go b/sourcecode-parser/construct.go index 0a0a074..192be95 100644 --- a/sourcecode-parser/construct.go +++ b/sourcecode-parser/construct.go @@ -9,11 +9,13 @@ import ( "os" "path/filepath" "strings" + "sync" + "time" "github.com/shivasurya/code-pathfinder/sourcecode-parser/model" + "github.com/smacker/go-tree-sitter/java" sitter "github.com/smacker/go-tree-sitter" - "github.com/smacker/go-tree-sitter/java" //nolint:all ) @@ -99,6 +101,7 @@ func isJavaSourceFile(filename string) bool { return filepath.Ext(filename) == ".java" } +//nolint:all func hasAccess(node *sitter.Node, variableName string, sourceCode []byte) bool { if node == nil { return false @@ -395,7 +398,8 @@ func buildGraphFromAST(node *sitter.Node, sourceCode []byte, graph *CodeGraph, c } if node.Type() == "local_variable_declaration" { scope = "local" - hasAccessValue = hasAccess(node.NextSibling(), variableName, sourceCode) + //nolint:all + // hasAccessValue = hasAccess(node.NextSibling(), variableName, sourceCode) } else { scope = "field" } @@ -508,7 +512,10 @@ func extractMethodName(node *sitter.Node, sourceCode []byte, filepath string) (s func getFiles(directory string) ([]string, error) { var files []string - err := filepath.Walk(directory, func(path string, info os.FileInfo, _ error) error { + err := filepath.Walk(directory, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } if !info.IsDir() { // append only java files if filepath.Ext(path) == ".java" { @@ -529,45 +536,123 @@ func readFile(path string) ([]byte, error) { } func Initialize(directory string) *CodeGraph { - // Initialize the parser - parser := sitter.NewParser() - defer parser.Close() - - // Set the language (Java in this case) - parser.SetLanguage(java.GetLanguage()) - codeGraph := NewCodeGraph() + // record start time + start := time.Now() files, err := getFiles(directory) if err != nil { //nolint:all - log.Fatal(err) + log.Println("Directory not found:", err) + return codeGraph } - for _, file := range files { - sourceCode, err := readFile(file) - if err != nil { - log.Fatal(err) - } - // Parse the source code - tree, err := parser.ParseCtx(context.TODO(), nil, sourceCode) - if err != nil { - log.Fatal(err) - } - //nolint:all - defer tree.Close() - // TODO: Merge the tree into a single root node - // TODO: normalize the class name without duplication of class, method names + totalFiles := len(files) + numWorkers := 5 // Number of concurrent workers + fileChan := make(chan string, totalFiles) + resultChan := make(chan *CodeGraph, totalFiles) + statusChan := make(chan string, numWorkers) + progressChan := make(chan int, totalFiles) + var wg sync.WaitGroup + + // Worker function + worker := func(workerID int) { + // Initialize the parser for each worker + parser := sitter.NewParser() + defer parser.Close() + + // Set the language (Java in this case) + parser.SetLanguage(java.GetLanguage()) + + for file := range fileChan { + fileName := filepath.Base(file) + statusChan <- fmt.Sprintf("\033[32mWorker %d ....... Reading and parsing code %s\033[0m", workerID, fileName) + sourceCode, err := readFile(file) + if err != nil { + log.Println("File not found:", err) + continue + } + // Parse the source code + tree, err := parser.ParseCtx(context.TODO(), nil, sourceCode) + if err != nil { + log.Println("Error parsing file:", err) + continue + } + //nolint:all + defer tree.Close() - rootNode := tree.RootNode() + rootNode := tree.RootNode() + localGraph := NewCodeGraph() + statusChan <- fmt.Sprintf("\033[32mWorker %d ....... Building graph and traversing code %s\033[0m", workerID, fileName) + buildGraphFromAST(rootNode, sourceCode, localGraph, nil, file) + statusChan <- fmt.Sprintf("\033[32mWorker %d ....... Done processing file %s\033[0m", workerID, fileName) - buildGraphFromAST(rootNode, sourceCode, codeGraph, nil, file) + resultChan <- localGraph + progressChan <- 1 + } + wg.Done() } - //nolint:all - // log.Println("Graph built successfully:", codeGraph) + + // Start workers + wg.Add(numWorkers) + for i := 0; i < numWorkers; i++ { + go worker(i + 1) + } + + // Send files to workers + for _, file := range files { + fileChan <- file + } + close(fileChan) + + // Status updater + go func() { + statusLines := make([]string, numWorkers) + progress := 0 + for { + select { + case status, ok := <-statusChan: + if !ok { + return + } + workerID := int(status[12] - '0') + statusLines[workerID-1] = status + case _, ok := <-progressChan: + if !ok { + return + } + progress++ + } + fmt.Print("\033[H\033[J") // Clear the screen + for _, line := range statusLines { + fmt.Println(line) + } + fmt.Printf("Progress: %d%%\n", (progress*100)/totalFiles) + } + }() + + // Wait for all workers to finish + go func() { + wg.Wait() + close(resultChan) + close(statusChan) + close(progressChan) + }() + + // Collect results + for localGraph := range resultChan { + for _, node := range localGraph.Nodes { + codeGraph.AddNode(node) + } + for _, edge := range localGraph.Edges { + codeGraph.AddEdge(edge.From, edge.To) + } + } + + end := time.Now() + elapsed := end.Sub(start) + log.Println("Elapsed time: ", elapsed) log.Println("Graph built successfully") - //nolint:all - // go StartServer(codeGraph) - // select {} + return codeGraph } diff --git a/sourcecode-parser/go.mod b/sourcecode-parser/go.mod index 1dcf045..80328f8 100644 --- a/sourcecode-parser/go.mod +++ b/sourcecode-parser/go.mod @@ -1,11 +1,14 @@ module github.com/shivasurya/code-pathfinder/sourcecode-parser -go 1.20 +go 1.22.0 require github.com/smacker/go-tree-sitter v0.0.0-20240625050157-a31a98a7c0f6 -require queryparser v0.0.0-00010101000000-000000000000 +require github.com/antlr4-go/antlr/v4 v4.13.1 -require github.com/jedib0t/go-pretty/v6 v6.5.9 // indirect +require github.com/stretchr/testify v1.9.0 // indirect -replace queryparser => ./queryparser +require ( + github.com/expr-lang/expr v1.16.9 // indirect + golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect +) diff --git a/sourcecode-parser/go.sum b/sourcecode-parser/go.sum index 5906dfc..7342dd8 100644 --- a/sourcecode-parser/go.sum +++ b/sourcecode-parser/go.sum @@ -1,23 +1,22 @@ +github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ= +github.com/antlr4-go/antlr/v4 v4.13.1/go.mod h1:GKmUxMtwp6ZgGwZSva4eWPC5mS6vUAmOABFgjdkM7Nw= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/jedib0t/go-pretty/v6 v6.5.9 h1:ACteMBRrrmm1gMsXe9PSTOClQ63IXDUt03H5U+UV8OU= -github.com/jedib0t/go-pretty/v6 v6.5.9/go.mod h1:zbn98qrYlh95FIhwwsbIip0LYpwSG8SUOScs+v9/t0E= -github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= -github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/expr-lang/expr v1.16.9 h1:WUAzmR0JNI9JCiF0/ewwHB1gmcGw5wW7nWt8gc6PpCI= +github.com/expr-lang/expr v1.16.9/go.mod h1:8/vRC7+7HBzESEqt5kKpYXxrxkr31SaO8r40VO/1IT4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/smacker/go-tree-sitter v0.0.0-20240625050157-a31a98a7c0f6 h1:mtD4ESyObQZnRVxHFcaYp2d7jMBDa4WJRXSB1Vszj+A= github.com/smacker/go-tree-sitter v0.0.0-20240625050157-a31a98a7c0f6/go.mod h1:q99oHDsbP0xRwmn7Vmob8gbSMNyvJ83OauXPSuHQuKE= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.4/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/sourcecode-parser/go.work b/sourcecode-parser/go.work index 9d9d8bd..96b89a3 100644 --- a/sourcecode-parser/go.work +++ b/sourcecode-parser/go.work @@ -1,6 +1,3 @@ -go 1.21 +go 1.22.0 -use ( - . - queryparser -) \ No newline at end of file +use . diff --git a/sourcecode-parser/go.work.sum b/sourcecode-parser/go.work.sum index 0941d28..26167c6 100644 --- a/sourcecode-parser/go.work.sum +++ b/sourcecode-parser/go.work.sum @@ -1,17 +1,26 @@ github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g= github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/pprof v0.0.0-20211214055906-6f57359322fd h1:1FjCyPC+syAzJ5/2S8fqdZK1R22vvA0J7JZKcuOIQ7Y= github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= -github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= -github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/pkg/profile v1.7.0 h1:hnbDkaNWPCLMO9wGLdBFTIZvzDrDfBM2072E1S9gJkA= github.com/pkg/profile v1.7.0/go.mod h1:8Uer0jas47ZQMJ7VD+OHknK4YDY07LPUC6dEvqDjvNo= -github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= +golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/tools v0.21.0 h1:qc0xYgIbsSDt9EyWz05J5wfa7LOVW0YTLOXrqdLAWIw= +golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= +golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= diff --git a/sourcecode-parser/main.go b/sourcecode-parser/main.go index 952dd0c..599a937 100644 --- a/sourcecode-parser/main.go +++ b/sourcecode-parser/main.go @@ -6,64 +6,101 @@ import ( "flag" "fmt" "os" - "queryparser" + "strconv" "strings" - "github.com/jedib0t/go-pretty/v6/table" + parser "github.com/shivasurya/code-pathfinder/sourcecode-parser/antlr" ) -var ( - Version = "dev" - GitCommit = "none" +// Version is the current version of the application. +const ( + Version = "0.0.22" + GitCommit = "HEAD" ) +func main() { + // accept command line param optional path to source code + output := flag.String("output", "", "Supported output format: json") + outputFile := flag.String("output-file", "", "Output file path") + project := flag.String("project", "", "Project to analyze") + query := flag.String("query", "", "Query to execute") + stdin := flag.Bool("stdin", false, "Read query from stdin") + versionFlag := flag.Bool("version", false, "Print the version information and exit") + flag.Parse() + + if *versionFlag { + fmt.Printf("Version: %s\n", Version) + fmt.Printf("Git Commit: %s\n", GitCommit) + os.Exit(0) + } + + result, err := executeCLIQuery(*project, *query, *output, *stdin) + if err != nil { + fmt.Println(err) + } + if *outputFile != "" { + file, err := os.Create(*outputFile) + if err != nil { + fmt.Println("Error creating output file: ", err) + } + defer func(file *os.File) { + err := file.Close() + if err != nil { + fmt.Println("Error closing output file: ", err) + os.Exit(1) + } + }(file) + _, err = file.WriteString(result) + if err != nil { + fmt.Println("Error writing output file: ", err) + } + } else { + fmt.Println(result) + } +} + func processQuery(input string, graph *CodeGraph, output string) (string, error) { fmt.Println("Executing query: " + input) - lex := queryparser.NewLexer(input) - pars := queryparser.NewParser(lex) - query := pars.ParseQuery() - if query == nil { - return "", fmt.Errorf("failed to parse query: %v", pars.Errors()) - } - entities := QueryEntities(graph, query) + parsedQuery := parser.ParseQuery(input) + entities := QueryEntities(graph, parsedQuery) if output == "json" { // convert struct to query_results - queryResults, err := json.Marshal(entities) + results := []map[string]interface{}{} + for _, entity := range entities { + result := make(map[string]interface{}) + result["file"] = entity.File + result["line"] = entity.LineNumber + result["code"] = entity.CodeSnippet + results = append(results, result) + } + queryResults, err := json.Marshal(results) if err != nil { return "", fmt.Errorf("error processing query results: %w", err) } return string(queryResults), nil } - - t := table.NewWriter() - t.SetOutputMirror(os.Stdout) - t.AppendHeader(table.Row{"#", "File", "Line Number", "Type", "Name", "Code Snippet"}) - t.SetColumnConfigs([]table.ColumnConfig{ - { - Name: "File", - WidthMin: 6, - WidthMax: 40, - }, - { - Name: "Code Snippet", - WidthMin: 6, - WidthMax: 60, - }, - }) - for i, entity := range entities { - t.AppendRow([]interface{}{i + 1, entity.File, entity.LineNumber, entity.Type, entity.Name, entity.CodeSnippet}) - t.AppendSeparator() + result := "" + for _, entity := range entities { + // add blockquotes to string + result += entity.File + ":" + strconv.Itoa(int(entity.LineNumber)) + "\n" + result += "------------\n" + result += "> " + entity.CodeSnippet + "\n" + result += "------------" + result += "\n" } - t.SetStyle(table.StyleLight) - t.Render() - return "", nil + return result, nil } -func executeProject(project, query, output string, stdin bool) (string, error) { +func InitializeProject(project string) *CodeGraph { graph := NewCodeGraph() if project != "" { graph = Initialize(project) } + return graph +} + +func executeCLIQuery(project, query, output string, stdin bool) (string, error) { + graph := InitializeProject(project) if stdin { // read from stdin @@ -79,57 +116,45 @@ func executeProject(project, query, output string, stdin bool) (string, error) { if strings.HasPrefix(input, ":quit") { return "Okay, Bye!", nil } - _, err = processQuery(input, graph, output) + result, err := processQuery(input, graph, output) + fmt.Println(result) if err != nil { return "", fmt.Errorf("error processing query: %w", err) } } - } else if output != "" && query != "" { - return processQuery(query, graph, output) - } - return "", fmt.Errorf("output and query parameters are required") -} - -func main() { - // accept command line param optional path to source code - output := flag.String("output", "", "Supported output format: json") - outputFile := flag.String("output-file", "", "Output file path") - query := flag.String("query", "", "Query to execute") - project := flag.String("project", "", "Project to analyze") - stdin := flag.Bool("stdin", false, "Read query from stdin") - versionFlag := flag.Bool("version", false, "Print the version information and exit") - flag.Parse() - - if *versionFlag { - fmt.Printf("Version: %s\n", Version) - fmt.Printf("Git Commit: %s\n", GitCommit) - os.Exit(0) - } - - result, err := executeProject(*project, *query, *output, *stdin) - if err != nil { - fmt.Println(err) - return - } - if *outputFile != "" { - file, err := os.Create(*outputFile) - if err != nil { - fmt.Println("Error creating output file: ", err) - return - } - defer func(file *os.File) { - err := file.Close() - if err != nil { - fmt.Println("Error closing output file: ", err) - return - } - }(file) - _, err = file.WriteString(result) + } else { + // read from command line + result, err := processQuery(query, graph, output) if err != nil { - fmt.Println("Error writing output file: ", err) - return + return "", fmt.Errorf("error processing query: %w", err) } - } else { - fmt.Println(result) + return result, nil } } + +// func parseQueryWithExpr(inputQuery string) { +// +// // string replace "md." with "" +// expression = strings.Replace(expression, "md.", "", -1) +// fmt.Println(expression) +// env := map[string]interface{}{ +// "getName": func() string { +// return "onCreate" +// }, +// "getVisibility": func() string { +// return "public" +// }, +// "getReturnType": func() string { +// return "voids" +// }, +// } +// program, err := expr.Compile(expression, expr.Env(env)) +// if err != nil { +// fmt.Println(err) +// } +// output, err := expr.Run(program, env) +// if err != nil { +// fmt.Println(err) +// } +// fmt.Println(output) +//} diff --git a/sourcecode-parser/main_test.go b/sourcecode-parser/main_test.go index d9e93f8..10f9b5f 100644 --- a/sourcecode-parser/main_test.go +++ b/sourcecode-parser/main_test.go @@ -1,13 +1,15 @@ package main import ( + "encoding/json" + "fmt" "testing" ) func TestProcessQuery(t *testing.T) { graph := NewCodeGraph() output := "json" - input := "FIND variable_declaration WHERE visibility = 'private'" + input := "FIND method_declaration AS md WHERE md.GetVisibility() == \"public\"" result, err := processQuery(input, graph, output) if err != nil { @@ -21,20 +23,88 @@ func TestProcessQuery(t *testing.T) { } } -func TestExecuteProject(t *testing.T) { +func TestExecuteCLIQuery(t *testing.T) { // get project from command line project := "../test-src/" - query := "FIND variable_declaration WHERE visibility = 'private'" + queries := []string{ + `FIND method_declaration AS md WHERE md.getName() == "onCreate"`, + `FIND variable_declaration AS vd WHERE vd.getVisibility() == "private"`, + } output := "json" - result, err := executeProject(project, query, output, false) - if err != nil { - t.Errorf("Expected no error, got %v", err) + for _, query := range queries { + fmt.Println(query) + result, err := executeCLIQuery(project, query, output, false) + if err != nil { + t.Errorf("Expected no error for query %s, got %v", query, err) + } + var resultMap []map[string]interface{} + err = json.Unmarshal([]byte(result), &resultMap) + if len(resultMap) == 0 { + t.Errorf("Expected result to be non-empty for query %s", query) + } + if err != nil { + t.Errorf("Expected no error for query %s, got %v", query, err) + } + + // Here you can add assertions based on what you expect the result to be. + // This will depend on the specifics of your executeProject function. + if result == "" { + t.Errorf("Expected result to be non-empty for query %s", query) + } } +} - // Here you can add assertions based on what you expect the result to be. - // This will depend on the specifics of your executeProject function. - if result == "" { - t.Errorf("Expected result to be non-empty") +func TestInitializeProject(t *testing.T) { + tests := []struct { + name string + project string + want *CodeGraph + }{ + { + name: "Empty project", + project: "", + want: NewCodeGraph(), + }, + { + name: "Valid project", + project: "../test-src/", + want: Initialize("../test-src/"), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := InitializeProject(tt.project) + if got == nil { + t.Errorf("InitializeProject() returned nil") + } + if tt.project == "" && len(got.Nodes) != 0 { + t.Errorf("InitializeProject() with empty project should return empty graph") + } + if tt.project != "" && len(got.Nodes) == 0 { + t.Errorf("InitializeProject() with valid project should return non-empty graph") + } + }) + } +} + +func TestInitializeProjectWithInvalidPath(t *testing.T) { + invalidProject := "/path/to/nonexistent/project" + got := InitializeProject(invalidProject) + if got == nil || got.Nodes == nil { + t.Errorf("InitializeProject() with invalid path should return empty graph, not nil") + } else if len(got.Nodes) != 0 { + t.Errorf("InitializeProject() with invalid path should return empty graph") + } +} + +func TestInitializeProjectConsistency(t *testing.T) { + project := "../test-src/" + graph1 := InitializeProject(project) + graph2 := InitializeProject(project) + + if len(graph1.Nodes) != len(graph2.Nodes) { + t.Errorf("InitializeProject() should return consistent results for the same project") } } diff --git a/sourcecode-parser/query.go b/sourcecode-parser/query.go new file mode 100644 index 0000000..532b4a4 --- /dev/null +++ b/sourcecode-parser/query.go @@ -0,0 +1,240 @@ +package main + +import ( + "fmt" + + "github.com/expr-lang/expr" + parser "github.com/shivasurya/code-pathfinder/sourcecode-parser/antlr" +) + +type Env struct { + Node *GraphNode +} + +func (env *Env) GetVisibility() string { + return env.Node.Modifier +} + +func (env *Env) GetAnnotations() []string { + return env.Node.Annotation +} + +func (env *Env) GetReturnType() string { + return env.Node.ReturnType +} + +func (env *Env) GetName() string { + return env.Node.Name +} + +func (env *Env) GetArgumentTypes() []string { + return env.Node.MethodArgumentsType +} + +func (env *Env) GetArgumentNames() []string { + return env.Node.MethodArgumentsValue +} + +func (env *Env) GetSuperClass() string { + return env.Node.SuperClass +} + +func (env *Env) GetInterfaces() []string { + return env.Node.Interface +} + +func (env *Env) GetScope() string { + return env.Node.Scope +} + +func (env *Env) GetVariableValue() string { + return env.Node.VariableValue +} + +func (env *Env) GetVariableDataType() string { + return env.Node.DataType +} + +func (env *Env) GetThrowsTypes() []string { + return env.Node.ThrowsExceptions +} + +func (env *Env) HasAccess() bool { + return env.Node.hasAccess +} + +func (env *Env) IsJavaSourceFile() bool { + return env.Node.isJavaSourceFile +} + +func (env *Env) GetCommentAuthor() string { + if env.Node.JavaDoc != nil { + if env.Node.JavaDoc.Author != "" { + return env.Node.JavaDoc.Author + } + } + return "" +} + +func (env *Env) GetCommentSee() string { + if env.Node.JavaDoc != nil { + for _, docTag := range env.Node.JavaDoc.Tags { + if docTag.TagName == "see" && docTag.Text != "" { + return docTag.Text + } + } + } + return "" +} + +func (env *Env) GetCommentVersion() string { + if env.Node.JavaDoc != nil { + for _, docTag := range env.Node.JavaDoc.Tags { + if docTag.TagName == "version" && docTag.Text != "" { + return docTag.Text + } + } + } + return "" +} + +func (env *Env) GetCommentSince() string { + if env.Node.JavaDoc != nil { + for _, docTag := range env.Node.JavaDoc.Tags { + if docTag.TagName == "since" && docTag.Text != "" { + return docTag.Text + } + } + } + return "" +} + +func (env *Env) GetCommentParam() string { + if env.Node.JavaDoc != nil { + for _, docTag := range env.Node.JavaDoc.Tags { + if docTag.TagName == "param" && docTag.Text != "" { + return docTag.Text + } + } + } + return "" +} + +func (env *Env) GetCommentThrows() string { + if env.Node.JavaDoc != nil { + for _, docTag := range env.Node.JavaDoc.Tags { + if docTag.TagName == "throws" && docTag.Text != "" { + return docTag.Text + } + } + } + return "" +} + +func (env *Env) GetCommentReturn() string { + if env.Node.JavaDoc != nil { + for _, docTag := range env.Node.JavaDoc.Tags { + if docTag.TagName == "return" && docTag.Text != "" { + return docTag.Text + } + } + } + return "" +} + +func QueryEntities(graph *CodeGraph, query parser.Query) []*GraphNode { + result := make([]*GraphNode, 0) + + for _, node := range graph.Nodes { + for _, entity := range query.SelectList { + if entity.Entity == node.Type && FilterEntities(node, query) { + result = append(result, node) + } + } + } + return result +} + +func generateProxyEnv(node *GraphNode, query parser.Query) map[string]interface{} { + proxyenv := Env{Node: node} + methodDeclaration := "method_declaration" + classDeclaration := "class_declaration" + methodInvocation := "method_invocation" + variableDeclaration := "variable_declaration" + // print query select list + for _, entity := range query.SelectList { + switch entity.Entity { + case "method_declaration": + methodDeclaration = entity.Alias + case "class_declaration": + classDeclaration = entity.Alias + case "method_invocation": + methodInvocation = entity.Alias + case "variable_declaration": + variableDeclaration = entity.Alias + } + } + env := map[string]interface{}{ + "isJavaSourceFile": proxyenv.IsJavaSourceFile(), + "getCommentAuthor": proxyenv.GetCommentAuthor(), + "getCommentSee": proxyenv.GetCommentSee(), + "getCommentVersion": proxyenv.GetCommentVersion(), + "getCommentSince": proxyenv.GetCommentSince(), + "getCommentParam": proxyenv.GetCommentParam(), + "getCommentThrows": proxyenv.GetCommentThrows(), + "getCommentReturn": proxyenv.GetCommentReturn(), + methodDeclaration: map[string]interface{}{ + "getVisibility": proxyenv.GetVisibility(), + "getAnnotation": proxyenv.GetAnnotations(), + "getReturnType": proxyenv.GetReturnType, + "getName": proxyenv.GetName, + "getArgumentType": proxyenv.GetArgumentTypes(), + "getArgumentName": proxyenv.GetArgumentNames(), + "getInterface": proxyenv.GetInterfaces(), + "getThrowsType": proxyenv.GetThrowsTypes(), + }, + classDeclaration: map[string]interface{}{ + "getSuperClass": proxyenv.GetSuperClass, + "getName": proxyenv.GetName, + "getAnnotation": proxyenv.GetAnnotations(), + "getVisibility": proxyenv.GetVisibility, + "getInterface": proxyenv.GetInterfaces(), + }, + methodInvocation: map[string]interface{}{ + "getArgumentName": proxyenv.GetArgumentNames(), + "getName": proxyenv.GetName, + }, + variableDeclaration: map[string]interface{}{ + "getName": proxyenv.GetName, + "getVisibility": proxyenv.GetVisibility, + "getVariableValue": proxyenv.GetVariableValue, + "getVariableDataType": proxyenv.GetVariableDataType, + "getScope": proxyenv.GetScope(), + }, + } + return env +} + +func FilterEntities(node *GraphNode, query parser.Query) bool { + expression := query.Expression + if expression == "" { + return true + } + + env := generateProxyEnv(node, query) + + program, err := expr.Compile(expression, expr.Env(env)) + if err != nil { + fmt.Println("Error compiling expression: ", err) + return false + } + output, err := expr.Run(program, env) + if err != nil { + fmt.Println("Error evaluating expression: ", err) + return false + } + if output.(bool) { + return true + } + return false +} diff --git a/sourcecode-parser/queryparser/go.mod b/sourcecode-parser/queryparser/go.mod deleted file mode 100644 index 459e20b..0000000 --- a/sourcecode-parser/queryparser/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module queryparser - -go 1.20 diff --git a/sourcecode-parser/queryparser/lexer.go b/sourcecode-parser/queryparser/lexer.go deleted file mode 100644 index e53873a..0000000 --- a/sourcecode-parser/queryparser/lexer.go +++ /dev/null @@ -1,90 +0,0 @@ -package queryparser - -func NewLexer(input string) *Lexer { - return &Lexer{input: input} -} - -type Lexer struct { - input string - position int // current position in input (points to current char) - readPosition int // current reading position (after current char) - ch byte // current char under examination -} - -func (l *Lexer) readChar() { - if l.readPosition >= len(l.input) { - l.ch = 0 - } else { - l.ch = l.input[l.readPosition] - } - l.position = l.readPosition - l.readPosition++ -} - -func (l *Lexer) NextToken() Token { - var tok Token - l.skipWhitespace() - - switch l.ch { - case '=': - tok = Token{Type: OPERATOR, Literal: string(l.ch)} - case '!': - ch := l.ch - l.readChar() - tok = Token{Type: OPERATOR, Literal: string(ch) + string(l.ch)} - case '\'': - tok.Type = STRING - tok.Literal = l.readString() - case '(': - tok = Token{Type: LPAREN, Literal: string(l.ch)} - case ')': - tok = Token{Type: RPAREN, Literal: string(l.ch)} - case 0: // End of file or input - tok.Type = EOF - tok.Literal = "" - default: - if isLetter(l.ch) { - tok.Literal = l.readIdentifier() - tok.Type = LookupIdent(tok.Literal) - return tok - } else if l.ch == '"' { - tok.Type = STRING - tok.Literal = l.readString() - return tok - } else { - tok = Token{Type: ILLEGAL, Literal: string(l.ch)} - } - } - - l.readChar() - return tok -} - -func (l *Lexer) readIdentifier() string { - position := l.position - for isLetter(l.ch) { - l.readChar() - } - return l.input[position:l.position] -} - -func (l *Lexer) readString() string { - startPosition := l.position + 1 // skip the initial quote - for { - l.readChar() - if l.ch == '"' || l.ch == '\'' || l.ch == 0 { - break - } - } - return l.input[startPosition:l.position] -} - -func (l *Lexer) skipWhitespace() { - for l.ch == ' ' || l.ch == '\t' || l.ch == '\n' || l.ch == '\r' { - l.readChar() - } -} - -func isLetter(ch byte) bool { - return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') || ch == '_' -} diff --git a/sourcecode-parser/queryparser/parser.go b/sourcecode-parser/queryparser/parser.go deleted file mode 100644 index 4470fbb..0000000 --- a/sourcecode-parser/queryparser/parser.go +++ /dev/null @@ -1,178 +0,0 @@ -package queryparser - -import "fmt" - -type Parser struct { - l *Lexer - errors []string - curToken Token - peekToken Token -} - -func NewParser(l *Lexer) *Parser { - p := &Parser{l: l, errors: []string{}} - // Read two tokens, so curToken and peekToken are both set - p.nextToken() - p.nextToken() - return p -} - -func (p *Parser) Errors() []string { - return p.errors -} - -func (p *Parser) peekError(t TokenType) { - msg := fmt.Sprintf("expected next token to be %s, got %s instead", t, p.peekToken.Type) - p.errors = append(p.errors, msg) -} - -func (p *Parser) nextToken() { - p.peekToken = p.l.NextToken() - p.curToken = p.peekToken -} - -func (p *Parser) parseExpression() Expr { - expr := p.parseLogicalOr() // Start with the lowest precedence - return expr -} - -func (p *Parser) parseLogicalOr() Expr { - expr := p.parseLogicalAnd() - for p.curToken.Type == KEYWORD && p.peekToken.Literal == "OR" { - p.nextToken() - right := p.parseLogicalAnd() - expr = &BinaryExpr{ - Left: expr, - Op: "OR", - Right: right, - } - } - return expr -} - -func (p *Parser) parseLogicalAnd() Expr { - expr := p.parseGroup() - for p.curToken.Type == KEYWORD && p.peekToken.Literal == "AND" { - p.nextToken() - right := p.parseGroup() - expr = &BinaryExpr{ - Left: expr, - Op: "AND", - Right: right, - } - } - return expr -} - -func (p *Parser) parseGroup() Expr { - if p.curToken.Type == LPAREN { - p.nextToken() // Skip '(' - expr := p.parseExpression() // Parse expression within parentheses - if p.curToken.Type != RPAREN { - p.peekError(p.curToken.Type) - return nil - } - p.nextToken() // Skip ')' - return expr - } - return p.parseCondition() // Parse a basic condition -} - -func (p *Parser) parseCondition() *Condition { - if p.curToken.Type != IDENT { - p.peekError(IDENT) - return nil - } - - field := p.curToken.Literal - p.nextToken() - - if p.curToken.Type != OPERATOR { - p.peekError(OPERATOR) - return nil - } - - operator := p.curToken.Literal - p.nextToken() - - if p.curToken.Type != STRING && p.curToken.Type != IDENT { - p.peekError(STRING) - return nil - } - value := p.curToken.Literal - p.nextToken() // move past the value - - return &Condition{Field: field, Operator: operator, Value: value} -} - -type EvalContext interface { - GetValue(key string, val string) string // Retrieves a value based on a key, which helps in condition evaluation. -} - -type Expr interface { - Evaluate(ctx EvalContext) bool -} - -type BinaryExpr struct { - Left Expr - Right Expr - Op string -} - -func (p *Parser) ParseQuery() *Query { - // fmt.Printf("Current token: %s\n", p.curToken.Literal) // Debug output - - query := &Query{} - - if p.curToken.Type != KEYWORD || p.curToken.Literal != "FIND" { - p.peekError(KEYWORD) - return nil - } - - query.Operation = p.curToken.Literal - p.nextToken() - - if p.curToken.Type != IDENT { - p.peekError(IDENT) - return nil - } - - query.Entity = p.curToken.Literal - p.nextToken() - - if p.curToken.Type != KEYWORD || p.curToken.Literal != "WHERE" { - p.peekError(KEYWORD) - return nil - } - - p.nextToken() - expr := p.parseExpression() - if expr == nil { - // handle error or invalid expression - return nil - } - query.Conditions = expr - - return query -} - -func (b *BinaryExpr) Evaluate(ctx EvalContext) bool { - switch b.Op { - case "AND": - return b.Left.Evaluate(ctx) && b.Right.Evaluate(ctx) - case "OR": - return b.Left.Evaluate(ctx) || b.Right.Evaluate(ctx) - } - return false -} - -func (c *Condition) Evaluate(ctx EvalContext) bool { - fieldValue := ctx.GetValue(c.Field, c.Value) - switch c.Operator { - case "=": - return fieldValue == c.Value - case "!=": - return fieldValue != c.Value - } - return false -} diff --git a/sourcecode-parser/queryparser/tokenizer.go b/sourcecode-parser/queryparser/tokenizer.go deleted file mode 100644 index 6418611..0000000 --- a/sourcecode-parser/queryparser/tokenizer.go +++ /dev/null @@ -1,79 +0,0 @@ -package queryparser - -import "fmt" - -// Token represents a lexical token. -type TokenType int - -const ( - ILLEGAL TokenType = iota - EOF - WS - // Special tokens - IDENT // Identifiers - STRING // String literals - KEYWORD // Keywords such as FIND, WHERE - OPERATOR // Operators such as =, INCLUDES, MATCHES - LPAREN // Left parenthesis '(' - RPAREN -) - -type Token struct { - Type TokenType - Literal string -} - -type Node interface { - node() -} - -type Query struct { - Operation string - Entity string - Conditions Expr -} - -type Condition struct { - Field string - Operator string - Value string -} - -func (q Query) node() {} -func (c Condition) node() {} - -// Define keywords -var keywords = map[string]TokenType{ - "FIND": KEYWORD, - "WHERE": KEYWORD, - "AND": KEYWORD, - "OR": KEYWORD, -} - -func LookupIdent(ident string) TokenType { - if tok, ok := keywords[ident]; ok { - return tok - } - return IDENT -} - -func (t TokenType) String() string { - switch t { - case EOF: - return "EOF" - case IDENT: - return "IDENT" - case KEYWORD: - return "KEYWORD" - case STRING: - return "STRING" - case OPERATOR: - return "OPERATOR" - case WS: - return "WS" - case ILLEGAL: - return "ILLEGAL" - default: - return fmt.Sprintf("UNKNOWN(%d)", int(t)) - } -} diff --git a/sourcecode-parser/source_sink.go b/sourcecode-parser/source_sink.go index 91957d5..fbdd0bc 100644 --- a/sourcecode-parser/source_sink.go +++ b/sourcecode-parser/source_sink.go @@ -3,7 +3,6 @@ package main import ( "fmt" - "queryparser" ) type Result struct { @@ -64,154 +63,3 @@ func AnalyzeSourceSinkPatterns(graph *CodeGraph, sourceMethodName, sinkMethodNam // Return true if sourceNode is connected to sinkNode as a result of the DFS return Result{IsConnected: isConnected, SourceMethod: sourceNode.CodeSnippet, SinkMethod: sinkNode.CodeSnippet, SourceLine: sourceNode.LineNumber, SinkLine: sinkNode.LineNumber} } - -type GraphNodeContext struct { - Node *GraphNode -} - -// GetValue returns the value of a field in a GraphNode based on the key. -func (gnc *GraphNodeContext) GetValue(key, val string) string { - switch key { - case "visibility": - return gnc.Node.Modifier - case "annotation": - for _, annotation := range gnc.Node.Annotation { - if annotation == val { - return annotation - } - } - return "" - case "returntype": - return gnc.Node.ReturnType - case "name": - return gnc.Node.Name - case "argumentype": - // check value in MethodArgumentsType array - for i, arg := range gnc.Node.MethodArgumentsType { - if arg == val { - return gnc.Node.MethodArgumentsType[i] - } - } - return "" - case "argumentname": - // check value in MethodArgumentsValue array - for i, arg := range gnc.Node.MethodArgumentsValue { - if arg == val { - return gnc.Node.MethodArgumentsValue[i] - } - } - return "" - case "superclass": - return gnc.Node.SuperClass - case "interface": - // check value in Interface array - for i, iface := range gnc.Node.Interface { - if iface == val { - return gnc.Node.Interface[i] - } - } - return "" - case "scope": - return gnc.Node.Scope - case "variablevalue": - return gnc.Node.VariableValue - case "variabledatatype": - return gnc.Node.DataType - case "throwstype": - for i, arg := range gnc.Node.ThrowsExceptions { - if arg == val { - return gnc.Node.ThrowsExceptions[i] - } - } - return "" - case "has_access": - if gnc.Node.hasAccess { - return "true" - } - return "false" - case "is_java_source": - if gnc.Node.isJavaSourceFile { - return "true" - } - return "false" - case "comment_author": - if gnc.Node.JavaDoc != nil { - if gnc.Node.JavaDoc.Author != "" { - return gnc.Node.JavaDoc.Author - } - } - return "" - case "comment_see": - if gnc.Node.JavaDoc != nil { - for _, docTag := range gnc.Node.JavaDoc.Tags { - if docTag.TagName == "see" && docTag.Text != "" { - if docTag.Text == val { - return docTag.Text - } - } - } - } - return "" - case "comment_version": - if gnc.Node.JavaDoc != nil { - for _, docTag := range gnc.Node.JavaDoc.Tags { - if docTag.TagName == "version" && docTag.Text != "" { - if docTag.Text == val { - return docTag.Text - } - } - } - } - return "" - case "comment_since": - if gnc.Node.JavaDoc != nil { - for _, docTag := range gnc.Node.JavaDoc.Tags { - if docTag.TagName == "since" && docTag.Text != "" { - if docTag.Text == val { - return docTag.Text - } - } - } - } - return "" - case "comment_param": - if gnc.Node.JavaDoc != nil { - for _, docTag := range gnc.Node.JavaDoc.Tags { - if docTag.TagName == "param" && docTag.Text != "" { - if docTag.Text == val { - return docTag.Text - } - } - } - } - return "" - case "comment_throws": - if gnc.Node.JavaDoc != nil { - for _, docTag := range gnc.Node.JavaDoc.Tags { - if docTag.TagName == "throws" && docTag.Text != "" { - if docTag.Text == val { - return docTag.Text - } - } - } - } - return "" - default: - fmt.Printf("Unsupported attribute key: %s\n", key) - return "" - } -} - -func QueryEntities(graph *CodeGraph, query *queryparser.Query) []*GraphNode { - result := make([]*GraphNode, 0) - - for _, node := range graph.Nodes { - if node.Type == query.Entity { - ctx := GraphNodeContext{Node: node} // Create a context for each node - if query.Conditions.Evaluate(&ctx) { // Use the context in evaluation - result = append(result, node) - } - } - } - return result -} diff --git a/test-src/android/app/src/main/AndroidManifest.xml b/test-src/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..def7a2f --- /dev/null +++ b/test-src/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/test-src/android/app/src/main/java/com/ivb/udacity/adapter/movieGeneralAdapter.java b/test-src/android/app/src/main/java/com/ivb/udacity/adapter/movieGeneralAdapter.java new file mode 100644 index 0000000..0cbbaad --- /dev/null +++ b/test-src/android/app/src/main/java/com/ivb/udacity/adapter/movieGeneralAdapter.java @@ -0,0 +1,86 @@ +package com.ivb.udacity.adapter; + +import android.content.Context; +import android.content.Intent; +import android.support.v4.app.FragmentManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.ivb.udacity.R; +import com.ivb.udacity.modal.movieGeneralModal; +import com.ivb.udacity.movieDetailActivity; +import com.ivb.udacity.movieDetailFragment; +import com.squareup.picasso.Picasso; + +import java.util.List; + +/** + * Created by S.Shivasurya on 1/1/2016 - androidStudio. + */ +public class movieGeneralAdapter extends RecyclerView.Adapter { + private List mMovieGeneralModal; + private Context context; + private boolean mTwoPane; + private FragmentManager fm; + + public movieGeneralAdapter(Context context, List itemList, boolean mTwoPane, FragmentManager fm) { + this.mMovieGeneralModal = itemList; + this.context = context; + this.mTwoPane = mTwoPane; + this.fm = fm; + } + + @Override + public movieGeneralHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.movie_cards, null); + movieGeneralHolder rcv = new movieGeneralHolder(layoutView); + return rcv; + } + + @Override + public void onBindViewHolder(movieGeneralHolder holder, final int position) { + holder.movieName.setText(mMovieGeneralModal.get(position).getTitle()); + holder.movieAvg.setText(mMovieGeneralModal.get(position).getmVote()); + //picasso loading here + Picasso.with(context) + .load(mMovieGeneralModal.get(position).getThumbnail()) + .into(holder.moviePhoto); + if (position == 0 && mTwoPane) { + movieDetailFragment fragment = new movieDetailFragment(); + fragment.setMovieData(mMovieGeneralModal.get(0)); + fragment.setArgument(fm); + fm + .beginTransaction() + .replace(R.id.movie_detail_container, fragment) + .commit(); + } + holder.mView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (mTwoPane) { + movieDetailFragment fragment = new movieDetailFragment(); + fragment.setMovieData(mMovieGeneralModal.get(position)); + fragment.setArgument(fm); + fm + .beginTransaction() + .replace(R.id.movie_detail_container, fragment) + .commit(); + } else { + Context context = v.getContext(); + Intent intent = new Intent(context, movieDetailActivity.class); + intent.putExtra("DATA_MOVIE", mMovieGeneralModal.get(position)); + context.startActivity(intent); + } + } + }); + } + + @Override + public int getItemCount() { + return this.mMovieGeneralModal.size(); + } +} + + diff --git a/test-src/android/app/src/main/java/com/ivb/udacity/adapter/movieGeneralHolder.java b/test-src/android/app/src/main/java/com/ivb/udacity/adapter/movieGeneralHolder.java new file mode 100644 index 0000000..b2b2f32 --- /dev/null +++ b/test-src/android/app/src/main/java/com/ivb/udacity/adapter/movieGeneralHolder.java @@ -0,0 +1,34 @@ +package com.ivb.udacity.adapter; + +import android.support.v7.widget.RecyclerView; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; + +import com.ivb.udacity.R; + +/** + * Created by S.Shivasurya on 1/1/2016 - androidStudio. + */ +public class movieGeneralHolder extends RecyclerView.ViewHolder implements View.OnClickListener { + + public TextView movieName, movieAvg; + public ImageView moviePhoto; + public View mView; + + public movieGeneralHolder(View itemView) { + super(itemView); + itemView.setOnClickListener(this); + mView = itemView; + movieName = (TextView) itemView.findViewById(R.id.movieName); + movieAvg = (TextView) itemView.findViewById(R.id.vote); + moviePhoto = (ImageView) itemView.findViewById(R.id.moviePhoto); + } + + @Override + public void onClick(View view) { + Toast.makeText(view.getContext(), "Clicked Country Position = " + getPosition(), Toast.LENGTH_SHORT).show(); + } +} + diff --git a/test-src/android/app/src/main/java/com/ivb/udacity/constants/constant.java b/test-src/android/app/src/main/java/com/ivb/udacity/constants/constant.java new file mode 100644 index 0000000..d01356b --- /dev/null +++ b/test-src/android/app/src/main/java/com/ivb/udacity/constants/constant.java @@ -0,0 +1,8 @@ +package com.ivb.udacity.constants; + +/** + * Created by S.Shivasurya on 1/10/2016 - androidStudio. + */ +public class constant { + public final static String ACCESS_TOKEN = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; +} diff --git a/test-src/android/app/src/main/java/com/ivb/udacity/database/favouritesSqliteHelper.java b/test-src/android/app/src/main/java/com/ivb/udacity/database/favouritesSqliteHelper.java new file mode 100644 index 0000000..cf804e7 --- /dev/null +++ b/test-src/android/app/src/main/java/com/ivb/udacity/database/favouritesSqliteHelper.java @@ -0,0 +1,91 @@ +package com.ivb.udacity.database; + +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; + +import com.ivb.udacity.modal.movieGeneralModal; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by S.Shivasurya on 1/11/2016 - androidStudio. + */ +public class favouritesSqliteHelper extends SQLiteOpenHelper { + public static final String KEY_ROWID = "id"; + public static final String KEY_THUMBNAIL = "mThumbnail"; + public static final String KEY_MVOTE = "mVote"; + public static final String KEY_TITLE = "mTitle"; + public static final String KEY_PEOPLE = "mPeople"; + public static final String KEY_RELEASEDATE = "mReleaseDate"; + public static final String KEY_OVERVIEW = "mOverview"; + public static final String KEY_REVIEW = "mReview"; + public static final String SQLITE_TABLE = "movies"; + private static final String LOG_TAG = "moviesDB"; + private static final String DATABASE_CREATE = + "CREATE TABLE if not exists " + SQLITE_TABLE + " (" + + KEY_ROWID + " integer PRIMARY KEY," + + KEY_THUMBNAIL + "," + + KEY_TITLE + "," + + KEY_PEOPLE + "," + + KEY_MVOTE + "," + + KEY_OVERVIEW + "," + + KEY_REVIEW + "," + + KEY_RELEASEDATE + "" + + " );"; + + public favouritesSqliteHelper(Context context) { + super(context, LOG_TAG, null, 1); + } + + + @Override + public void onCreate(SQLiteDatabase db) { + db.execSQL(DATABASE_CREATE); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + db.execSQL("DROP TABLE IF EXISTS " + SQLITE_TABLE); + onCreate(db); + } + + public boolean insertMovie(movieGeneralModal movieGeneralModals) { + SQLiteDatabase db = this.getWritableDatabase(); + ContentValues values = new ContentValues(); + values.put(KEY_ROWID, Integer.parseInt(movieGeneralModals.getmId())); + values.put(KEY_THUMBNAIL, movieGeneralModals.getThumbnail()); + values.put(KEY_TITLE, movieGeneralModals.getTitle()); + values.put(KEY_PEOPLE, movieGeneralModals.getmPeople()); + values.put(KEY_MVOTE, movieGeneralModals.getmVote()); + values.put(KEY_OVERVIEW, movieGeneralModals.getmOverview()); + values.put(KEY_RELEASEDATE, movieGeneralModals.getmReleaseDate()); + values.put(KEY_REVIEW, movieGeneralModals.getmReview()); + + boolean createSuccessful = db.insert(SQLITE_TABLE, null, values) > 0; + db.close(); + return createSuccessful; + } + + public List getAllMovies() { + List movieList = new ArrayList<>(); + String selectQuery = "SELECT * FROM " + SQLITE_TABLE; + + SQLiteDatabase db = this.getReadableDatabase(); + Cursor cursor = db.rawQuery(selectQuery, null); + + if (cursor.moveToFirst()) { + do { + movieGeneralModal movie = new movieGeneralModal(cursor.getString(2), cursor.getString(1), cursor.getString(4), cursor.getString(0), cursor.getString(3), cursor.getString(7), cursor.getString(5)); + movieList.add(movie); + } while (cursor.moveToNext()); + } + cursor.close(); + + return movieList; + } + +} diff --git a/test-src/android/app/src/main/java/com/ivb/udacity/modal/Results.java b/test-src/android/app/src/main/java/com/ivb/udacity/modal/Results.java new file mode 100644 index 0000000..979760d --- /dev/null +++ b/test-src/android/app/src/main/java/com/ivb/udacity/modal/Results.java @@ -0,0 +1,153 @@ +package com.ivb.udacity.modal; + +import java.io.Serializable; + +/** + * Created by S.Shivasurya on 1/1/2016 - androidStudio. + */ +public class Results implements Serializable { + private String vote_average; + + private String backdrop_path; + + private String adult; + + private String id; + + private String title; + + private String overview; + + private String original_language; + + private String[] genre_ids; + + private String release_date; + + private String original_title; + + private String vote_count; + + private String poster_path; + + private String video; + + private String popularity; + + public String getVote_average() { + return vote_average; + } + + public void setVote_average(String vote_average) { + this.vote_average = vote_average; + } + + public String getBackdrop_path() { + return backdrop_path; + } + + public void setBackdrop_path(String backdrop_path) { + this.backdrop_path = backdrop_path; + } + + public String getAdult() { + return adult; + } + + public void setAdult(String adult) { + this.adult = adult; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getOverview() { + return overview; + } + + public void setOverview(String overview) { + this.overview = overview; + } + + public String getOriginal_language() { + return original_language; + } + + public void setOriginal_language(String original_language) { + this.original_language = original_language; + } + + public String[] getGenre_ids() { + return genre_ids; + } + + public void setGenre_ids(String[] genre_ids) { + this.genre_ids = genre_ids; + } + + public String getRelease_date() { + return release_date; + } + + public void setRelease_date(String release_date) { + this.release_date = release_date; + } + + public String getOriginal_title() { + return original_title; + } + + public void setOriginal_title(String original_title) { + this.original_title = original_title; + } + + public String getVote_count() { + return vote_count; + } + + public void setVote_count(String vote_count) { + this.vote_count = vote_count; + } + + public String getPoster_path() { + return poster_path; + } + + public void setPoster_path(String poster_path) { + this.poster_path = poster_path; + } + + public String getVideo() { + return video; + } + + public void setVideo(String video) { + this.video = video; + } + + public String getPopularity() { + return popularity; + } + + public void setPopularity(String popularity) { + this.popularity = popularity; + } + + @Override + public String toString() { + return "ClassPojo [vote_average = " + vote_average + ", backdrop_path = " + backdrop_path + ", adult = " + adult + ", id = " + id + ", title = " + title + ", overview = " + overview + ", original_language = " + original_language + ", genre_ids = " + genre_ids + ", release_date = " + release_date + ", original_title = " + original_title + ", vote_count = " + vote_count + ", poster_path = " + poster_path + ", video = " + video + ", popularity = " + popularity + "]"; + } +} diff --git a/test-src/android/app/src/main/java/com/ivb/udacity/modal/movieGeneral.java b/test-src/android/app/src/main/java/com/ivb/udacity/modal/movieGeneral.java new file mode 100644 index 0000000..2cf2bc6 --- /dev/null +++ b/test-src/android/app/src/main/java/com/ivb/udacity/modal/movieGeneral.java @@ -0,0 +1,53 @@ +package com.ivb.udacity.modal; + +import java.io.Serializable; + +/** + * Created by S.Shivasurya on 1/1/2016 - androidStudio. + */ +public class movieGeneral implements Serializable { + private Results[] results; + + private String page; + + private String total_pages; + + private String total_results; + + public Results[] getResults() { + return results; + } + + public void setResults(Results[] results) { + this.results = results; + } + + public String getPage() { + return page; + } + + public void setPage(String page) { + this.page = page; + } + + public String getTotal_pages() { + return total_pages; + } + + public void setTotal_pages(String total_pages) { + this.total_pages = total_pages; + } + + public String getTotal_results() { + return total_results; + } + + public void setTotal_results(String total_results) { + this.total_results = total_results; + } + + @Override + public String toString() { + return "ClassPojo [results = " + results + ", page = " + page + ", total_pages = " + total_pages + ", total_results = " + total_results + "]"; + } +} diff --git a/test-src/android/app/src/main/java/com/ivb/udacity/modal/movieGeneralModal.java b/test-src/android/app/src/main/java/com/ivb/udacity/modal/movieGeneralModal.java new file mode 100644 index 0000000..f5f9f59 --- /dev/null +++ b/test-src/android/app/src/main/java/com/ivb/udacity/modal/movieGeneralModal.java @@ -0,0 +1,63 @@ +package com.ivb.udacity.modal; + +import java.io.Serializable; + +/** + * Created by S.Shivasurya on 1/1/2016 - androidStudio. + */ +public class movieGeneralModal implements Serializable { + String mTitle; + String mThumbnail; + String mVote; + String mId; + String mPeople; + String mReleaseDate; + String mOverview; + String mReview; + + public movieGeneralModal(String mTitle, String mThumbnail, String mVote, String mId, String mPeople, String mReleaseDate, String mOverview) { + this.mThumbnail = mThumbnail; + this.mTitle = mTitle; + this.mVote = mVote; + this.mId = mId; + this.mPeople = mPeople; + this.mReleaseDate = mReleaseDate; + this.mOverview = mOverview; + } + + public String getmReview() { + return this.mReview; + } + + public void setmReview(String mReview) { + this.mReview = mReview; + } + + public String getmOverview() { + return this.mOverview; + } + + public String getmReleaseDate() { + return this.mReleaseDate; + } + + public String getTitle() { + return this.mTitle; + } + + public String getThumbnail() { + String url = "http://image.tmdb.org/t/p/w185/" + this.mThumbnail; + return url; + } + + public String getmId() { + return this.mId; + } + + public String getmPeople() { + return this.mPeople; + } + public String getmVote() { + return this.mVote; + } +} diff --git a/test-src/android/app/src/main/java/com/ivb/udacity/modal/review/Results.java b/test-src/android/app/src/main/java/com/ivb/udacity/modal/review/Results.java new file mode 100644 index 0000000..c459d90 --- /dev/null +++ b/test-src/android/app/src/main/java/com/ivb/udacity/modal/review/Results.java @@ -0,0 +1,51 @@ +package com.ivb.udacity.modal.review; + +/** + * Created by S.Shivasurya on 1/8/2016 - androidStudio. + */ +public class Results { + private String content; + + private String id; + + private String author; + + private String url; + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + @Override + public String toString() { + return "ClassPojo [content = " + content + ", id = " + id + ", author = " + author + ", url = " + url + "]"; + } +} diff --git a/test-src/android/app/src/main/java/com/ivb/udacity/modal/review/movieReview.java b/test-src/android/app/src/main/java/com/ivb/udacity/modal/review/movieReview.java new file mode 100644 index 0000000..2d825a1 --- /dev/null +++ b/test-src/android/app/src/main/java/com/ivb/udacity/modal/review/movieReview.java @@ -0,0 +1,61 @@ +package com.ivb.udacity.modal.review; + +/** + * Created by S.Shivasurya on 1/8/2016 - androidStudio. + */ +public class movieReview { + private String id; + + private Results[] results; + + private String page; + + private String total_pages; + + private String total_results; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public Results[] getResults() { + return results; + } + + public void setResults(Results[] results) { + this.results = results; + } + + public String getPage() { + return page; + } + + public void setPage(String page) { + this.page = page; + } + + public String getTotal_pages() { + return total_pages; + } + + public void setTotal_pages(String total_pages) { + this.total_pages = total_pages; + } + + public String getTotal_results() { + return total_results; + } + + public void setTotal_results(String total_results) { + this.total_results = total_results; + } + + @Override + public String toString() { + return "ClassPojo [id = " + id + ", results = " + results + ", page = " + page + ", total_pages = " + total_pages + ", total_results = " + total_results + "]"; + } +} diff --git a/test-src/android/app/src/main/java/com/ivb/udacity/modal/trailer/Results.java b/test-src/android/app/src/main/java/com/ivb/udacity/modal/trailer/Results.java new file mode 100644 index 0000000..7cbe8cf --- /dev/null +++ b/test-src/android/app/src/main/java/com/ivb/udacity/modal/trailer/Results.java @@ -0,0 +1,81 @@ +package com.ivb.udacity.modal.trailer; + +/** + * Created by S.Shivasurya on 1/10/2016 - androidStudio. + */ +public class Results { + private String site; + + private String id; + + private String iso_639_1; + + private String name; + + private String type; + + private String key; + + private String size; + + public String getSite() { + return site; + } + + public void setSite(String site) { + this.site = site; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getIso_639_1() { + return iso_639_1; + } + + public void setIso_639_1(String iso_639_1) { + this.iso_639_1 = iso_639_1; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getSize() { + return size; + } + + public void setSize(String size) { + this.size = size; + } + + @Override + public String toString() { + return "ClassPojo [site = " + site + ", id = " + id + ", iso_639_1 = " + iso_639_1 + ", name = " + name + ", type = " + type + ", key = " + key + ", size = " + size + "]"; + } +} diff --git a/test-src/android/app/src/main/java/com/ivb/udacity/modal/trailer/movieYoutubeModal.java b/test-src/android/app/src/main/java/com/ivb/udacity/modal/trailer/movieYoutubeModal.java new file mode 100644 index 0000000..10afebe --- /dev/null +++ b/test-src/android/app/src/main/java/com/ivb/udacity/modal/trailer/movieYoutubeModal.java @@ -0,0 +1,32 @@ +package com.ivb.udacity.modal.trailer; + +/** + * Created by S.Shivasurya on 1/10/2016 - androidStudio. + */ +public class movieYoutubeModal { + + private String id; + + private Results[] results; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public Results[] getResults() { + return results; + } + + public void setResults(Results[] results) { + this.results = results; + } + + @Override + public String toString() { + return "ClassPojo [id = " + id + ", results = " + results + "]"; + } +} diff --git a/test-src/android/app/src/main/java/com/ivb/udacity/movieDetailActivity.java b/test-src/android/app/src/main/java/com/ivb/udacity/movieDetailActivity.java new file mode 100644 index 0000000..d66686c --- /dev/null +++ b/test-src/android/app/src/main/java/com/ivb/udacity/movieDetailActivity.java @@ -0,0 +1,63 @@ +package com.ivb.udacity; + +import android.content.Intent; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.view.MenuItem; + +import com.ivb.udacity.modal.movieGeneralModal; + +/** + * An activity representing a single movie detail screen. This + * activity is only used narrow width devices. On tablet-size devices, + * item details are presented side-by-side with a list of items + * in a {@link movieListActivity}. + * @author shivasurya + * @author nirooba + * @version 1.0 + * @since 2016-02-25 + * @see movieListActivity + * @see movieDetailFragment + */ +public class movieDetailActivity extends AppCompatActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_movie_detail); + Intent intent = getIntent(); + + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + getSupportActionBar().setDisplayShowHomeEnabled(true); + + // webview.javascriptEnabled(); + webview.getSettings().setJavaScriptEnabled(false); + + movieGeneralModal moviegeneralModal = (movieGeneralModal) intent.getSerializableExtra("DATA_MOVIE"); + + if (savedInstanceState == null) { + + movieDetailFragment fragment = new movieDetailFragment(); + fragment.setMovieData(moviegeneralModal); + getSupportFragmentManager().beginTransaction() + .add(R.id.movie_detail_container, fragment) + .commit(); + } + } + + + @Override + public void onBackPressed() { + super.onBackPressed(); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + int id = item.getItemId(); + if (id == android.R.id.home) { + onBackPressed(); + return true; + } + return super.onOptionsItemSelected(item); + } +} \ No newline at end of file diff --git a/test-src/android/app/src/main/java/com/ivb/udacity/movieDetailFragment.java b/test-src/android/app/src/main/java/com/ivb/udacity/movieDetailFragment.java new file mode 100644 index 0000000..6f44496 --- /dev/null +++ b/test-src/android/app/src/main/java/com/ivb/udacity/movieDetailFragment.java @@ -0,0 +1,266 @@ +package com.ivb.udacity; + +import android.content.ActivityNotFoundException; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.design.widget.FloatingActionButton; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import com.ivb.udacity.constants.constant; +import com.ivb.udacity.database.favouritesSqliteHelper; +import com.ivb.udacity.modal.movieGeneralModal; +import com.ivb.udacity.modal.review.Results; +import com.ivb.udacity.modal.review.movieReview; +import com.ivb.udacity.modal.trailer.movieYoutubeModal; +import com.ivb.udacity.network.MovieAPI; +import com.ivb.udacity.network.NetworkAPI; +import com.squareup.picasso.Picasso; + +import retrofit.Callback; +import retrofit.RetrofitError; +import retrofit.client.Response; + +/** + * A fragment representing a single movie detail screen. + * This fragment is either contained in a {@link movieListActivity} + * in two-pane mode (on tablets) or a {@link movieDetailActivity} + * on handsets. + */ +public class movieDetailFragment extends Fragment { + + private FragmentManager fm; + private movieGeneralModal moviegeneralModal; + private TextView reviewText, titleText, voteText, peoplesText, calendarText, plotSynopsis; + private ImageView titleImage; + private LinearLayout youtubeViewHolder; + private TextView shareYoutube; + private String shareYoutubeID; + private FloatingActionButton fab; + + public movieDetailFragment() { + + } + + public void setArgument(FragmentManager fm) { + this.fm = fm; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setHasOptionsMenu(true); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View rootView = inflater.inflate(R.layout.movie_detail, container, false); + if (savedInstanceState != null) { + this.moviegeneralModal = (movieGeneralModal) savedInstanceState.getSerializable("DATA"); + } + updateGeneralUI(rootView); + return rootView; + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putSerializable("DATA", moviegeneralModal); + } + @Override + public void onActivityCreated(@Nullable Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + } + + public void setMovieData(movieGeneralModal moviegeneralModal) { + this.moviegeneralModal = moviegeneralModal; + } + + private void updateGeneralUI(View v) { + titleText = (TextView) v.findViewById(R.id.titleText); + voteText = (TextView) v.findViewById(R.id.rating); + calendarText = (TextView) v.findViewById(R.id.calendar); + peoplesText = (TextView) v.findViewById(R.id.people); + titleImage = (ImageView) v.findViewById(R.id.titleimg); + plotSynopsis = (TextView) v.findViewById(R.id.plotsynopsis); + reviewText = (TextView) v.findViewById(R.id.reviewText); + youtubeViewHolder = (LinearLayout) v.findViewById(R.id.youtubelayout); + shareYoutube = (TextView) v.findViewById(R.id.youtubesharer); + fab = (FloatingActionButton) v.findViewById(R.id.fab); + + titleText.setText(moviegeneralModal.getTitle()); + voteText.setText(moviegeneralModal.getmVote()); + peoplesText.setText(moviegeneralModal.getmPeople()); + calendarText.setText(moviegeneralModal.getmReleaseDate()); + plotSynopsis.setText(moviegeneralModal.getmOverview()); + getMovieReview(reviewText); + Picasso.with(getContext()) + .load(moviegeneralModal.getThumbnail()) + .into(titleImage); + getMovieReview(reviewText); + getTrailer(youtubeViewHolder); + shareYoutube.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (shareYoutubeID != null) { + shareYoutubeIntent(shareYoutubeID); + } else { + Toast.makeText(getContext(), "No Youtube Videos Available! Sorry", Toast.LENGTH_LONG).show(); + } + } + }); + fab.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + saveToDatabase(); + } + }); + } + + protected void saveToDatabase() { + favouritesSqliteHelper db = new favouritesSqliteHelper(getContext()); + if (!reviewText.getText().toString().contains("Sorry")) { + moviegeneralModal.setmReview(reviewText.getText().toString()); + } + boolean b = db.insertMovie(moviegeneralModal); + if (b) + Toast.makeText(getContext(), "Added to Favourites", Toast.LENGTH_LONG).show(); + else + Toast.makeText(getContext(), "Seems Already in Favourites!", Toast.LENGTH_LONG).show(); + } + protected void shareYoutubeIntent(String shareYoutubeID) { + String url = "http://www.youtube.com/watch?v" + shareYoutubeID; + String shareMsg = "hey,there new film named " + moviegeneralModal.getTitle() + " has been released and here is the Trailer link,Have a look at it " + url; + Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND); + sharingIntent.setType("text/plain"); + sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "Movies Now - Android App"); + sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, shareMsg); + startActivity(Intent.createChooser(sharingIntent, getResources().getString(R.string.share_using))); + } + + protected String generateYoutubeThumbnailURL(String id) { + String url = "http://img.youtube.com/vi/" + id + "/mqdefault.jpg"; + return url; + } + + public void watchYoutubeVideo(String id) { + try { + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("vnd.youtube:" + id)); + startActivity(intent); + } catch (ActivityNotFoundException ex) { + Intent intent = new Intent(Intent.ACTION_VIEW, + Uri.parse("http://www.youtube.com/watch?v=" + id)); + startActivity(intent); + } + } + + protected void getTrailer(final LinearLayout youtubeViewHolder) { + MovieAPI mMovieAPI = NetworkAPI.createService(MovieAPI.class); + mMovieAPI.fetchVideos(constant.ACCESS_TOKEN, this.moviegeneralModal.getmId(), new Callback() { + + @Override + public void success(movieYoutubeModal movieYoutubeModal, Response response) { + youtubeViewHolder.setPadding(5, 10, 5, 0); + com.ivb.udacity.modal.trailer.Results[] trailer = movieYoutubeModal.getResults(); + if (trailer.length > 0) { + shareYoutubeID = trailer[0].getKey(); + for (final com.ivb.udacity.modal.trailer.Results obj : trailer) { + String url = generateYoutubeThumbnailURL(obj.getKey()); + ImageView myImage = new ImageView(getContext()); + LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( + 180, + LinearLayout.LayoutParams.WRAP_CONTENT + ); + params.leftMargin = 3; + params.rightMargin = 3; + params.topMargin = 6; + params.bottomMargin = 3; + myImage.setLayoutParams(params); + Picasso.with(getContext()) + .load(url) + .into(myImage); + youtubeViewHolder.addView(myImage); + myImage.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + watchYoutubeVideo(obj.getKey()); + } + }); + + } + + } else { + youtubeViewHolder.setPadding(50, 50, 50, 50); + TextView errmsg = new TextView(getContext()); + LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.WRAP_CONTENT, + 30 + ); + errmsg.setLayoutParams(params); + errmsg.setText("That's Bad Luck,No Trailers Found!Check later"); + youtubeViewHolder.addView(errmsg); + } + } + + @Override + public void failure(RetrofitError error) { + youtubeViewHolder.setPadding(50, 50, 50, 50); + TextView errmsg = new TextView(getContext()); + LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.WRAP_CONTENT, + 30 + ); + errmsg.setLayoutParams(params); + errmsg.setText("Network Error! You can't view Trailers Rite Now"); + youtubeViewHolder.addView(errmsg); + + } + }); + } + + protected void getMovieReview(final View review) { + MovieAPI mMovieAPI = NetworkAPI.createService(MovieAPI.class); + mMovieAPI.fetchReview(constant.ACCESS_TOKEN, this.moviegeneralModal.getmId(), new Callback() { + + @Override + public void success(movieReview movieReview, Response response) { + Results[] movieResult = movieReview.getResults(); + if (movieResult.length > 0) + ((TextView) review).setText(movieResult[0].getContent()); + else + ((TextView) review).setText("Sorry No Review is Available Till Now!"); + + } + + @Override + public void failure(RetrofitError error) { + Log.d("error", error.toString()); + ((TextView) review).setText("Sorry! Check Back Latter! Network Error!"); + } + }); + } + + protected void generateThumbnail() { + + } + @Override + public void onDestroy() { + super.onDestroy(); + } + + @Override + public void onPause() { + super.onPause(); + } +} \ No newline at end of file diff --git a/test-src/android/app/src/main/java/com/ivb/udacity/movieListActivity.java b/test-src/android/app/src/main/java/com/ivb/udacity/movieListActivity.java new file mode 100644 index 0000000..fa6f9ad --- /dev/null +++ b/test-src/android/app/src/main/java/com/ivb/udacity/movieListActivity.java @@ -0,0 +1,239 @@ +package com.ivb.udacity; + +import android.content.DialogInterface; +import android.content.res.Configuration; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.FragmentManager; +import android.support.v7.app.AlertDialog; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.util.DisplayMetrics; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; + +import com.ivb.udacity.adapter.movieGeneralAdapter; +import com.ivb.udacity.constants.constant; +import com.ivb.udacity.database.favouritesSqliteHelper; +import com.ivb.udacity.modal.Results; +import com.ivb.udacity.modal.movieGeneral; +import com.ivb.udacity.modal.movieGeneralModal; +import com.ivb.udacity.network.MovieAPI; +import com.ivb.udacity.network.NetworkAPI; + +import java.util.ArrayList; +import java.util.List; + +import retrofit.Callback; +import retrofit.RetrofitError; +import retrofit.client.Response; + +/** + * An activity representing a list of movies. This activity + * has different presentations for handset and tablet-size devices. On + * handsets, the activity presents a list of items, which when touched, + * lead to a {@link movieDetailActivity} representing + * item details. On tablets, the activity presents the list of items and + * item details side-by-side using two vertical panes. + * @author shivasurya + * @version 1.0 + * @throws ClassCastException + */ + @Deprecated +public class movieListActivity extends AppCompatActivity { + final CharSequence[] items = {" Most Popular ", " Highest Rated ", " My Favourites "}; + private final String MOST_POPULAR = "popularity.desc"; + private final String HIGHLY_RATED = "vote_count.desc"; + View recyclerView; + private AlertDialog choice; + private String FLAG_CURRENT = MOST_POPULAR; + private String FLAG_FAV = "FAVOURITE"; + private TextView errorTextView; + private ImageView errorImageview; + /** + * Whether or not the activity is in two-pane mode, i.e. running on a tablet + * device. + */ + private boolean mTwoPane; + private movieGeneral mMoviegeneralData; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_movie_list); + + + recyclerView = findViewById(R.id.movie_list); + errorImageview = (ImageView) findViewById(R.id.errimg); + errorTextView = (TextView) findViewById(R.id.errtext); + + assert recyclerView != null; + + if (findViewById(R.id.movie_detail_container) != null) { + mTwoPane = true; + } + if (savedInstanceState == null) + FetchMovie((RecyclerView) recyclerView, FLAG_CURRENT); + else { + if (savedInstanceState.getString("CURRENT") == FLAG_FAV) { + FetchMovie((RecyclerView) recyclerView, FLAG_FAV); + } else if (savedInstanceState.getSerializable("adapter") != null) { + mMoviegeneralData = (movieGeneral) savedInstanceState.getSerializable("adapter"); + drawLayout((RecyclerView) recyclerView, mMoviegeneralData); + } else { + FetchMovie((RecyclerView) recyclerView, FLAG_CURRENT); + } + } + + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.main, menu); + return true; + } + + @Deprecated + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.mapMenu: + showChoices(); + break; + } + return true; + } + + @Deprecated + private void showChoices() { + + choice = new AlertDialog.Builder(this) + .setSingleChoiceItems(items, -1, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int item) { + switch (item) { + case 0: + FetchMovie((RecyclerView) recyclerView, MOST_POPULAR); + break; + case 1: + FetchMovie((RecyclerView) recyclerView, HIGHLY_RATED); + break; + case 2: + FetchMovie((RecyclerView) recyclerView, FLAG_FAV); + break; + } + choice.dismiss(); + } + }).setTitle("Choose") + .show(); + } + + protected void FetchFavourites(@NonNull final RecyclerView recyclerView) { + favouritesSqliteHelper db = new favouritesSqliteHelper(getApplicationContext()); + List movieGeneralModals = db.getAllMovies(); + if (movieGeneralModals.size() > 0) + attachAdapter(recyclerView, movieGeneralModals); + else { + Toast.makeText(getApplicationContext(), "It seems No Favourites! check back Later", Toast.LENGTH_LONG).show(); + } + } + /** + * Fetch movie data from themoviedb.org + * @param recyclerView + * @param flag + */ + protected void getPaneChanges() throws ClassCastException { + mTwoPane = findViewById(R.id.movie_detail_container) != null; + } + + + @Override + protected void onDestroy() { + super.onDestroy(); + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + + super.onConfigurationChanged(newConfig); + getPaneChanges(); + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putSerializable("adapter", mMoviegeneralData); + outState.putString("CURRENT", FLAG_CURRENT); + + } + + private void attachAdapter(@NonNull final RecyclerView recyclerView, List movieGeneralModals) { + DisplayMetrics displaymetrics = new DisplayMetrics(); + getWindowManager().getDefaultDisplay().getMetrics(displaymetrics); + int width = displaymetrics.widthPixels; + int number; + if (!mTwoPane) { + number = width / 170; + } else { + number = (width / 2) / 170; + } + GridLayoutManager lLayout = new GridLayoutManager(getApplicationContext(), number); + RecyclerView rView = recyclerView; + rView.setHasFixedSize(true); + rView.setLayoutManager(lLayout); + FragmentManager fm = getSupportFragmentManager(); + movieGeneralAdapter mMovieGeneralAdapter = new movieGeneralAdapter(getApplicationContext(), movieGeneralModals, mTwoPane, fm); + rView.setAdapter(mMovieGeneralAdapter); + + } + + private void drawLayout(@NonNull final RecyclerView recyclerView, movieGeneral mMoviegeneral) { + List movieGeneralModals = new ArrayList(); + Results[] mResult = mMoviegeneral.getResults(); + for (Results result : mResult) { + movieGeneralModal obj = new movieGeneralModal(result.getTitle(), result.getPoster_path(), result.getVote_average() + , result.getId(), result.getVote_count(), result.getRelease_date(), result.getOverview()); + movieGeneralModals.add(obj); + } + if (mResult.length > 0) { + attachAdapter(recyclerView, movieGeneralModals); + } else { + errorImageview.setVisibility(View.VISIBLE); + errorTextView.setVisibility(View.VISIBLE); + } + } + + private void FetchMovie(@NonNull final RecyclerView recyclerView, String temp) { + + errorImageview.setVisibility(View.INVISIBLE); + errorTextView.setVisibility(View.INVISIBLE); + errorTextView.setText("Sorry!Network Error! check back Later"); + + FLAG_CURRENT = temp; + if (FLAG_CURRENT != FLAG_FAV) { + MovieAPI mMovieAPI = NetworkAPI.createService(MovieAPI.class); + mMovieAPI.fetchMovies(FLAG_CURRENT, constant.ACCESS_TOKEN, "en", new Callback() { + @Override + public void success(movieGeneral mMoviegeneral, Response response) { + mMoviegeneralData = mMoviegeneral; + drawLayout(recyclerView, mMoviegeneral); + } + + @Override + public void failure(RetrofitError error) { + errorImageview.setVisibility(View.VISIBLE); + errorTextView.setVisibility(View.VISIBLE); + } + }); + } else { + FetchFavourites(recyclerView); + } + } + + +} diff --git a/test-src/android/app/src/main/java/com/ivb/udacity/network/MovieAPI.java b/test-src/android/app/src/main/java/com/ivb/udacity/network/MovieAPI.java new file mode 100644 index 0000000..e990073 --- /dev/null +++ b/test-src/android/app/src/main/java/com/ivb/udacity/network/MovieAPI.java @@ -0,0 +1,40 @@ +package com.ivb.udacity.network; + +import com.ivb.udacity.modal.movieGeneral; +import com.ivb.udacity.modal.review.movieReview; +import com.ivb.udacity.modal.trailer.movieYoutubeModal; + +import retrofit.Callback; +import retrofit.http.GET; +import retrofit.http.Path; +import retrofit.http.Query; + +/** + * Created by S.Shivasurya on 1/1/2016 - androidStudio. + */ +public interface MovieAPI { + + //this method is to fetch the ALL movies with specific sort + @GET("/3/discover/movie") + void fetchMovies( + @Query("sort_by") String mSort, + @Query("api_key") String mApiKey, + @Query("language") String lang, + Callback cb + ); + + @GET("/3/movie/{id}/reviews") + void fetchReview( + @Query("api_key") String mApiKey, + @Path("id") String id, + Callback cb + ); + + @GET("/3/movie/{id}/videos") + void fetchVideos( + @Query("api_key") String mApiKey, + @Path("id") String id, + Callback cb + ); + +} diff --git a/test-src/android/app/src/main/java/com/ivb/udacity/network/NetworkAPI.java b/test-src/android/app/src/main/java/com/ivb/udacity/network/NetworkAPI.java new file mode 100644 index 0000000..2a6cf2a --- /dev/null +++ b/test-src/android/app/src/main/java/com/ivb/udacity/network/NetworkAPI.java @@ -0,0 +1,22 @@ +package com.ivb.udacity.network; + +import com.squareup.okhttp.OkHttpClient; + +import retrofit.RestAdapter; +import retrofit.client.OkClient; + +/** + * Created by S.Shivasurya on 1/1/2016 - androidStudio. + */ +public class NetworkAPI { + public static final String API_BASE_URL = "http://api.themoviedb.org"; + + private static RestAdapter.Builder builder = new RestAdapter.Builder() + .setEndpoint(API_BASE_URL) + .setClient(new OkClient(new OkHttpClient())); + + public static S createService(Class serviceClass) { + RestAdapter adapter = builder.build(); + return adapter.create(serviceClass); + } +} diff --git a/test-src/android/app/src/main/res/drawable/calendar.png b/test-src/android/app/src/main/res/drawable/calendar.png new file mode 100644 index 0000000000000000000000000000000000000000..0689efaba46ee93bd3e8c3b428144b39707e2098 GIT binary patch literal 304 zcmeAS@N?(olHy`uVBq!ia0vp^{2|t!nPGov`!=dBuv`2#b&!^A#q}dsLp0?cn%i-tuKCrEy!~J1df!a-=T@0SC KelF{r5}E)UlvOVP literal 0 HcmV?d00001 diff --git a/test-src/android/app/src/main/res/drawable/groups.png b/test-src/android/app/src/main/res/drawable/groups.png new file mode 100644 index 0000000000000000000000000000000000000000..0ff2a7a1acb8775c524851eb7126c9b3f7201fb6 GIT binary patch literal 416 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 literal 0 HcmV?d00001 diff --git a/test-src/android/app/src/main/res/drawable/menu_main.png b/test-src/android/app/src/main/res/drawable/menu_main.png new file mode 100644 index 0000000000000000000000000000000000000000..1c292d3cc53550171669a28a1fab01d2b5aeb94b GIT binary patch literal 385 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY1|&n@Zgyv2VD#{GaSW-5dppaK?~nlx%SYvh z6F+z;_cer+Z!PpXT;O*n&FG$%VBy2ctD|FUJ@ru zA~zr{?X|S2ct3|`*ph?m%h>}qHZw3?kYCyK!tPY{i-Y)!cKG}ey+2+4t#umq!nX$K4Pk(mr-|x+- z&3886c(b^vo5O)uH|=jFWAiH6nKd_-9F1YR+Gcj$zP8eGiU0njLPmx~M_p3w+L8s> j5+}GbG~3jr;AQzU?eOrddyygs3|aWl$WzvhLy@0>N!@cXxLUwm8AvWpNJ)5S-xd4q4m@!9B3J`v!LjdUMXJdiCD_ z+g;P$Gd(q5*Hm}SRQ21^+ZN!xvb>T!01gfSfcwXQw^hJr01^TsIywgWe+dokKkA=E zMMM8*qM`niX#eDU3{*4{G*mP!N-Pp`av%_hjzK{Qq@X0D08+pqAt9lnpkkw;VUywG z;u8}Rk`WT(uv;T+Qegbe%0Znj{2yoN@cpNwc9Jsdu z0NKA7k>LIl>i;Ep1Vkic6gbp>UfuTqcsK+EI7Ac#R0Iq(R0IGVJOTg_2ML#o3;BbT zCJG+4xqDa=cOisETFWE6Z{`9&xq+5PMqAgyGZngh$tP#&OUVZ4gmf?nD7Y5h$#OjCOCK;gnxjDQkvA}AKa6W!V3QZ z;c;vI1GQ+F-M)NV0bnBhI}!&02Ot4>7>i*nfd5|{DEy0^NO-!5=yAw?m1UFsu%zn> zW(Ow*8lgYJ+V0R3cAuqiZTy3k;4Li+^L-s?H-UyZ27&!t^K~UxjH%>hc@3BGcTXz= zXG!9N+M76PhFB4VzR|m=E$@ny1gmG}<3`gt<@}NX;5_07_2C%dwi6cG6Y?ngwslDs zZ!lyXi3%MVfi_RU_}Kyda6D~9l#5&=Ql2o`7JR=ZxZVb%FgQ-|R&1U#@N7d_pUXoP zH;bX%UF(ePijMD7KNAj^lxFVcnjWe@S=Uz_hXTd(_>_o_57dlkwW?70&!#C`k-NiJ z15PzH#!oo9=364In|**yn{FkgF5iyM7#`no3QYz2@frBog>E6-@&$x=HsRzsq#5T& z?^Gt8D@O6(Qz{YRwOJYm7!Zr{1-Qpzc3Wn3t6LInZ9d!4>?+vF8|akCqmGN$I( z4`=1p7J?UlusgaNTDiH0y7jMBll35k%@B~G=Xi2N*sj{R-I&{$@9{$Gp-ZBCMcWo; zKF`&$CVi5BB6H?3#rojx$lk-!&=B>dmbgugo@#7tq-$k$)J?xPwVX3fnysMXZ>))+ zG$1X6l6%(=vc~{=hB!;i616*X4xlYK1klI^cPLMGO7hl z(v0E3pDWDoHDj|H#sj%OG_pHkr&6w3R=pfFIq6)WN}%8A6A}wnSEkr_c52{BXq#4i z8`KY+H07(x=SY=mZ^XA6X~3X0C4S6O0OyaEs=3C*%Nb*vC`9@~4q|>l6TK^yN4_^z zlYAMWXr^Lb)(XIRlS>Pwg508r&h`Hm+%fs78j1jP~ zEoVKwM>r!c+sC&qkV_6m#Cgz#DCiuf<}?j_PUMF}sTKT}l41^OZFdU4vU)_#LMSnz z#<+3c7FG)hb{T_3b&g3J@kG*3t>-n8sDkPfo~pzeUR5o}iq~3yRG(Yku0Au9LP_tC zn}umSG@``LO)R%f-1 zUo|gK#>a}*6t=JtglH-s0;-19Lrbhzza(z?U5`ElNW`hmdiC5we%k_ew}*s%bqgaI ztM}gk7JQv0w#lOja$=$=8u3h)YAJo{!N{HYRyTqcaSaGuWP8}_YMb^mu+MnQW=i@K zJ`4)D!m{NQqZhBh>0d?DwzRf_)|7jkBQzu7ER8K$?Nc-Pp%wmRX*HZWIL6OVXnT(s zw?lkD`B9l1Gi=q=^HFBt*2tG&|~u>I+m7i?q`}=5p`$pm`4#C}g z8x4|1mcq_)p%Z=J3Q4r%p@og~O_r$%kPTuAB+|7yq4p)PP$owD}Ue|b(RN6Q)C>!1< zt5JRj9{7q1AY=SFJ@LCEP;>mEu)$%o*Wr2aaJG`vRb{0%?pj~P9KEDLD$^pCkt*9| z&dGOA;P>3SF-Kvs1TR-A0X=rfB-D45h+BI>sn5O@6j4s;-JMA-Ut3$aW$S;kd+^)` z-G+CzrUVd+Rg!<>BHNE1h3z;zboh22p3Vi`gSBey`3-Y(e0&z+M-jm%PwBC&_F*Xr z?>q-hz((@33=MN2`N`9)#^?t5?NjH~saft4GhI-MHOGxP!P0rT&j&?)rg+{FW^Cgv zxNE-f&kY2CRFq{mG`LVP?2JiaqW!d;QbX{gA2T$$WQalVU(Epx{V%V4|1g0P4?4V; zW?Mi)mKIjlnmdlR*30uN@nV9x}R64#NDN-cG?FJkFOK! ze#&_-SW_lRDd+rr(X$#(qJ+1Q$a&3+ed?>CSNY?rClAmo-b`pg}%-g2TN;t8T zDvIO?uT?GFk@|aq$xiXmRF)Cd0kj%H9*xH5vs~KW5(s|TizzuHGW(kYN@?H(7>VZF z)(hQt!N*6#nqdL9+6&16Gv~)+1l?3BDWi6%DK@L<#t^k*&{Wv4{VfRf z2a;)H*DB^sIFU;pH(f%94{xjE6jThzT!v5q2)_Yb7nS9bs+njuRMN1pq)>SGagIoS zqH-2!Gwxohfnwu`1$Uww>bNhwhx^%Ol|9Uldl>xFj|PBwLp;S&s#aFRuSJ7zK%a!% zA3j!5qh$WK>&Nb{zD)Tpvp3Dp=s7b4_Vz zUWyZ6)|lsW<4+lUZ+}SBPAGMH`tXj1BZq!>I&|33%fm4xq=T49du>sFM1kxeH=j?2 z!5)X3fcO(R5vG-2g14XZirXFnX_-2A{{x9l;AO1CWUeSF*pym}!))XY5XmDp9=TDS zm+MRRbj(uic;5R#UDq@I4DtHH_V}uf-zg@5rXVeMR611E~jorus2dzUpTqM;2 zmRf4*>iq6pHur^E}p>s?6;@s14%R@28i<1O+JB*n&hpl&5( zl*e@nVV>y!gKBeY4JtWxqB2S@J2(ukAiMpS*43q z3$%+;zgatd7z;}lBG#PJ=OC5h5z-i{~crWUB#oU*2zl! zo%_dA=XEgE}oSGeUFj(Botczwm+1kD6 z?&Ojh6Wf-ajJ4N&V@LZ7GHT+FAjYpbCCKOtlL?D=_@YLwFv50TF2Ho9#T73$limFF z>W}D}Zds!Ro=x>T+0n<{CtaVqdVpVea7LNAa!CcZKo$GMdQsda*F%hldtBR zXwVO_-6!e%4vogA5YJ|+VN2OOSZ_ve{X?yt2yL;a?Wo2~Rg%IFiCOHEtj?34cL_%k zH|9p1PA8MuzD=OJntDi6Q1aFrK!2V($I~$TSn}oQuM)ku`n;Bx55=RNcDzBx1Rfb29k zKZr@r25U=GXA znAEldsk!rhEMH0el>qk7KiYe)*7Xv%1U>OvA&msBDE{`GkL->y_%$3qu8pgLgltK&Sl)0 z)|s@dTI{FzbAXZ*`k=B0%%GG>mjDEUV}*|%va=Q9X3l`Eo8A0eb0;>6mEhAh1ARuz zL_(49p1_N};F;QK>n%rXD~X&57z(pG_*_eH2p-C*0JU4Y88xKZ{Bw=lx3|Kd8JLNfDTEU2Q{BNMDFt$WB*>#QB7w24NBX$)>C+5FfJB(VwPj z26l@~)UgOt!Ltn%*fE?)YVMCUNndQsJB0P!+buzQ&0i++f{Ii=?5J5ZqfH2?FChys z)+ii^P<}KTc@LN#>rk(Hwj66ex5MM%M!1XM?Ruy*Jq*!L?4{!ypZh+%7bls^x(lRw z(Edo4pP>Ae1%Ns-jaS|)M>KM%N$g_wo#}%KvKlW*)vAv1)!f&G4|$HNMjsf{IM^Ln z*Ss&QrVqd4QyiOsXhuL8^aGXTGps|@8!1*9V2Lbf?=^+A7CatO5Zxed4~^T zpA`?AN&y;v!NOYATDIxZ2wuCWo6Qs4Gco{Vj+H*D7JITz+;=&x5$<5G= z1^z;Z9;vXR6CqkA!1Qu60)B4;phP{Q*H*imREIK z?6B@prn!;(%w!?Yjm;VDuyA9J6Jd(j{H^!-@EalP|m`%^RK!kp2)c04^YIk)?1;=gx#!!5C@B~&+55*R7sNXMg6#x~A03c@tNyGuyc49k z3A?_ZPtB{sZmv16Jh6@~Ie}1?t;FC9L9r}<*G&}yv8U^zK z6CuTK6beheoPb2(_wsJyCOlX8lqR$>nqezz@6m|=#><(gvCYg3vuV&GEkQg9dl#r29&8nx)doEw;c6SIPQXd% zBxgxo9An!IvHqLul1oR@AUAHCvTI!4H~Zq5?2{+h`&jG?^0=*c<1;O7~#p2tnkTm>Fr&~fU&*!Wl#(v*vhmj`P50z*XXP`7{ z&+{DLA&AUjbFWtW#iSzSN9~yY?ix%?bpk@+HRBF5Z2SWQy#Z()@{f++0C&9o{sIf4 zym8vYudY3B086!a<6ybAk+Dv6yR7-%;vmOMOsd`t&MALEj(w7Ty3OkL8a&_b+km(~Ul9 z9tB-Z?M*gXGqrOcj56`ni3&0aeG$Ww4wx@S(Ueopha=?$(tst~g4f z)IHSSPlm?dKy~&z=ug=k+t5ZtsdPtJh^!ZdscukkXgqU~hX6obBGSte>(2-b@+;|w z6b0E_ikH&p-Yox9eZd%2?~pWvFR7zZ88 z`Q8R70fsQ_tmcFGCK*4%EB+6Hxe+83X~^I~@cTp!Otsj&Xyvp9xn zU^F%0{A5M7{P~0iC2JMeb+@(|!{E9gvWFAB{Phc!J($+lO6M+*P8TQC{Vsp-;Q{92 zIsL1^^plI2zm@ml_EQzvdJ37(k2NEub6Pgqf^C5xEEM9g1Kkd4}CU?*Om8*03{EAPb3f<3>PGYh^R{B#tg{*%e^m5CgwNyO2u*;8YO#H8& zYnjg;_z5rgijxd^l4fh0y5VKbW)+DP`absB-|d-4k7_1*CNN(eQH_Y%pOaH_DypYf z3vIzA#4~S*RFYv$aP4siU;nIfB*G)xt^ZYn7;2`Me@vI9RownnS@y5wYS{4gq*;Jb zi6A&lTsN9sR41<_pmEZxT8!X8RtZr#oxhi0K>EeM&4B)U$X!fmg;`uCD-zvrto_KBsZ&Q znhr$}PohYROU=NHT~J(CN2u}eQKgHuFM&$+3;%E+gqB+|s&$d8DMKYni6+5GPyHrh zsl6Q9ZSzOL*{@6{5}fw#>*1RwlZIX6&pH9P>iQKo~OL8G^yqP;SG?+yZN~GDUJ)4{CU5z)X_D+ z7ovw`j}`I^fBo!|{@QhN|5|9ozU17}(%Xhj+O=Rv@Qp0(x?j|K7wY7~Cw}JWWA(jS zzYmTw>1D1z&oS*ir`T>5^ifJ|vL)SuE2B2Z-;F0+ic}-9Q;ydIdelNw_ zoY5owdzJh&qNdH#WfYF>rZ0?w%k};2QcVDS4-w z78RCA*eOrE&=kk-(?4p`jN~o-6|7l-<;%am&2bLWxcsSfyO@3hcrdw73JJBo>Nz?r zJDZ+DLzt);5a<2a&!8lxwg0kaHsrbWvL?YYfOm0d_o)cO?v#=ccie+L6P|CfwyLT& zw`;aBvu@{NNC4MSm-oc0+uQ_Q)W=^-F_v?b`VF9hqJ=F@gmYChZGMX-y|%7m*4bj1 z;*%W^P(o0&GnbaelCjQ@5$5D$8IA}2p6y2#QW?@B!JVXwmwygcn|~s^``x|YeOtS- zGK%_r1xudEd7|_wnk&c_&U*6$)_4wi`;eU1xx7hfzIJ17UBwrnJwHH8mesvi41`u_P4>`ib~0&bHr&%xH+VpcFiT!n*C-=L! zn*1cgsrwPIB1Cy3ZtNQ`91y8(AU7@$4JUQA-uLX_Hvj8Duz19{GBFVYXD_hYn65Bz zq)9dFHhRiGB45I1Div>8^Z~dN5-A<=5wxF9wv`MwB>a*UvQR+&4(-MKsq09bnZvP9 z7&H*&*@tL*pm9;Lvid5m!Fu|5pYe29=oRY6;QRS z4#~3oE4co}y^~1w;mP^r!Rwv`3YLMe?sK@nM{y%+a*nGj3VH~$nxIa9`f3up#rRPW zqb(4bmK;UBH^_@n!^ein8^15>$4N(7z#{tyr}RZ<%ib2u6Z0}pm}KFQ05VhssnDgv zrl3t4r>Frx%&DZbNNd2v0WaRGDNkC!Qud8qJFGq3>@8BnAk=bcmIfRqrK@q`ox4o2 zu{XeiR_{veyxKwDz#jUH|5&wErBfLi!pW%%&)MB1)w#|~YKfAc!1k#;$Pu@=jEP{z zb6R=UcsP~eQ2R8l<4`-TwMD?R7m>wn{k*0ISIV0=QZj=9clB3x%Py|qkrZ*h3~_bP zejvI!16FGW`v`tR{sqU z-h7zD# z&4ngrZhhRHdt=Q-!{7^-C-rL7;zB>nE}k=-euVbS*c>ukG@bw@W^U^5d1Ui<&e@ z6Zm>6G7r?AQ9_zZBfzXj6A-CN#`C~h4;5m*(|K(f476S*HXYlD<`Yqg9@{!fTf`lu zLXSBOz-v^V7{;lf%N{YCCoJ0N`($_o65#nJ+Zw)2o2GHdM)iw2r_ouZVYqP1541YF zk&fqP@U)n3TjG@&R9#?8>ISAFv#Fm8%DoH{TzAkNJgHyzdmW_7S3ieb zo!feu-kq(?Zl|rg(1-J9Da6slGg;~SbqNMNK7ch};vsSv`ITOF$n{Yr;tZSySot#f=Xqs4@8E&f76MPrz?O9A^Jh5vC zzHo6vn0{c7%AJz!Gz6!Mh&ehJ*>M}KEVHIa5!Raw{BDMtq;^lJ>wUB*;UQs3TB|^^ z6x(KNvY8Hd@F7T>A8dwo)b&Fq`8qi74a>d|KXo%-7Gtgw-^%G(t%1{Ye^42@yknNH zU7~OEJ>xBQae{q8(-LYH<6~#r=c;HA*KJE<5?~t}LvSWGJ$aZ9DXN=RsBlOFrHqpC z&rXmW*<0bzf)gXeR*6X?UG-ulMMtG}O&FT8f>X-DF$-QQN;jl?O`UdZ2LTyW;ZA)a zxXSRIyq;_WF`VxR-XS}DE1iA8^?5C4;wVlO%{F?$4zMri{^cP*k2dOIA>hXf+iMa*sfSf-IH)n4k%aV=`*1_1#{S*q{d*0n zRIDcLGcEMgccc*}EYNh@rXb;Uq>_bJpVnGO%sAKNG+VW>6sDajNH zK7^K_*dJeI8uN&2jXDIFCxM zX1od38nEN{9CWsGDamv9b_?h=kR#Mab$?kP!z%pX>eY{!J09=Fp62s0ZPBPY#OPC{ z-kerTr@?qP`JD?)O-)@_KU2UGR zqHGnf5+}_speRzJ5I);bi@i zr4uM$cB(jf|0-s`4pM`vN=+S>&}j{i_&`#p_ z&@jdf6xIDiJ9Vljy=l9q21MVRg!Ku@Ua{ZYN$S)NEdysHrr zswT5&6#4LP??G)+Es{mIoUZ>+ikvxQ4v&Pfg7&T^fW?8Xqa`lgL-Z2m6YmBFZ2bpG zZ7oN!T_d>um01XQpl9~FxehW;d=R;Vc-4|1(!iycONGT^y0M4_FlZhOgc#@~JnP~& zzbBxjVBc>%(D-_?HG3;R)_#RX`4Z82Z_()yK<|Oa)Ff0f+OGK(Hr#jR-KTkLBhe_! z{!Sr+YgpAnSF2YVRK%L8K*2epACTHz6!PdHF`Eor{<)Q4yB&)^-ABRm1_00X5C^MR zB{mGLE-MR%OYNOasA6ZGIXy=TF3Kuu_AKD{T~c-A2|r2Bk%Dp2EJe|Z8OF(XQUm?o z_n%iiaAamJ7>KXR{~q7pkoO4`&XlNfu=UEi5-Inl(WV=6s5@uNv83IyvSPe+Ek7$& z5(Ff>p@_c$C{cQ8u`|l(GLj;O8#uGq=_-zo+J~_VI$hsVlEr6BM2{0yDOs#;^*!tfy7gU+*3rtk6~{BbBt(r?$=vNv^=oG1N@6x*0|C zd=j=IrU-oR!M2gU8oW%Oew21;Xt1t&7wzuOHriPW z7nw1rVRimkHC}rJuNRoCHH$_vw7%r~?oLflqN=<QuI)L?=3HW1siTO~lw)rwY) z+Gttc_fGP&bZ?{17bPJH?NZnDX8*u@|NONmH&Y4tyW?4}(28sYsJwK~qKPgBZJ3F^ z%^N^OnL9BsX8u#D7{4F~-I-rl1~1lJbJL}qx5dCM?Xt0?I9IcMw?qjcnr(m`O7&`{ zSE8Pa$TzY2vayG~PJ;<;iD#C;Kb^7%$I3rC_Vd=1$|lx=stpkDT->Ly@(O8bUdwMm zWLY^LE_G0~`_mAO0jFX;AY%ON=8Aq<-nUYHb*TNqBDb1{Hx11=qsQL8z({BSO(>FN zM7V)!Dh?n!L54R>s8x&F43p(#c`mv>PLvGkn1 z4zW$ZJ@4B2SK;n6(Lsy@x)T5D)yo^;A}+hAXSxN4j@dpPHJ&&gp`N)x0ndz8$6Dq1&7q9bvx%`IA!U){-a zw8G*US{g{iNKeJ@;2!$y=BTHUrkPxKwBm9+EE*i*p3P4*iu8TN@R3v5@}`~g@L#^n&%FU|(JO8m%MbQ%i98mB zYZ{Gzz5#Yhe9qaO_FqV&_R`HMXgb|be(*Klc(0UX4H(Jb=je3=YKaWp89Md!Iz;ZL zZPT{5`eCiv8DygMDUM^}Q6<$G;w_wBt!34Vnz%ND`pGO(^|rq7vM;e0BA3uX8d@EV z6zgcRRu@y}rz*>g-UmFj<9r|VX5OWsF3=x~{nxMggq~6j&fD3h4b8wM4zH=kO3QVb zWmdr(sbytB_k`7LqIBJ^y3x29dJw}Wx zxZSC!(>V(f8x!BM2R}A&B&>f_+c3^^(+8G%dD>_dwLy3vNIoanrS~I~%KKyXcwRp{ z+!>5r=U*@eht4rkY}Ub9F4h~$y)0RIbi*S7zXA=lvoz~B-IERTk*u75P8-{bTjgZw z^e6b@^|@lRql|SYOH1M>=+aoD83?|BfXbO4y#MMt-ikk_+cSLnV$YSfpS6@r2o@;MPj+>8qIvzqq0SQ4?`y69klWed zejZnceaqZ(q?Swo%;fGpQ35uJdlWp*9rq9=&CCH;j4ku20YD_)q0iKECHu-L^TtD) z&3(h2-I}-M3!JJ^@;YN=aCcw*PF+6vriW~ZI^aYd@xMCe0m;JpKTsxw|B!!NqlFZcb%&w+4TmZkD~(!q zNDGtQNCu)1J+P469c*DH3TjC+KEs68)^1=DpsF&b-1boygRki@pgS!R#r9dnD4WNf zTw%jKn^&Cv$~gIK+%#e(t0UAeZa(}ef;;j-Pv9n@m@fBazRP&ECU?Kl7W||%Z`&C7 zaIm1C4KsXdJx4{L!V9+BgwPcWQ0}$j+7`ZIwlNH4m^V=qiYAG*M{-9SgDt& zBF)2z7KrBXVx19)Hv-jEW;>-kNm;{15YyyXC13k}S6l;KyqOG|Mr)`j{;^~AT}*(ZMUoF|!z6~N4*{5PdxI~B zX6JRoqz2c%yYSH&rb)Bt!VoJh%R;I|RwiO1q1JFtC!0#m_5yVLpen7w34oFBS~QsV zrAn2Wq(1pHf0C#yq+@8Sn*)0qb%YHLH4+r!p|LGi^Vi&4J$B)a(k98UB+g>EbB(}A zk5Xo0!}a+@2!>1%=P0pu`LnG2B>(;C8jl$6Kusj3#kA~=(yLZcXV?&0-8J+8d+H{a z65LKj%DouvySgJ>x=1H;R|hUuL-7dWyP4D(YZFmUdhT7o&ARO6o>ISUze#K7N!}WP z?;^b?6mWO5=Jgr{d8Vt@IT=iy|B{Mn?%eE{?HFyIy2dIT!Co4I+LY5nu(4~!i0ktC z2`j-WLAz@s~$__$3$nvYu7MJA_jAd!N@xHb|vg zKxK~MY!_u&fN;TMVx$TiaSKk1_B3)6$s8KxlJUD!)bnB}ds?~o;>@%hKSbaW_lgdp zx5B=z;qBxsW;(XAeh}}YBBEb#P8&_9xE!;0(KsSuH@7MCzQLsVn(5X=d}GHbQxFv~ z4cd>02my@JUeUsd2J~;Cp}VZChs(&7Rcc9L6@tCqOZ6d=i$vt3e_dgpSznh;8f7H7 zqF}A}P@5MNC2Fi z%4e!sXDXvixB(Ov>4zy66)jV@lH6L+6qabpg>Gkd9ny_nmdwb7ogE42eb<5eulk76 zSvel?Ri<6P+H2&BcODOp>sBej0PQgZ-DA<9E%tqKL%4_JFhiLi{wFyjZIiz0y@nK% zcA<$H&n95w)WTX1uym5GQ_jl`b8=XnFrI6F&!H+NKbnKiOQFw-Z#4(j?X;IadE}p$ zx2-~6*s*&x*|#QWiYzw$8w@KCT<7}RE&e^J*4Xne2v)y*vE}Pk zb;S6Pd_|%cQRt6zTC{Xb;=F${)snWT#JaE3j#{<*Io8Fco2B%w8j74LVe=)0;<8e% z^v~U~8%?6mtkGuEJ!m$$ZJA^snFWTjU`;{xyl*-uB(U~9Sv>M2q|DLxgg3xwJoAiT ztiS2wy1|$$BDa#aBU?`jTJqXgowHKk)=DJAxNsJ^)m~K+wbQg#XXIkBl8!H>SObVg zN30D-ZveSJEy=|-9yLy#r|g7IVGkcA*CRf$EH)FU0YS&&SvNZEkbKq7o<=qPajlsc zUTzu_{Wx}=nSETzfrh#g#Ed|Gn>F{AqC<+zn_W;sdD&8Hcb-*NGby6<`-X=^iR5w?#CSFWN5GKGvSLWaBr@s3Dh8hh=y5 z#1113CL8l^7kP`c$R3~WWr*e7RG0TJ*Z(=JbFt}kG_hE|fw*?8*f*mUCXYQjMjKi1 z(tn_iL~5i2gylTH$RRG@E;@_x*%RuuPCM6ZER#!5ZLm0lSXBO&&KhFWJsu#&@9cIf zmc`1Jw=Wf}4xe1jtJoeIDV}xmGtAlMHU&u=RhKwAOR~-mvp0G=`mOs6%_-XE&6&|( zZt{O}*y;IH6pmegldoZj*4@|@m#?btO-T32t^y*uh$KIvoYTknpi*AkT|)>SXKS@F}dIdURa$>p|>z60hU#``D55L|?x z1`=+%Z;&B1oSO87F5CY&yrS*ClCw!NUQs-$t5Fp1LrnU_JR^z04HUlMDw&Z)!qfa; J9l*Ec{{aPMXsQ4J literal 0 HcmV?d00001 diff --git a/test-src/android/app/src/main/res/drawable/review.png b/test-src/android/app/src/main/res/drawable/review.png new file mode 100644 index 0000000000000000000000000000000000000000..610450e9a0c426043548463bf52d29945279315d GIT binary patch literal 479 zcmeAS@N?(olHy`uVBq!ia0vp^LLkh+3?vf;>QaH!t^l79S0Jq-CN>mN=lRtafv&eL z3GxeOU}R!tW9Q=L6A%&>5tWdXl9o|XH83-`uyb_w^!5vlj!jC-$Sy9g@9tZ)bk+K; zyAB+^e(S-@*B?KB{rOkxaPD!SLDM~5977}|Sr4)+#V|5B9Q^4O#(Ob(L&v75L$4~o z@1G{gpv=IaSI)>Fvz3*>AdibdVwovFLz}0mb@6xM18-`-zSvON(3<(xvgn@PgX7Ux zc_-g{-mrYtz3+Xig*Qb0UA?M`A^q#FsL-!G>t22T5Ey#5>2lP^*HwR>ufD~ey_JLS xRVv$zExgly?dOxw``0vgxhR91w8XT={A^uGxm{CUwgH{U;OXk;vd$@?2>?FGg$4is literal 0 HcmV?d00001 diff --git a/test-src/android/app/src/main/res/layout-w900dp/movie_list.xml b/test-src/android/app/src/main/res/layout-w900dp/movie_list.xml new file mode 100644 index 0000000..e75247a --- /dev/null +++ b/test-src/android/app/src/main/res/layout-w900dp/movie_list.xml @@ -0,0 +1,36 @@ + + + + + + + + + diff --git a/test-src/android/app/src/main/res/layout/activity_movie_detail.xml b/test-src/android/app/src/main/res/layout/activity_movie_detail.xml new file mode 100644 index 0000000..5f2a628 --- /dev/null +++ b/test-src/android/app/src/main/res/layout/activity_movie_detail.xml @@ -0,0 +1,14 @@ + + + + + + + diff --git a/test-src/android/app/src/main/res/layout/activity_movie_list.xml b/test-src/android/app/src/main/res/layout/activity_movie_list.xml new file mode 100644 index 0000000..c61138b --- /dev/null +++ b/test-src/android/app/src/main/res/layout/activity_movie_list.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + diff --git a/test-src/android/app/src/main/res/layout/movie_cards.xml b/test-src/android/app/src/main/res/layout/movie_cards.xml new file mode 100644 index 0000000..ff82ec9 --- /dev/null +++ b/test-src/android/app/src/main/res/layout/movie_cards.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + diff --git a/test-src/android/app/src/main/res/layout/movie_detail.xml b/test-src/android/app/src/main/res/layout/movie_detail.xml new file mode 100644 index 0000000..f8419a8 --- /dev/null +++ b/test-src/android/app/src/main/res/layout/movie_detail.xml @@ -0,0 +1,252 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test-src/android/app/src/main/res/layout/movie_list.xml b/test-src/android/app/src/main/res/layout/movie_list.xml new file mode 100644 index 0000000..8380bd1 --- /dev/null +++ b/test-src/android/app/src/main/res/layout/movie_list.xml @@ -0,0 +1,10 @@ + + diff --git a/test-src/android/app/src/main/res/menu/detail.xml b/test-src/android/app/src/main/res/menu/detail.xml new file mode 100644 index 0000000..79d72f9 --- /dev/null +++ b/test-src/android/app/src/main/res/menu/detail.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/test-src/android/app/src/main/res/menu/main.xml b/test-src/android/app/src/main/res/menu/main.xml new file mode 100644 index 0000000..aadee93 --- /dev/null +++ b/test-src/android/app/src/main/res/menu/main.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/test-src/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/test-src/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..c6bcfb324391fd6e970ebaf83af2848a7e7c01ec GIT binary patch literal 550 zcmV+>0@?kEP) z9AA($n=s9PNO~<9Z${E$@-&}t@==G1whoHwb;5@OPz~4s1VCYWgh3Nyko$hi?6GKk zcRP0T&9HYnzO}jCnE6qW#n634W@pLMJnariv^!{bC|Zz4Vo2;euG3MB)lrn}(#+qA z)4aAMEsdY3gYSGc({;&`V_x!|;(t^-M{VXil_evs+3&|;`%nGTbuc}fjR4N8p>0?}d+5<_B0EULsrny>Cj zH(I4+d~>uQo$;I-xduSgVvPv%>t+}PgR*51O?$SU*%zZ&6(6(w#AptZ*W@YynmT~Q z5j?8-5o`Z^{3UGtnvXTL7`0d!8(|O(%9lZWP{%>?fHcp}Dm$y}tVZ2gMPf({i3Lk6 oYzg*1toaA3n)e7m02C(mFDq{7XADRC8UO$Q07*qoM6N<$g5yT=_W%F@ literal 0 HcmV?d00001 diff --git a/test-src/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/test-src/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..e9be8d236e168e106af67710b0cdaff3eab5812e GIT binary patch literal 366 zcmV-!0g?WRP)8gd~)h40mt=VxwfwqbRyd)q3;7t=*na&rEM^JwxK3 zCGJ1|Gk|la>G#aoqP*Jlvumerb8L>0fmIMhyXsM zB^byj?6HKf1ALm@XI>h(`QXE3KizI_Gq=ku*LOnz4N(s$+~hHcCgzPR5F!9Y78wkN zfz+Egl=x-kgpj=#vgAvMnH{>b%oNgjK_Eo{MDip@2?qQK*gEG$4M1Ju8L$U%xX1D~ zU{%p=H2EnM0fZ9YGEn3u7R?$GhG2lSEIJ+mh!XiV48cI?KV4Cac;uum9_jazKnX{uv+xv`- z%+dib=DfJLfi-)<1_9RW4XjdMib}YoH!yEGrl>n}&i}uKdp|C%{rUdP?|nNxpY5Hq zgrz@(Nwu_ujh{tDpNU05VWz{U4&aA7y z-acNsPk!A!+nDpx-&5<0VzTCJf3~g6I<_KF|Bnlci^77fU)W@pGqW8ib`gBAz+wR# z6E>!sIMbpdwO2k}d9Xn+@H_j4sGu!(T#kIc^Jra*~IaoV9II*2e;>(Wr_!ylm3JPjeqR^+>)84!s1k@fWqR>EP@XnYJ@vB z^qdoRX=q;@!^&u6*wV<^>tG=i3%?NbW>NqLTsy@*|UE?=U!WU zP2>_wfpgk2HpaE8zs`QtTgQ5lv7}+cw{$@(kbO!A4hODlVvwAx-oe1{zSB#bNvWwf z;+dU8T-{vO%VtS)3#a(A!|f7fIq|~A5u2lYgb(~>c*lOidq;P+V+jM$pC4{ttkHIQ z#dMEZC1;-iQ;p72FOCTtemcc+JScabY~S|l+T$JCOJlnv%+2n<5qyxW8S2!~a#q}_ zp?_%zC!>&AJO`uQv>;U$j~g`$Z5aRLy_kN~gz?S<&wHH842+++E5*ehzhJOx;CnF7 zV1CmQy$7}qhn{gO9ylJf>dSLhk95}+o(T{CPstB^#3{rGGDMN(M}*f@0fofRtpXt1 belfhdBr>;Nd}Adry)t;Z`njxgN@xNAY#}ic literal 0 HcmV?d00001 diff --git a/test-src/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/test-src/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..128a7b32b20a9e864e45b66904e9317dd899f062 GIT binary patch literal 1316 zcmeAS@N?(olHy`uVBq!ia0vp^6F``Q4M;wBd$farf#tQQi(^Pd+}pX1e3u;rSRS6M z{=xA68S|cYYmaG4imL5_H_v>@=>D9x{BCHRwNl6W_&>?a=2AbZ9&fI@!nRLig3z5T zhsM0C&)Y>k*z-&mIBb9Q`7qZK=Iv4e3!=aNOk};(7|nY}?8W!~_w^o4`S$e-ZslUEGU3;pQBV_8$#eU}7=XT#s7k(A$#q46S<&x3*A*a z{{Apx)lzz)w@Mwyx{Q!`|5*SUvlOjf4j`#xMKacCear+?fP%~HugFHd&9b3w1aKA zeRRdPZ~wPP16_0P$9c<)0@hzT`fpo{0v7x)@3?boCR6Bwq_O8+TPN{A|3ecFLyHO;Ad*y{WTq0a)-a4$eoU}}q<50d12AYVG{oqu$Yk-EIFJDj?TGP2tYC*q9mfc+OSEr-bfRcv)f`G-) zG_=HF_x@w;pRDz+-4cFb5ws8(uVi}-IV7@K7ae^0KF;aq-lMPHwVtbH{eJ&g`%Kry zOVZuvf)^MR#uaJ=uxc?abrsz%AHU4OmF2FhXmYRqYoOZCf@bSZJ!cTnu$}qRhBaux zYDQKr(Z*wo9BdoAdM_{Py4|lIyg;ex-J-6I$EKHlcY6Ml&tzSf{>52ie!nfdgbd_`8SGWe82u9pziq5sA?uzcdai?q8cJ+rbTdVX${HnW94Gq ztU8S;S5b6UaHG?~oX({V(H^bOLKXxVL?>xp5DQvpi9>nuS_c!0zjwVg_CxZ@`Un4R z|1j7L4O$!OQ{QWFS%#>+O5Zp=aoJXPc+`}vnQ5A;((soUiZ!h#wi;tZ?!fszDc@NJ%vNU zfphj^T1y`2Wc=Zo@-p&pa&6ySU_3K_=znsy zqHy0g$vWXbTaWzv{2myrISc`=nRyJVIq`0EOoup=`e&w$Iw8*3DbMPJA`g9gpOM7y zMqwQ=Y##u__UC7#37|}K?m93ZXaD~Eg$}#}jf_9c4?VCBp7q + + + diff --git a/test-src/android/app/src/main/res/values-w820dp/dimens.xml b/test-src/android/app/src/main/res/values-w820dp/dimens.xml new file mode 100644 index 0000000..63fc816 --- /dev/null +++ b/test-src/android/app/src/main/res/values-w820dp/dimens.xml @@ -0,0 +1,6 @@ + + + 64dp + diff --git a/test-src/android/app/src/main/res/values/colors.xml b/test-src/android/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..acab235 --- /dev/null +++ b/test-src/android/app/src/main/res/values/colors.xml @@ -0,0 +1,18 @@ + + + #FF5722 + #E64A19 + #795548 + #212121 + #212121 + #B6B6B6 + #F44336 + #BA68C8 + #F50057 + #42A5F5 + #26A69A + #00C853 + #455A64 + #fff + #e7e7e7 + diff --git a/test-src/android/app/src/main/res/values/dimens.xml b/test-src/android/app/src/main/res/values/dimens.xml new file mode 100644 index 0000000..5909abf --- /dev/null +++ b/test-src/android/app/src/main/res/values/dimens.xml @@ -0,0 +1,9 @@ + + + 3dp + 3dp + 16dp + 16dp + 200dp + 200dp + diff --git a/test-src/android/app/src/main/res/values/strings.xml b/test-src/android/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..0761510 --- /dev/null +++ b/test-src/android/app/src/main/res/values/strings.xml @@ -0,0 +1,20 @@ + + Movies Now + My NanoDegree Apps + Spotify Streamer + Scores App + Library App + Build It Bigger + XYZ Reader + CAPSTONE:My Own App + sort + MovieDetailActivity + Share using + Movies Now + Movie + Bad Luck!Network Error + Trailer + SHARE + Plot Synopsis + Review + diff --git a/test-src/android/app/src/main/res/values/styles.xml b/test-src/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..35e20e4 --- /dev/null +++ b/test-src/android/app/src/main/res/values/styles.xml @@ -0,0 +1,27 @@ + + + + + + + + +