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 0000000..0689efa
Binary files /dev/null and b/test-src/android/app/src/main/res/drawable/calendar.png differ
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 0000000..0ff2a7a
Binary files /dev/null and b/test-src/android/app/src/main/res/drawable/groups.png differ
diff --git a/test-src/android/app/src/main/res/drawable/ic_action.png b/test-src/android/app/src/main/res/drawable/ic_action.png
new file mode 100644
index 0000000..ad1d965
Binary files /dev/null and b/test-src/android/app/src/main/res/drawable/ic_action.png differ
diff --git a/test-src/android/app/src/main/res/drawable/ic_launcher.png b/test-src/android/app/src/main/res/drawable/ic_launcher.png
new file mode 100644
index 0000000..d1c0044
Binary files /dev/null and b/test-src/android/app/src/main/res/drawable/ic_launcher.png differ
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 0000000..1c292d3
Binary files /dev/null and b/test-src/android/app/src/main/res/drawable/menu_main.png differ
diff --git a/test-src/android/app/src/main/res/drawable/mqdefault.jpg b/test-src/android/app/src/main/res/drawable/mqdefault.jpg
new file mode 100644
index 0000000..2a47387
Binary files /dev/null and b/test-src/android/app/src/main/res/drawable/mqdefault.jpg differ
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 0000000..610450e
Binary files /dev/null and b/test-src/android/app/src/main/res/drawable/review.png differ
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 0000000..c6bcfb3
Binary files /dev/null and b/test-src/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
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 0000000..e9be8d2
Binary files /dev/null and b/test-src/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/test-src/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/test-src/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..74688b3
Binary files /dev/null and b/test-src/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
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 0000000..128a7b3
Binary files /dev/null and b/test-src/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/test-src/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/test-src/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..5bbbce3
Binary files /dev/null and b/test-src/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/test-src/android/app/src/main/res/values-v21/styles.xml b/test-src/android/app/src/main/res/values-v21/styles.xml
new file mode 100644
index 0000000..dbbdd40
--- /dev/null
+++ b/test-src/android/app/src/main/res/values-v21/styles.xml
@@ -0,0 +1,9 @@
+
+
+
+
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 @@
+
+
+
+
+
+
+
+
+
+
+
+
+