blob: 80d4a124bafb04282250dc9d1439e98a2619a8d2 [file] [log] [blame]
Joachim Bingelc8a28e42014-04-24 15:06:42 +00001package de.ids_mannheim.korap.query.serialize;
2
3import java.lang.reflect.Method;
4import java.util.ArrayList;
5import java.util.HashMap;
6import java.util.LinkedHashMap;
7import java.util.LinkedList;
8import java.util.List;
9import java.util.Map;
10import java.util.regex.Matcher;
11import java.util.regex.Pattern;
12
13import org.antlr.v4.runtime.ANTLRInputStream;
14import org.antlr.v4.runtime.BailErrorStrategy;
15import org.antlr.v4.runtime.CharStream;
16import org.antlr.v4.runtime.CommonTokenStream;
17import org.antlr.v4.runtime.Lexer;
18import org.antlr.v4.runtime.Parser;
19import org.antlr.v4.runtime.ParserRuleContext;
20import org.antlr.v4.runtime.tree.ParseTree;
21
22import de.ids_mannheim.korap.query.annis.AqlLexer;
23import de.ids_mannheim.korap.query.annis.AqlParser;
24import de.ids_mannheim.korap.query.serialize.AbstractSyntaxTree;
25import de.ids_mannheim.korap.util.QueryException;
26
27/**
28 * Map representation of syntax tree as returned by ANTLR
29 * @author joachim
30 *
31 */
32public class TreeTemplate extends Antlr4AbstractSyntaxTree {
33 /**
34 * Top-level map representing the whole request.
35 */
36 LinkedHashMap<String,Object> requestMap = new LinkedHashMap<String,Object>();
37 /**
38 * Keeps track of open node categories
39 */
40 LinkedList<String> openNodeCats = new LinkedList<String>();
41 /**
42 * Flag that indicates whether token fields or meta fields are currently being processed
43 */
44 boolean inMeta = false;
45 /**
46 * Parser object deriving the ANTLR parse tree.
47 */
48 static Parser qlParser;
49 /**
50 * Keeps track of all visited nodes in a tree
51 */
52 List<ParseTree> visited = new ArrayList<ParseTree>();
53 /**
54 * Keeps track of active object.
55 */
56 LinkedList<LinkedHashMap<String,Object>> objectStack = new LinkedList<LinkedHashMap<String,Object>>();
57 /**
58 * Marks the currently active token in order to know where to add flags (might already have been taken away from token stack).
59 */
60 LinkedHashMap<String,Object> curToken = new LinkedHashMap<String,Object>();
61
62 private LinkedList<ArrayList<ArrayList<Object>>> distributedOperandsLists = new LinkedList<ArrayList<ArrayList<Object>>>();
63
64 /**
65 * Keeps track of how many objects there are to pop after every recursion of {@link #processNode(ParseTree)}
66 */
67 LinkedList<Integer> objectsToPop = new LinkedList<Integer>();
68 Integer stackedObjects = 0;
69 public static boolean verbose = false;
70
71 /**
72 *
73 * @param tree The syntax tree as returned by ANTLR
74 * @param parser The ANTLR parser instance that generated the parse tree
75 */
76 public TreeTemplate(String query) {
77// prepareContext();
78 requestMap.put("@context", "http://ids-mannheim.de/ns/KorAP/json-ld/v0.1/context.jsonld");
79 try {
80 process(query);
81 } catch (QueryException e) {
82 e.printStackTrace();
83 }
84 System.out.println(">>> "+requestMap.get("query")+" <<<");
85 }
86
87 private void prepareContext() {
88 LinkedHashMap<String,Object> context = new LinkedHashMap<String,Object>();
89 LinkedHashMap<String,Object> operands = new LinkedHashMap<String,Object>();
90 LinkedHashMap<String,Object> relation = new LinkedHashMap<String,Object>();
91 LinkedHashMap<String,Object> classMap = new LinkedHashMap<String,Object>();
92
93 operands.put("@id", "korap:operands");
94 operands.put("@container", "@list");
95
96 relation.put("@id", "korap:relation");
97 relation.put("@type", "korap:relation#types");
98
99 classMap.put("@id", "korap:class");
100 classMap.put("@type", "xsd:integer");
101
102 context.put("korap", "http://korap.ids-mannheim.de/ns/query");
103 context.put("@language", "de");
104 context.put("operands", operands);
105 context.put("relation", relation);
106 context.put("class", classMap);
107 context.put("query", "korap:query");
108 context.put("filter", "korap:filter");
109 context.put("meta", "korap:meta");
110
111 requestMap.put("@context", context);
112 }
113
114 @Override
115 public Map<String, Object> getRequestMap() {
116 return requestMap;
117 }
118
119 @Override
120 public void process(String query) throws QueryException {
121 ParseTree tree = parseAnnisQuery(query);
122 System.out.println("Processing Annis QL");
123 processNode(tree);
124 }
125
126 private void processNode(ParseTree node) {
127 // Top-down processing
128 if (visited.contains(node)) return;
129 else visited.add(node);
130
131 String nodeCat = getNodeCat(node);
132 openNodeCats.push(nodeCat);
133
134 stackedObjects = 0;
135
136 if (verbose) {
137 System.err.println(" "+objectStack);
138 System.out.println(openNodeCats);
139 }
140
141 /*
142 ****************************************************************
143 ****************************************************************
144 * Processing individual node categories *
145 ****************************************************************
146 ****************************************************************
147 */
148
149 objectsToPop.push(stackedObjects);
150
151 /*
152 ****************************************************************
153 ****************************************************************
154 * recursion until 'request' node (root of tree) is processed *
155 ****************************************************************
156 ****************************************************************
157 */
158 for (int i=0; i<node.getChildCount(); i++) {
159 ParseTree child = node.getChild(i);
160 processNode(child);
161 }
162
163
164 /*
165 **************************************************************
166 * Stuff that happens after processing the children of a node *
167 **************************************************************
168 */
169
170
171 for (int i=0; i<objectsToPop.pop(); i++) {
172 objectStack.pop();
173 }
174
175
176 openNodeCats.pop();
177
178 }
179
Joachim Bingelc8a28e42014-04-24 15:06:42 +0000180 @SuppressWarnings("unused")
181 private void putIntoSuperObject(LinkedHashMap<String, Object> object) {
182 putIntoSuperObject(object, 0);
183 }
184
185 @SuppressWarnings({ "unchecked" })
186 private void putIntoSuperObject(LinkedHashMap<String, Object> object, int objStackPosition) {
187 if (distributedOperandsLists.size()>0) {
188 ArrayList<ArrayList<Object>> distributedOperands = distributedOperandsLists.pop();
189 for (ArrayList<Object> operands : distributedOperands) {
190 operands.add(object);
191 }
192 } else if (objectStack.size()>objStackPosition) {
193 ArrayList<Object> topObjectOperands = (ArrayList<Object>) objectStack.get(objStackPosition).get("operands");
194 topObjectOperands.add(0, object);
195
196 } else {
197 requestMap.put("query", object);
198 }
199 }
200
201 private static ParserRuleContext parseAnnisQuery (String p) throws QueryException {
202 Lexer poliqarpLexer = new AqlLexer((CharStream)null);
203 ParserRuleContext tree = null;
204 // Like p. 111
205 try {
206
207 // Tokenize input data
208 ANTLRInputStream input = new ANTLRInputStream(p);
209 poliqarpLexer.setInputStream(input);
210 CommonTokenStream tokens = new CommonTokenStream(poliqarpLexer);
211 qlParser = new AqlParser(tokens);
212
213 // Don't throw out erroneous stuff
214 qlParser.setErrorHandler(new BailErrorStrategy());
215 qlParser.removeErrorListeners();
216
217 // Get starting rule from parser
218 Method startRule = AqlParser.class.getMethod("start");
219 tree = (ParserRuleContext) startRule.invoke(qlParser, (Object[])null);
220 }
221
222 // Some things went wrong ...
223 catch (Exception e) {
224 System.err.println( e.getMessage() );
225 }
226
227 if (tree == null) {
228 throw new QueryException("Could not parse query. Make sure it is correct QL syntax.");
229 }
230
231 // Return the generated tree
232 return tree;
233 }
234
235 public static void main(String[] args) {
236 /*
237 * For testing
238 */
239 String[] queries = new String[] {
240 };
241 TreeTemplate.verbose=true;
242 for (String q : queries) {
243 try {
244 System.out.println(q);
245 System.out.println(TreeTemplate.parseAnnisQuery(q).toStringTree(TreeTemplate.qlParser));
246 @SuppressWarnings("unused")
247 TreeTemplate at = new TreeTemplate(q);
248// System.out.println(TreeTemplate.parseAnnisQuery(q).toStringTree(TreeTemplate.aqlParser));
249 System.out.println();
250
251 } catch (NullPointerException | QueryException npe) {
252 npe.printStackTrace();
253 }
254 }
255 }
256
257}