blob: a5c6969282ce2ee5c2aa069488270cc3c91fc037 [file] [log] [blame]
Joachim Bingel5c93f902013-11-19 14:49:04 +00001package de.ids_mannheim.korap.query.serialize;
2
3import java.util.ArrayList;
Joachim Bingeld5161a12014-01-08 11:15:49 +00004import java.util.Arrays;
Joachim Bingel5c93f902013-11-19 14:49:04 +00005import java.util.LinkedHashMap;
6import java.util.LinkedList;
7import java.util.List;
8import java.util.Map;
Joachim Bingel81812632014-02-18 08:55:22 +00009import java.util.regex.Matcher;
10import java.util.regex.Pattern;
Joachim Bingel5c93f902013-11-19 14:49:04 +000011
12import org.antlr.runtime.ANTLRStringStream;
13import org.antlr.runtime.RecognitionException;
14import org.antlr.runtime.tree.Tree;
Joachim Bingelb5f7bf02014-01-07 16:36:54 +000015import org.antlr.v4.runtime.tree.ParseTree;
16import org.slf4j.Logger;
17import org.slf4j.LoggerFactory;
Joachim Bingel5c93f902013-11-19 14:49:04 +000018
19import de.ids_mannheim.korap.query.cosmas2.c2psLexer;
20import de.ids_mannheim.korap.query.cosmas2.c2psParser;
Joachim Bingele98d0882014-01-21 12:58:54 +000021import de.ids_mannheim.korap.query.serialize.util.CosmasCondition;
Joachim Bingel87480d02014-01-17 14:07:46 +000022import de.ids_mannheim.korap.util.QueryException;
Joachim Bingel5c93f902013-11-19 14:49:04 +000023
24/**
25 * Map representation of CosmasII syntax tree as returned by ANTLR
26 * @author joachim
27 *
28 */
Joachim Bingelc8a28e42014-04-24 15:06:42 +000029public class CosmasTree extends Antlr3AbstractSyntaxTree {
Joachim Bingel5c93f902013-11-19 14:49:04 +000030
Michael Hanl10d21502014-02-07 20:09:58 +000031 private static Logger log = LoggerFactory.getLogger(CosmasTree.class);
Joachim Bingelb5f7bf02014-01-07 16:36:54 +000032
Joachim Bingel5c93f902013-11-19 14:49:04 +000033 /*
34 * Following collections have the following functions:
35 * - the request is a map with two keys (meta/query): {meta=[], query=[]}
36 * - the query is a list of token group maps: {meta=[], query=[tg1=[], tg2=[]]}
37 * - each token group is a list of tokens: {meta=[], query=[tg1=[t1_1, t1_2], tg2=[t2_1, t2_2, t2_3]]}
38 * - each token corresponds to a single 'fields' linked list {meta=[], query=[tg1=[t1_1=[], t1_2=[]], ... ]}
39 * - each fields list contains a logical operator and 'field maps' defining attributes and values
40 * {meta=[], query=[tg1=[t1_1=[[disj, {base=foo}, {base=bar}]], t1_2=[]], ... ]}
41 */
42 String query;
43 LinkedHashMap<String,Object> requestMap = new LinkedHashMap<String,Object>();
Joachim Bingelb5f7bf02014-01-07 16:36:54 +000044 /**
45 * Keeps track of active object.
46 */
47 LinkedList<LinkedHashMap<String,Object>> objectStack = new LinkedList<LinkedHashMap<String,Object>>();
48 /**
Joachim Bingel5c93f902013-11-19 14:49:04 +000049 * Makes it possible to store several distantTokenGroups
50 */
51 LinkedList<ArrayList<List<Object>>> distantTokensStack = new LinkedList<ArrayList<List<Object>>>();
52 /**
53 * Field for repetition query (Kleene + or * operations, or min/max queries: {2,4}
54 */
55 String repetition = "";
Joachim Bingel5c93f902013-11-19 14:49:04 +000056 /**
57 * Keeps track of open node categories
58 */
59 LinkedList<String> openNodeCats = new LinkedList<String>();
60 /**
61 * Global control structure for fieldGroups, keeps track of open fieldGroups.
62 */
63 LinkedList<ArrayList<Object>> openFieldGroups = new LinkedList<ArrayList<Object>>();
64 /**
Joachim Bingelb5f7bf02014-01-07 16:36:54 +000065 * Keeps track of how many objects there are to pop after every recursion of {@link #processNode(ParseTree)}
Joachim Bingel5c93f902013-11-19 14:49:04 +000066 */
Joachim Bingelb5f7bf02014-01-07 16:36:54 +000067 LinkedList<Integer> objectsToPop = new LinkedList<Integer>();
Joachim Bingel5c93f902013-11-19 14:49:04 +000068 /**
69 * Flag that indicates whether token fields or meta fields are currently being processed
70 */
71 boolean inMeta = false;
Joachim Bingel402c6e12014-05-08 17:09:06 +000072 /**
73 *
74 */
75 int classRefCounter = 1;
Joachim Bingel5c93f902013-11-19 14:49:04 +000076 boolean negate = false;
77
78 Tree cosmasTree;
79
80 LinkedHashMap<String,Object> treeMap = new LinkedHashMap<String,Object>();
81 /**
82 * Keeps track of all visited nodes in a tree
83 */
84 List<Tree> visited = new ArrayList<Tree>();
Joachim Bingelb5f7bf02014-01-07 16:36:54 +000085
86 Integer stackedObjects = 0;
87
88 private static boolean debug = false;
Joachim Bingeld5161a12014-01-08 11:15:49 +000089 /**
90 * A list of node categories that can be sequenced (i.e. which can be in a sequence with any number of other nodes in this list)
91 */
Joachim Bingel81812632014-02-18 08:55:22 +000092 private final List<String> sequentiableCats = Arrays.asList(new String[] {"OPWF", "OPLEM", "OPMORPH", "OPBEG", "OPEND", "OPIN", "OPBED"});
Joachim Bingeld5161a12014-01-08 11:15:49 +000093 /**
94 * Keeps track of sequenced nodes, i.e. nodes that implicitly govern a sequence, as in (C2PQ (OPWF der) (OPWF Mann)).
95 * This is necessary in order to know when to take the sequence off the object stack, as the sequence is introduced by the
96 * first child but cannot be closed after this first child in order not to lose its siblings
97 */
98 private LinkedList<Tree> sequencedNodes = new LinkedList<Tree>();
Joachim Bingeleecc7652014-01-11 17:21:07 +000099
100 private boolean hasSequentiableSiblings;
101
Joachim Bingeleecc7652014-01-11 17:21:07 +0000102 /**
103 * Keeps track of operands lists that are to be serialised in an inverted
104 * order (e.g. the IN() operator) compared to their AST representation.
105 */
Joachim Bingelcc1dc242014-01-15 09:32:38 +0000106 private LinkedList<ArrayList<Object>> invertedOperandsLists = new LinkedList<ArrayList<Object>>();
Joachim Bingele98d0882014-01-21 12:58:54 +0000107
108 private LinkedList<ArrayList<ArrayList<Object>>> distributedOperandsLists = new LinkedList<ArrayList<ArrayList<Object>>>();
Joachim Bingel5c93f902013-11-19 14:49:04 +0000109 /**
110 *
111 * @param tree The syntax tree as returned by ANTLR
112 * @param parser The ANTLR parser instance that generated the parse tree
Joachim Bingel87480d02014-01-17 14:07:46 +0000113 * @throws QueryException
Joachim Bingel5c93f902013-11-19 14:49:04 +0000114 */
Joachim Bingel87480d02014-01-17 14:07:46 +0000115 public CosmasTree(String query) throws QueryException {
Joachim Bingel5c93f902013-11-19 14:49:04 +0000116 this.query = query;
117 process(query);
Joachim Bingelc8a28e42014-04-24 15:06:42 +0000118 System.out.println("\n"+requestMap.get("query"));
119 log.info(">>> " + requestMap.get("query") + " <<<");
Joachim Bingel5c93f902013-11-19 14:49:04 +0000120 }
121
122 @Override
123 public Map<String, Object> getRequestMap() {
124 return this.requestMap;
125 }
126
Joachim Bingel11d5b152014-02-11 21:33:47 +0000127
Joachim Bingelb5f7bf02014-01-07 16:36:54 +0000128
Joachim Bingel5c93f902013-11-19 14:49:04 +0000129 @Override
Joachim Bingel87480d02014-01-17 14:07:46 +0000130 public void process(String query) throws QueryException {
131 Tree tree = null;
132 try {
133 tree = parseCosmasQuery(query);
134 } catch (RecognitionException e) {
135 throw new QueryException("Your query could not be processed. Please make sure it is well-formed.");
136 } catch (NullPointerException e) {
137 throw new QueryException("Your query could not be processed. Please make sure it is well-formed.");
138 }
139
Joachim Bingel5c93f902013-11-19 14:49:04 +0000140 System.out.println("Processing Cosmas");
Joachim Bingel81812632014-02-18 08:55:22 +0000141 requestMap.put("@context", "http://ids-mannheim.de/ns/KorAP/json-ld/v0.1/context.jsonld");
Joachim Bingelc8a28e42014-04-24 15:06:42 +0000142// prepareContext(requestMap);
Joachim Bingel5c93f902013-11-19 14:49:04 +0000143 processNode(tree);
144 }
145
Joachim Bingel402c6e12014-05-08 17:09:06 +0000146 @SuppressWarnings("unchecked")
Joachim Bingel5c93f902013-11-19 14:49:04 +0000147 private void processNode(Tree node) {
148
149 // Top-down processing
150 if (visited.contains(node)) return;
151 else visited.add(node);
152
153
Joachim Bingelc8a28e42014-04-24 15:06:42 +0000154 String nodeCat = getNodeCat(node);
Joachim Bingel5c93f902013-11-19 14:49:04 +0000155 openNodeCats.push(nodeCat);
156
Joachim Bingelb5f7bf02014-01-07 16:36:54 +0000157 stackedObjects = 0;
Joachim Bingel5c93f902013-11-19 14:49:04 +0000158
Joachim Bingelb5f7bf02014-01-07 16:36:54 +0000159 if (debug) {
Joachim Bingelb5f7bf02014-01-07 16:36:54 +0000160 System.err.println(" "+objectStack);
161 System.out.println(openNodeCats);
162 }
Joachim Bingel5c93f902013-11-19 14:49:04 +0000163
Joachim Bingel5c93f902013-11-19 14:49:04 +0000164
165 /* ***************************************
166 * Processing individual node categories *
167 *****************************************/
Joachim Bingeld5161a12014-01-08 11:15:49 +0000168
169
170 // Check for potential implicit sequences as in (C2PQ (OPWF der) (OPWF Mann)). The sequence is introduced
171 // by the first child if it (and its siblings) is sequentiable.
172 if (sequentiableCats.contains(nodeCat)) {
173 // for each node, check if parent has more than one child (-> could be implicit sequence)
Joachim Bingeleecc7652014-01-11 17:21:07 +0000174 Tree parent = node.getParent();
175 if (parent.getChildCount()>1) {
Joachim Bingeld5161a12014-01-08 11:15:49 +0000176 // if node is first child of parent...
Joachim Bingeleecc7652014-01-11 17:21:07 +0000177 if (node == parent.getChild(0)) {
178 hasSequentiableSiblings = false;
179 for (int i=1; i<parent.getChildCount() ;i++) {
Joachim Bingelc8a28e42014-04-24 15:06:42 +0000180 if (sequentiableCats.contains(getNodeCat(parent.getChild(i)))) {
Joachim Bingeleecc7652014-01-11 17:21:07 +0000181 hasSequentiableSiblings = true;
Joachim Bingel81812632014-02-18 08:55:22 +0000182 continue;
Joachim Bingeleecc7652014-01-11 17:21:07 +0000183 }
Joachim Bingeld5161a12014-01-08 11:15:49 +0000184 }
Joachim Bingeleecc7652014-01-11 17:21:07 +0000185 if (hasSequentiableSiblings) {
186 // Step I: create sequence
187 LinkedHashMap<String, Object> sequence = new LinkedHashMap<String, Object>();
Joachim Bingel2daf9862014-02-12 10:18:54 +0000188 sequence.put("@type", "korap:group");
Joachim Bingel81812632014-02-18 08:55:22 +0000189 sequence.put("operation", "operation:sequence");
Joachim Bingel11d5b152014-02-11 21:33:47 +0000190 sequence.put("operands", new ArrayList<Object>());
Joachim Bingeleecc7652014-01-11 17:21:07 +0000191 // push sequence on object stack but don't increment stackedObjects counter since
192 // we've got to wait until the parent node is processed - therefore, add the parent
193 // to the sequencedNodes list and remove the sequence from the stack when the parent
194 // has been processed
195 objectStack.push(sequence);
196 sequencedNodes.push(parent);
197 // Step II: decide where to put sequence
Joachim Bingelcc1dc242014-01-15 09:32:38 +0000198 putIntoSuperObject(sequence, 1);
Joachim Bingeleecc7652014-01-11 17:21:07 +0000199 }
Joachim Bingeld5161a12014-01-08 11:15:49 +0000200 }
201 }
202 }
203
Joachim Bingel5c93f902013-11-19 14:49:04 +0000204 // Nodes introducing tokens. Process all in the same manner, except for the fieldMap entry
Joachim Bingelffd65e32014-01-22 14:22:57 +0000205 if (nodeCat.equals("OPWF") || nodeCat.equals("OPLEM")) {
Joachim Bingel5c93f902013-11-19 14:49:04 +0000206
Joachim Bingelb5f7bf02014-01-07 16:36:54 +0000207 //Step I: get info
208 LinkedHashMap<String, Object> token = new LinkedHashMap<String, Object>();
Joachim Bingel2daf9862014-02-12 10:18:54 +0000209 token.put("@type", "korap:token");
Joachim Bingelb5f7bf02014-01-07 16:36:54 +0000210 objectStack.push(token);
211 stackedObjects++;
Joachim Bingelb5f7bf02014-01-07 16:36:54 +0000212 LinkedHashMap<String, Object> fieldMap = new LinkedHashMap<String, Object>();
Joachim Bingel2daf9862014-02-12 10:18:54 +0000213 token.put("wrap", fieldMap);
Joachim Bingel5c93f902013-11-19 14:49:04 +0000214
Joachim Bingel2daf9862014-02-12 10:18:54 +0000215 fieldMap.put("@type", "korap:term");
Joachim Bingel5c93f902013-11-19 14:49:04 +0000216 // make category-specific fieldMap entry
Joachim Bingelba9a0ab2014-01-29 10:12:25 +0000217 String attr = nodeCat.equals("OPWF") ? "orth" : "lemma";
218 String value = node.getChild(0).toStringTree().replaceAll("\"", "");
Joachim Bingelee3b21d2014-02-12 12:34:59 +0000219 if (value.startsWith("$")) {
220 value = value.substring(1);
221 fieldMap.put("caseInsensitive", true);
222 }
Joachim Bingel11d5b152014-02-11 21:33:47 +0000223 fieldMap.put("key", value);
224 fieldMap.put("layer", attr);
Joachim Bingelffd65e32014-01-22 14:22:57 +0000225
Joachim Bingel5c93f902013-11-19 14:49:04 +0000226 // negate field (see above)
227 if (negate) {
Joachim Bingel0207d5e2014-02-12 14:18:41 +0000228 fieldMap.put("match", "match:ne");
Joachim Bingelb5f7bf02014-01-07 16:36:54 +0000229 } else {
Joachim Bingel0207d5e2014-02-12 14:18:41 +0000230 fieldMap.put("match", "match:eq");
Joachim Bingel5c93f902013-11-19 14:49:04 +0000231 }
Joachim Bingelb5f7bf02014-01-07 16:36:54 +0000232 //Step II: decide where to put
Joachim Bingelc8a28e42014-04-24 15:06:42 +0000233 if (! hasChild(node, "TPOS")) {
Joachim Bingel81812632014-02-18 08:55:22 +0000234 putIntoSuperObject(token, 1);
235 } else {
236
237 }
238
Joachim Bingelb5f7bf02014-01-07 16:36:54 +0000239 }
240
Joachim Bingelffd65e32014-01-22 14:22:57 +0000241 if (nodeCat.equals("OPMORPH")) {
242 //Step I: get info
243 LinkedHashMap<String, Object> token = new LinkedHashMap<String, Object>();
Joachim Bingel2daf9862014-02-12 10:18:54 +0000244 token.put("@type", "korap:token");
Joachim Bingelba9a0ab2014-01-29 10:12:25 +0000245 LinkedHashMap<String, Object> fieldMap = new LinkedHashMap<String, Object>();
Joachim Bingel2daf9862014-02-12 10:18:54 +0000246 token.put("wrap", fieldMap);
Joachim Bingelffd65e32014-01-22 14:22:57 +0000247
Joachim Bingel2daf9862014-02-12 10:18:54 +0000248 fieldMap.put("@type", "korap:term");
Joachim Bingel11d5b152014-02-11 21:33:47 +0000249// fieldMap.put("key", "morph:"+node.getChild(0).toString().replace(" ", "_"));
Joachim Bingel0207d5e2014-02-12 14:18:41 +0000250 String[] morphValues = node.getChild(0).toString().split(" ");
251 String pos = morphValues[0];
252
253 fieldMap.put("key", pos);
254 fieldMap.put("layer", "pos");
Joachim Bingelba9a0ab2014-01-29 10:12:25 +0000255 // make category-specific fieldMap entry
256 // negate field (see above)
257 if (negate) {
Joachim Bingel0207d5e2014-02-12 14:18:41 +0000258 fieldMap.put("match", "match:ne");
Joachim Bingelffd65e32014-01-22 14:22:57 +0000259 } else {
Joachim Bingel0207d5e2014-02-12 14:18:41 +0000260 fieldMap.put("match", "match:eq");
Joachim Bingelffd65e32014-01-22 14:22:57 +0000261 }
Joachim Bingelc8a28e42014-04-24 15:06:42 +0000262// List<String> morphValues = parseMorph(node.getChild(0).toStringTree());
Joachim Bingelba9a0ab2014-01-29 10:12:25 +0000263// System.err.println(morphValues);
264// if (morphValues.size() == 1) {
265// LinkedHashMap<String, Object> fieldMap = new LinkedHashMap<String, Object>();
Joachim Bingel11d5b152014-02-11 21:33:47 +0000266// token.put("key", fieldMap);
Joachim Bingelba9a0ab2014-01-29 10:12:25 +0000267//
Joachim Bingel2daf9862014-02-12 10:18:54 +0000268// fieldMap.put("@type", "korap:term");
Joachim Bingel11d5b152014-02-11 21:33:47 +0000269// fieldMap.put("key", morphValues.get(0));
Joachim Bingelba9a0ab2014-01-29 10:12:25 +0000270// // make category-specific fieldMap entry
271// // negate field (see above)
272// if (negate) {
Joachim Bingel2daf9862014-02-12 10:18:54 +0000273// fieldMap.put("operation", "operation:"+ "!=");
Joachim Bingelba9a0ab2014-01-29 10:12:25 +0000274// } else {
Joachim Bingel2daf9862014-02-12 10:18:54 +0000275// fieldMap.put("operation", "operation:"+ "=");
Joachim Bingelba9a0ab2014-01-29 10:12:25 +0000276// }
277// } else {
278// LinkedHashMap<String, Object> conjGroup = new LinkedHashMap<String, Object>();
Joachim Bingel11d5b152014-02-11 21:33:47 +0000279// token.put("key", conjGroup);
Joachim Bingelba9a0ab2014-01-29 10:12:25 +0000280// ArrayList<Object> conjOperands = new ArrayList<Object>();
Joachim Bingel2daf9862014-02-12 10:18:54 +0000281// conjGroup.put("@type", "korap:group");
282// conjGroup.put("operation", "operation:"+ "and");
Joachim Bingel11d5b152014-02-11 21:33:47 +0000283// conjGroup.put("operands", conjOperands);
Joachim Bingelba9a0ab2014-01-29 10:12:25 +0000284// for (String value : morphValues) {
285// LinkedHashMap<String, Object> fieldMap = new LinkedHashMap<String, Object>();
Joachim Bingel11d5b152014-02-11 21:33:47 +0000286// token.put("key", fieldMap);
Joachim Bingelba9a0ab2014-01-29 10:12:25 +0000287//
Joachim Bingel2daf9862014-02-12 10:18:54 +0000288// fieldMap.put("@type", "korap:term");
Joachim Bingel11d5b152014-02-11 21:33:47 +0000289// fieldMap.put("key", value);
Joachim Bingelba9a0ab2014-01-29 10:12:25 +0000290// // make category-specific fieldMap entry
291// // negate field (see above)
292// if (negate) {
Joachim Bingel2daf9862014-02-12 10:18:54 +0000293// fieldMap.put("operation", "operation:"+ "!=");
Joachim Bingelba9a0ab2014-01-29 10:12:25 +0000294// } else {
Joachim Bingel2daf9862014-02-12 10:18:54 +0000295// fieldMap.put("operation", "operation:"+ "=");
Joachim Bingelba9a0ab2014-01-29 10:12:25 +0000296// }
297// }
298// }
Joachim Bingelffd65e32014-01-22 14:22:57 +0000299
300
301 //Step II: decide where to put
302 putIntoSuperObject(token, 0);
303 }
304
Joachim Bingeleecc7652014-01-11 17:21:07 +0000305 if (nodeCat.equals("OPELEM")) {
306 // Step I: create element
307 LinkedHashMap<String, Object> elem = new LinkedHashMap<String, Object>();
Joachim Bingel2daf9862014-02-12 10:18:54 +0000308 elem.put("@type", "korap:span");
Joachim Bingel402c6e12014-05-08 17:09:06 +0000309 if (node.getChild(0).toStringTree().equals("EMPTY")) {
310
311 } else {
312 int elname = 0;
313 Tree elnameNode = getFirstChildWithCat(node, "ELNAME");
314 if (elnameNode != null) {
315 elem.put("key", elnameNode.getChild(0).toStringTree().toLowerCase());
316 elname = 1;
317 }
318 if (node.getChildCount() > elname) {
319 LinkedHashMap<String, Object> termGroup = makeTermGroup("and");
320 ArrayList<Object> termGroupOperands = (ArrayList<Object>) termGroup.get("operands");
321 for (int i=elname; i<node.getChildCount(); i++) {
322 Tree attrNode = node.getChild(i);
323 if (attrNode.getChildCount()==2) {
324 LinkedHashMap<String, Object> term = makeTerm();
325 termGroupOperands.add(term);
326 String layer = attrNode.getChild(0).toStringTree();
327 term.put("layer", translateMorph(layer));
328 term.put("key", attrNode.getChild(1).toStringTree());
329 term.put("match", "match:eq");
330 } else {
331 for (int j=1; j<attrNode.getChildCount(); j++) {
332 LinkedHashMap<String, Object> term = makeTerm();
333 termGroupOperands.add(term);
334 String layer = attrNode.getChild(0).toStringTree();
335 term.put("layer", translateMorph(layer));
336 term.put("key", attrNode.getChild(j).toStringTree());
337 term.put("match", "match:eq");
338 }
339 }
340
341
342 if (getNodeCat(attrNode).equals("NOTEQ")) negate=true;
343
344 }
345 elem.put("attr", termGroup);
346 }
347 }
348
Joachim Bingeleecc7652014-01-11 17:21:07 +0000349 //Step II: decide where to put
Joachim Bingelcc1dc242014-01-15 09:32:38 +0000350 putIntoSuperObject(elem);
351 }
Joachim Bingeleecc7652014-01-11 17:21:07 +0000352
Joachim Bingelb5f7bf02014-01-07 16:36:54 +0000353 if (nodeCat.equals("OPLABEL")) {
354 // Step I: create element
355 LinkedHashMap<String, Object> elem = new LinkedHashMap<String, Object>();
Joachim Bingel2daf9862014-02-12 10:18:54 +0000356 elem.put("@type", "korap:span");
Joachim Bingel11d5b152014-02-11 21:33:47 +0000357 elem.put("key", node.getChild(0).toStringTree().replaceAll("<|>", ""));
Joachim Bingelb5f7bf02014-01-07 16:36:54 +0000358 //Step II: decide where to put
Joachim Bingelcc1dc242014-01-15 09:32:38 +0000359 putIntoSuperObject(elem);
Joachim Bingel5c93f902013-11-19 14:49:04 +0000360 }
361
Joachim Bingelb7a59792014-02-14 13:52:29 +0000362 if (nodeCat.equals("OPAND") || nodeCat.equals("OPNOT")) {
363 // Step I: create group
364 LinkedHashMap<String, Object> distgroup = new LinkedHashMap<String, Object>();
365 distgroup.put("@type", "korap:group");
366 distgroup.put("operation", "operation:sequence");
367 ArrayList<Object> distances = new ArrayList<Object>();
368 LinkedHashMap<String, Object> zerodistance = new LinkedHashMap<String, Object>();
369 zerodistance.put("@type", "korap:distance");
370 zerodistance.put("key", "t");
371 zerodistance.put("min", 0);
372 zerodistance.put("max", 0);
373 if (nodeCat.equals("OPNOT")) zerodistance.put("exclude", true);
374 distances.add(zerodistance);
375 distgroup.put("distances", distances);
376 distgroup.put("operands", new ArrayList<Object>());
377 objectStack.push(distgroup);
378 stackedObjects++;
379 // Step II: decide where to put
380 putIntoSuperObject(distgroup, 1);
381 }
382
383 if (nodeCat.equals("OPOR")) {
Joachim Bingelb5f7bf02014-01-07 16:36:54 +0000384 // Step I: create group
385 LinkedHashMap<String, Object> disjunction = new LinkedHashMap<String, Object>();
Joachim Bingel2daf9862014-02-12 10:18:54 +0000386 disjunction.put("@type", "korap:group");
Joachim Bingelb7a59792014-02-14 13:52:29 +0000387 disjunction.put("operation", "operation:or");
Joachim Bingel11d5b152014-02-11 21:33:47 +0000388 disjunction.put("operands", new ArrayList<Object>());
Joachim Bingelb5f7bf02014-01-07 16:36:54 +0000389 objectStack.push(disjunction);
390 stackedObjects++;
Joachim Bingelb5f7bf02014-01-07 16:36:54 +0000391 // Step II: decide where to put
Joachim Bingelcc1dc242014-01-15 09:32:38 +0000392 putIntoSuperObject(disjunction, 1);
Joachim Bingel5c93f902013-11-19 14:49:04 +0000393 }
394
395 if (nodeCat.equals("OPPROX")) {
Joachim Bingelba9a0ab2014-01-29 10:12:25 +0000396 //TODO direction "both": wrap in "or" group with operands once flipped, once not
Joachim Bingelb5f7bf02014-01-07 16:36:54 +0000397 // collect info
Joachim Bingel5c93f902013-11-19 14:49:04 +0000398 Tree prox_opts = node.getChild(0);
399 Tree typ = prox_opts.getChild(0);
Joachim Bingel5c93f902013-11-19 14:49:04 +0000400 Tree dist_list = prox_opts.getChild(1);
Joachim Bingel89cceac2014-01-08 15:51:08 +0000401 // Step I: create group
Joachim Bingelba9a0ab2014-01-29 10:12:25 +0000402 LinkedHashMap<String, Object> proxSequence = new LinkedHashMap<String, Object>();
Joachim Bingel2daf9862014-02-12 10:18:54 +0000403 proxSequence.put("@type", "korap:group");
404 proxSequence.put("operation", "operation:"+ "sequence");
Joachim Bingelba9a0ab2014-01-29 10:12:25 +0000405 objectStack.push(proxSequence);
Joachim Bingelb5f7bf02014-01-07 16:36:54 +0000406 stackedObjects++;
Joachim Bingel89cceac2014-01-08 15:51:08 +0000407 ArrayList<Object> constraints = new ArrayList<Object>();
Joachim Bingelba9a0ab2014-01-29 10:12:25 +0000408 boolean exclusion = ! typ.getChild(0).toStringTree().equals("PROX");
409
Joachim Bingel36233b52014-02-13 10:48:24 +0000410 boolean inOrder = false;
Joachim Bingel11d5b152014-02-11 21:33:47 +0000411 proxSequence.put("inOrder", inOrder);
412 proxSequence.put("distances", constraints);
Joachim Bingelba9a0ab2014-01-29 10:12:25 +0000413
Joachim Bingel3f0850c2014-01-17 16:50:10 +0000414 ArrayList<Object> operands = new ArrayList<Object>();
Joachim Bingel11d5b152014-02-11 21:33:47 +0000415 proxSequence.put("operands", operands);
Joachim Bingel36233b52014-02-13 10:48:24 +0000416
417 // possibly several distance constraints
418 for (int i=0; i<dist_list.getChildCount(); i++) {
419 String direction = dist_list.getChild(i).getChild(0).getChild(0).toStringTree().toLowerCase();
420 String min = dist_list.getChild(i).getChild(1).getChild(0).toStringTree();
421 String max = dist_list.getChild(i).getChild(1).getChild(1).toStringTree();
422 String meas = dist_list.getChild(i).getChild(2).getChild(0).toStringTree();
Joachim Bingel89cceac2014-01-08 15:51:08 +0000423 if (min.equals("VAL0")) {
Joachim Bingel87480d02014-01-17 14:07:46 +0000424 min="0";
Joachim Bingel89cceac2014-01-08 15:51:08 +0000425 }
426 LinkedHashMap<String, Object> distance = new LinkedHashMap<String, Object>();
Joachim Bingel2daf9862014-02-12 10:18:54 +0000427 distance.put("@type", "korap:distance");
428 distance.put("key", meas);
Joachim Bingel11d5b152014-02-11 21:33:47 +0000429 distance.put("min", Integer.parseInt(min));
430 distance.put("max", Integer.parseInt(max));
Joachim Bingelba9a0ab2014-01-29 10:12:25 +0000431 if (exclusion) {
Joachim Bingel11d5b152014-02-11 21:33:47 +0000432 distance.put("exclude", exclusion);
Joachim Bingelba9a0ab2014-01-29 10:12:25 +0000433 }
Joachim Bingel89cceac2014-01-08 15:51:08 +0000434 constraints.add(distance);
Joachim Bingel36233b52014-02-13 10:48:24 +0000435 if (direction.equals("plus")) {
436 inOrder=true;
437 } else if (direction.equals("minus")) {
438 inOrder=true;
439 invertedOperandsLists.add(operands);
Joachim Bingel89cceac2014-01-08 15:51:08 +0000440 }
441 }
Joachim Bingel36233b52014-02-13 10:48:24 +0000442 proxSequence.put("inOrder", inOrder);
Joachim Bingelb5f7bf02014-01-07 16:36:54 +0000443 // Step II: decide where to put
Joachim Bingelba9a0ab2014-01-29 10:12:25 +0000444 putIntoSuperObject(proxSequence, 1);
Joachim Bingel5c93f902013-11-19 14:49:04 +0000445 }
446
Joachim Bingeld5161a12014-01-08 11:15:49 +0000447 // inlcusion or overlap
448 if (nodeCat.equals("OPIN") || nodeCat.equals("OPOV")) {
Joachim Bingelb5f7bf02014-01-07 16:36:54 +0000449 // Step I: create group
Joachim Bingelba9a0ab2014-01-29 10:12:25 +0000450 LinkedHashMap<String, Object> submatchgroup = new LinkedHashMap<String, Object>();
Joachim Bingel2daf9862014-02-12 10:18:54 +0000451 submatchgroup.put("@type", "korap:group");
452 submatchgroup.put("operation", "operation:"+ "submatch");
453 ArrayList<Integer> classRef = new ArrayList<Integer>();
Joachim Bingel402c6e12014-05-08 17:09:06 +0000454 classRef.add(classRefCounter);
Joachim Bingel2daf9862014-02-12 10:18:54 +0000455 submatchgroup.put("classRef", classRef);
Joachim Bingeleecc7652014-01-11 17:21:07 +0000456
Joachim Bingelba9a0ab2014-01-29 10:12:25 +0000457 ArrayList<Object> submatchoperands = new ArrayList<Object>();
Joachim Bingeleecc7652014-01-11 17:21:07 +0000458 LinkedHashMap<String, Object> posgroup = new LinkedHashMap<String, Object>();
Joachim Bingel11d5b152014-02-11 21:33:47 +0000459 submatchgroup.put("operands", submatchoperands);
Joachim Bingelba9a0ab2014-01-29 10:12:25 +0000460 submatchoperands.add(posgroup);
Joachim Bingel2daf9862014-02-12 10:18:54 +0000461 posgroup.put("@type", "korap:group");
Joachim Bingel84e33df2014-01-31 14:02:46 +0000462// String relation = nodeCat.equals("OPIN") ? "position" : "overlaps";
Joachim Bingel2daf9862014-02-12 10:18:54 +0000463 posgroup.put("operation", "operation:"+ "position");
Joachim Bingel87480d02014-01-17 14:07:46 +0000464 if (nodeCat.equals("OPIN")) {
465 parseOPINOptions(node, posgroup);
Joachim Bingelcc1dc242014-01-15 09:32:38 +0000466 } else {
Joachim Bingel87480d02014-01-17 14:07:46 +0000467 parseOPOVOptions(node, posgroup);
Joachim Bingeld5161a12014-01-08 11:15:49 +0000468 }
Joachim Bingelcc1dc242014-01-15 09:32:38 +0000469 ArrayList<Object> posoperands = new ArrayList<Object>();
Joachim Bingel11d5b152014-02-11 21:33:47 +0000470 posgroup.put("operands", posoperands);
Joachim Bingeleecc7652014-01-11 17:21:07 +0000471 objectStack.push(posgroup);
Joachim Bingelcc1dc242014-01-15 09:32:38 +0000472 // mark this an inverted list
473 invertedOperandsLists.push(posoperands);
Joachim Bingeld5161a12014-01-08 11:15:49 +0000474 stackedObjects++;
Joachim Bingeld5161a12014-01-08 11:15:49 +0000475 // Step II: decide where to put
Joachim Bingelba9a0ab2014-01-29 10:12:25 +0000476 putIntoSuperObject(submatchgroup, 1);
Joachim Bingeld5161a12014-01-08 11:15:49 +0000477 }
478
Joachim Bingel87480d02014-01-17 14:07:46 +0000479
480 // Wrap the first argument of an #IN operator in a class group
Joachim Bingel36233b52014-02-13 10:48:24 +0000481 if (nodeCat.equals("ARG1") && (openNodeCats.get(1).equals("OPIN") || openNodeCats.get(1).equals("OPOV") || openNodeCats.get(2).equals("OPNHIT"))) {
Joachim Bingelcc1dc242014-01-15 09:32:38 +0000482 // Step I: create group
483 LinkedHashMap<String, Object> classGroup = new LinkedHashMap<String, Object>();
Joachim Bingel2daf9862014-02-12 10:18:54 +0000484 classGroup.put("@type", "korap:group");
485 classGroup.put("operation", "operation:"+ "class");
Joachim Bingel402c6e12014-05-08 17:09:06 +0000486 classGroup.put("class", classRefCounter);
487 classRefCounter++;
Joachim Bingel11d5b152014-02-11 21:33:47 +0000488 classGroup.put("operands", new ArrayList<Object>());
Joachim Bingelcc1dc242014-01-15 09:32:38 +0000489 objectStack.push(classGroup);
490 stackedObjects++;
491 // Step II: decide where to put
492 putIntoSuperObject(classGroup, 1);
493 }
494
Joachim Bingel36233b52014-02-13 10:48:24 +0000495 // Wrap the 2nd argument of an #IN operator embedded in NHIT in a class group
496 if (nodeCat.equals("ARG2") && openNodeCats.get(2).equals("OPNHIT")) {
497 // Step I: create group
498 LinkedHashMap<String, Object> classGroup = new LinkedHashMap<String, Object>();
499 classGroup.put("@type", "korap:group");
500 classGroup.put("operation", "operation:"+ "class");
Joachim Bingel402c6e12014-05-08 17:09:06 +0000501 classGroup.put("class", classRefCounter);
502 classRefCounter++;
Joachim Bingel36233b52014-02-13 10:48:24 +0000503 classGroup.put("operands", new ArrayList<Object>());
504 objectStack.push(classGroup);
505 stackedObjects++;
506 // Step II: decide where to put
507 putIntoSuperObject(classGroup, 1);
508 }
509
Joachim Bingelcc1dc242014-01-15 09:32:38 +0000510
Joachim Bingel8c640e42014-02-07 16:20:47 +0000511 if (nodeCat.equals("OPNHIT")) {
Joachim Bingel8c640e42014-02-07 16:20:47 +0000512 LinkedHashMap<String, Object> exclGroup = new LinkedHashMap<String, Object>();
Joachim Bingel2daf9862014-02-12 10:18:54 +0000513 exclGroup.put("@type", "korap:group");
Joachim Bingel36233b52014-02-13 10:48:24 +0000514 exclGroup.put("operation", "operation:"+ "submatch");
Joachim Bingel8c640e42014-02-07 16:20:47 +0000515 ArrayList<Integer> classRef = new ArrayList<Integer>();
Joachim Bingel402c6e12014-05-08 17:09:06 +0000516
517 classRef.add(classRefCounter);
518// classRefCounter++;
519 // yes, do this twice!
520 classRef.add(classRefCounter+1);
521// classRefCounter++;
Joachim Bingel8c640e42014-02-07 16:20:47 +0000522 exclGroup.put("classRef", classRef);
Joachim Bingel2daf9862014-02-12 10:18:54 +0000523 exclGroup.put("classRefOp", "classRefOp:"+"intersection");
Joachim Bingel8c640e42014-02-07 16:20:47 +0000524 ArrayList<Object> operands = new ArrayList<Object>();
Joachim Bingel11d5b152014-02-11 21:33:47 +0000525 exclGroup.put("operands", operands);
Joachim Bingel8c640e42014-02-07 16:20:47 +0000526 objectStack.push(exclGroup);
527 stackedObjects++;
528 putIntoSuperObject(exclGroup, 1);
Joachim Bingel89cceac2014-01-08 15:51:08 +0000529 }
530
Joachim Bingeld5161a12014-01-08 11:15:49 +0000531 if (nodeCat.equals("OPEND") || nodeCat.equals("OPBEG")) {
532 // Step I: create group
Joachim Bingel3f0850c2014-01-17 16:50:10 +0000533 LinkedHashMap<String, Object> beggroup = new LinkedHashMap<String, Object>();
Joachim Bingel2daf9862014-02-12 10:18:54 +0000534 beggroup.put("@type", "korap:group");
535 beggroup.put("operation", "operation:"+ "submatch");
Joachim Bingelba9a0ab2014-01-29 10:12:25 +0000536 ArrayList<Integer> spanRef = new ArrayList<Integer>();
537 if (nodeCat.equals("OPBEG")) {
538 spanRef.add(0); spanRef.add(1);
539 } else {
540 spanRef.add(-1); spanRef.add(1);
541 }
Joachim Bingelcd7b7252014-02-13 08:49:14 +0000542 beggroup.put("spanRef", spanRef);
Joachim Bingel11d5b152014-02-11 21:33:47 +0000543 beggroup.put("operands", new ArrayList<Object>());
Joachim Bingel3f0850c2014-01-17 16:50:10 +0000544 objectStack.push(beggroup);
Joachim Bingelb5f7bf02014-01-07 16:36:54 +0000545 stackedObjects++;
546
547 // Step II: decide where to put
Joachim Bingel3f0850c2014-01-17 16:50:10 +0000548 putIntoSuperObject(beggroup, 1);
Joachim Bingelb5f7bf02014-01-07 16:36:54 +0000549 }
Joachim Bingel5c93f902013-11-19 14:49:04 +0000550
Joachim Bingeleecc7652014-01-11 17:21:07 +0000551 if (nodeCat.equals("OPBED")) {
552 // Step I: create group
Joachim Bingeleecc7652014-01-11 17:21:07 +0000553 int optsChild = node.getChildCount()-1;
Joachim Bingele98d0882014-01-21 12:58:54 +0000554 Tree conditions = node.getChild(optsChild).getChild(0);
Joachim Bingel36233b52014-02-13 10:48:24 +0000555
556 // create a containing group expressing the submatch constraint on the first argument
557 LinkedHashMap<String, Object> submatchgroup = new LinkedHashMap<String, Object>();
558 submatchgroup.put("@type", "korap:group");
559 submatchgroup.put("operation", "operation:"+ "submatch");
560 ArrayList<Integer> spanRef = new ArrayList<Integer>();
561 spanRef.add(1);
562 submatchgroup.put("classRef", spanRef);
563 ArrayList<Object> submatchoperands = new ArrayList<Object>();
564 submatchgroup.put("operands", submatchoperands);
Joachim Bingel81812632014-02-18 08:55:22 +0000565 putIntoSuperObject(submatchgroup, 0);
Joachim Bingel36233b52014-02-13 10:48:24 +0000566
Joachim Bingelcd7b7252014-02-13 08:49:14 +0000567 // Distinguish two cases. Normal case: query has just one condition, like #BED(X, sa) ...
Joachim Bingel3f0850c2014-01-17 16:50:10 +0000568 if (conditions.getChildCount()==1) {
Joachim Bingelcd7b7252014-02-13 08:49:14 +0000569 CosmasCondition c = new CosmasCondition(conditions.getChild(0));
Joachim Bingelcd7b7252014-02-13 08:49:14 +0000570
571 // create the group expressing the position constraint
Joachim Bingel3f0850c2014-01-17 16:50:10 +0000572 LinkedHashMap<String, Object> posgroup = new LinkedHashMap<String, Object>();
Joachim Bingel2daf9862014-02-12 10:18:54 +0000573 posgroup.put("@type", "korap:group");
574 posgroup.put("operation", "operation:"+ "position");
Joachim Bingelcd7b7252014-02-13 08:49:14 +0000575
Joachim Bingel2daf9862014-02-12 10:18:54 +0000576 posgroup.put("frame", "frame:"+c.position);
Joachim Bingelcd7b7252014-02-13 08:49:14 +0000577 if (c.negated) posgroup.put("exclude", true);
Joachim Bingele98d0882014-01-21 12:58:54 +0000578 ArrayList<Object> operands = new ArrayList<Object>();
Joachim Bingel11d5b152014-02-11 21:33:47 +0000579 posgroup.put("operands", operands);
Joachim Bingelcd7b7252014-02-13 08:49:14 +0000580
581 // create span representing the element expressed in the condition
Joachim Bingele98d0882014-01-21 12:58:54 +0000582 LinkedHashMap<String, Object> bedElem = new LinkedHashMap<String, Object>();
Joachim Bingel2daf9862014-02-12 10:18:54 +0000583 bedElem.put("@type", "korap:span");
Joachim Bingel11d5b152014-02-11 21:33:47 +0000584 bedElem.put("key", c.elem);
Joachim Bingelcd7b7252014-02-13 08:49:14 +0000585
586 // create a class group containing the argument, in order to submatch the arg.
587 LinkedHashMap<String, Object> classGroup = new LinkedHashMap<String, Object>();
588 classGroup.put("@type", "korap:group");
589 classGroup.put("operation", "operation:class");
Joachim Bingel402c6e12014-05-08 17:09:06 +0000590 classGroup.put("class", classRefCounter);
591 classRefCounter++;
Joachim Bingelcd7b7252014-02-13 08:49:14 +0000592 classGroup.put("operands", new ArrayList<Object>());
593 objectStack.push(classGroup);
Joachim Bingel3f0850c2014-01-17 16:50:10 +0000594 stackedObjects++;
Joachim Bingelcd7b7252014-02-13 08:49:14 +0000595 operands.add(bedElem);
596 operands.add(classGroup);
Joachim Bingel3f0850c2014-01-17 16:50:10 +0000597 // Step II: decide where to put
Joachim Bingelcd7b7252014-02-13 08:49:14 +0000598 submatchoperands.add(posgroup);
Joachim Bingel36233b52014-02-13 10:48:24 +0000599
Joachim Bingele98d0882014-01-21 12:58:54 +0000600 // ... or the query has several conditions specified, like #BED(XY, sa,-pa). In that case,
601 // create an 'and' group and embed the position groups in its operands
Joachim Bingel3f0850c2014-01-17 16:50:10 +0000602 } else {
603 // node has several conditions (like 'sa, -pa')
Joachim Bingel36233b52014-02-13 10:48:24 +0000604 // -> create zero-distance sequence group and embed all position groups there
Joachim Bingel3f0850c2014-01-17 16:50:10 +0000605 LinkedHashMap<String, Object> conjunct = new LinkedHashMap<String, Object>();
Joachim Bingel2daf9862014-02-12 10:18:54 +0000606 conjunct.put("@type", "korap:group");
Joachim Bingel36233b52014-02-13 10:48:24 +0000607 conjunct.put("operation", "operation:"+ "sequence");
608 ArrayList<Object> distances = new ArrayList<Object>();
609 conjunct.put("distances", distances);
610 LinkedHashMap<String, Object> zerodistance = new LinkedHashMap<String, Object>();
611 zerodistance.put("@type", "korap:distance");
612 zerodistance.put("key", "w");
613 zerodistance.put("min", 0);
614 zerodistance.put("max", 0);
615 distances.add(zerodistance);
Joachim Bingel3f0850c2014-01-17 16:50:10 +0000616 ArrayList<Object> operands = new ArrayList<Object>();
Joachim Bingel11d5b152014-02-11 21:33:47 +0000617 conjunct.put("operands", operands);
Joachim Bingele98d0882014-01-21 12:58:54 +0000618 ArrayList<ArrayList<Object>> distributedOperands = new ArrayList<ArrayList<Object>>();
619
Joachim Bingel3f0850c2014-01-17 16:50:10 +0000620 for (int i=0; i<conditions.getChildCount(); i++) {
Joachim Bingel36233b52014-02-13 10:48:24 +0000621 // for each condition, create a position group containing a class group. problem: how to get argument into every operands list?
Joachim Bingele98d0882014-01-21 12:58:54 +0000622 // -> use distributedOperandsLists
623 LinkedHashMap<String, Object> posGroup = new LinkedHashMap<String, Object>();
624 operands.add(posGroup);
625
Joachim Bingel36233b52014-02-13 10:48:24 +0000626 // make position group
Joachim Bingele98d0882014-01-21 12:58:54 +0000627 CosmasCondition c = new CosmasCondition(conditions.getChild(i));
Joachim Bingel2daf9862014-02-12 10:18:54 +0000628 posGroup.put("@type", "korap:group");
629 posGroup.put("operation", "operation:"+ "position");
630 posGroup.put("frame", "frame:"+c.position);
Joachim Bingel11d5b152014-02-11 21:33:47 +0000631 if (c.negated) posGroup.put("exclude", "true");
Joachim Bingele98d0882014-01-21 12:58:54 +0000632 ArrayList<Object> posOperands = new ArrayList<Object>();
Joachim Bingel36233b52014-02-13 10:48:24 +0000633
634 // make class group
635 LinkedHashMap<String, Object> classGroup = new LinkedHashMap<String, Object>();
636 classGroup.put("@type", "korap:group");
637 classGroup.put("operation", "operation:class");
Joachim Bingel402c6e12014-05-08 17:09:06 +0000638 classGroup.put("class", classRefCounter);
639 classRefCounter++;
Joachim Bingel36233b52014-02-13 10:48:24 +0000640 ArrayList<Object> classOperands = new ArrayList<Object>();
641 classGroup.put("operands", classOperands);
642 distributedOperands.add(classOperands); // subtree to be put into every class group -> distribute
643
644 // put the span and the class group into the position group
Joachim Bingel11d5b152014-02-11 21:33:47 +0000645 posGroup.put("operands", posOperands);
Joachim Bingel36233b52014-02-13 10:48:24 +0000646 LinkedHashMap<String, Object> span = new LinkedHashMap<String, Object>();
647 posOperands.add(span);
648 posOperands.add(classGroup);
649 span.put("@type", "korap:span");
650 span.put("key", c.elem);
Joachim Bingel3f0850c2014-01-17 16:50:10 +0000651 }
Joachim Bingel36233b52014-02-13 10:48:24 +0000652 submatchoperands.add(conjunct);
Joachim Bingele98d0882014-01-21 12:58:54 +0000653 distributedOperandsLists.push(distributedOperands);
Joachim Bingel3f0850c2014-01-17 16:50:10 +0000654 }
Joachim Bingel36233b52014-02-13 10:48:24 +0000655
Joachim Bingeleecc7652014-01-11 17:21:07 +0000656 }
Joachim Bingelb5f7bf02014-01-07 16:36:54 +0000657 objectsToPop.push(stackedObjects);
658
Joachim Bingel87480d02014-01-17 14:07:46 +0000659 /*
660 ****************************************************************
661 ****************************************************************
662 * recursion until 'request' node (root of tree) is processed *
663 ****************************************************************
664 ****************************************************************
665 */
Joachim Bingel5c93f902013-11-19 14:49:04 +0000666 for (int i=0; i<node.getChildCount(); i++) {
667 Tree child = node.getChild(i);
668 processNode(child);
669 }
670
Joachim Bingel87480d02014-01-17 14:07:46 +0000671 /*
672 **************************************************************
673 * Stuff that happens after processing the children of a node *
674 **************************************************************
675 */
676
Joachim Bingeld5161a12014-01-08 11:15:49 +0000677 // remove sequence from object stack if node is implicitly sequenced
678 if (sequencedNodes.size()>0) {
679 if (node == sequencedNodes.getFirst()) {
680 objectStack.pop();
681 sequencedNodes.pop();
682 }
683 }
684
Joachim Bingeleecc7652014-01-11 17:21:07 +0000685 for (int i=0; i<objectsToPop.get(0); i++) {
686 objectStack.pop();
687 }
688 objectsToPop.pop();
689
Joachim Bingel5c93f902013-11-19 14:49:04 +0000690 if (nodeCat.equals("ARG2") && openNodeCats.get(1).equals("OPNOT")) {
691 negate = false;
692 }
693
Joachim Bingel5c93f902013-11-19 14:49:04 +0000694 openNodeCats.pop();
695
696 }
697
Joachim Bingel87480d02014-01-17 14:07:46 +0000698
Joachim Bingelffd65e32014-01-22 14:22:57 +0000699
700
Joachim Bingel402c6e12014-05-08 17:09:06 +0000701 private Object translateMorph(String layer) {
702 LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();
703 map.put("ANA", "pos");
704 if (map.containsKey(layer))
705 return map.get(layer);
706 else
707 return layer;
708 }
709
Joachim Bingel87480d02014-01-17 14:07:46 +0000710 private void parseOPINOptions(Tree node, LinkedHashMap<String, Object> posgroup) {
Joachim Bingelc8a28e42014-04-24 15:06:42 +0000711 Tree posnode = getFirstChildWithCat(node, "POS");
712 Tree rangenode = getFirstChildWithCat(node, "RANGE");
713 Tree exclnode = getFirstChildWithCat(node, "EXCL");
714 Tree groupnode = getFirstChildWithCat(node, "GROUP");
Joachim Bingel87480d02014-01-17 14:07:46 +0000715 boolean negatePosition = false;
716
717 String position = "";
718 if (posnode != null) {
719 String value = posnode.getChild(0).toStringTree();
Joachim Bingel84e33df2014-01-31 14:02:46 +0000720 position = translateTextAreaArgument(value, "in");
Joachim Bingel87480d02014-01-17 14:07:46 +0000721 if (value.equals("N")) {
722 negatePosition = !negatePosition;
723 }
724 } else {
725 position = "contains";
726 }
Joachim Bingel2daf9862014-02-12 10:18:54 +0000727 posgroup.put("frame", "frame:"+position);
Joachim Bingel87480d02014-01-17 14:07:46 +0000728 position = openNodeCats.get(1).equals("OPIN") ? "contains" : "full";
729
730 if (rangenode != null) {
731 String range = rangenode.getChild(0).toStringTree();
732 posgroup.put("range", range.toLowerCase());
733 }
734
735 if (exclnode != null) {
736 if (exclnode.getChild(0).toStringTree().equals("YES")) {
737 negatePosition = !negatePosition;
738 }
739 }
Joachim Bingelba9a0ab2014-01-29 10:12:25 +0000740 System.err.println(negatePosition);
Joachim Bingel87480d02014-01-17 14:07:46 +0000741 if (negatePosition) {
Joachim Bingel11d5b152014-02-11 21:33:47 +0000742 posgroup.put("exclude", "true");
Joachim Bingelba9a0ab2014-01-29 10:12:25 +0000743// negate = !negate;
Joachim Bingel87480d02014-01-17 14:07:46 +0000744 }
745
746 if (groupnode != null) {
Joachim Bingelba9a0ab2014-01-29 10:12:25 +0000747 String grouping = groupnode.getChild(0).toStringTree().equals("max") ? "true" : "false";
Joachim Bingel87480d02014-01-17 14:07:46 +0000748 posgroup.put("grouping", grouping);
749 }
750 }
751
752 private void parseOPOVOptions(Tree node, LinkedHashMap<String, Object> posgroup) {
Joachim Bingelc8a28e42014-04-24 15:06:42 +0000753 Tree posnode = getFirstChildWithCat(node, "POS");
754 Tree exclnode = getFirstChildWithCat(node, "EXCL");
755 Tree groupnode = getFirstChildWithCat(node, "GROUP");
Joachim Bingel87480d02014-01-17 14:07:46 +0000756
757 String position = "";
758 if (posnode != null) {
759 String value = posnode.getChild(0).toStringTree();
Joachim Bingel84e33df2014-01-31 14:02:46 +0000760 position = "-"+translateTextAreaArgument(value, "ov");
Joachim Bingel87480d02014-01-17 14:07:46 +0000761 }
Joachim Bingel2daf9862014-02-12 10:18:54 +0000762 posgroup.put("frame", "frame:"+"overlaps"+position);
Joachim Bingel87480d02014-01-17 14:07:46 +0000763
764 if (exclnode != null) {
765 if (exclnode.getChild(0).toStringTree().equals("YES")) {
Joachim Bingelee3b21d2014-02-12 12:34:59 +0000766 posgroup.put("match", "match:"+"ne");
Joachim Bingel87480d02014-01-17 14:07:46 +0000767 }
768 }
769 if (groupnode != null) {
Joachim Bingelba9a0ab2014-01-29 10:12:25 +0000770 String grouping = groupnode.getChild(0).toStringTree().equals("@max") ? "true" : "false";
Joachim Bingel87480d02014-01-17 14:07:46 +0000771 posgroup.put("grouping", grouping);
772 }
773
774 }
775
776 /**
Joachim Bingel36233b52014-02-13 10:48:24 +0000777 * Translates the text area specifications (position option arguments) to terms used in serialisation.
Joachim Bingel87480d02014-01-17 14:07:46 +0000778 * For the allowed argument types and their values for OPIN and OPOV, see
779 * http://www.ids-mannheim.de/cosmas2/win-app/hilfe/suchanfrage/eingabe-grafisch/syntax/ARGUMENT_I.html or
780 * http://www.ids-mannheim.de/cosmas2/win-app/hilfe/suchanfrage/eingabe-grafisch/syntax/ARGUMENT_O.html, respectively.
781 * @param argument
Joachim Bingel84e33df2014-01-31 14:02:46 +0000782 * @param mode
Joachim Bingel87480d02014-01-17 14:07:46 +0000783 * @return
784 */
Joachim Bingel84e33df2014-01-31 14:02:46 +0000785 private String translateTextAreaArgument(String argument, String mode) {
Joachim Bingel87480d02014-01-17 14:07:46 +0000786 String position = "";
787 switch (argument) {
788 case "L":
Joachim Bingel84e33df2014-01-31 14:02:46 +0000789 position = mode.equals("in") ? "startswith" : "left";
Joachim Bingel87480d02014-01-17 14:07:46 +0000790 break;
791 case "R":
Joachim Bingel84e33df2014-01-31 14:02:46 +0000792 position = mode.equals("in") ? "endswith" : "right";
Joachim Bingel87480d02014-01-17 14:07:46 +0000793 break;
794 case "F":
795 position = "leftrightmatch";
796 break;
797 case "FE":
Joachim Bingel84e33df2014-01-31 14:02:46 +0000798 position = "matches";
Joachim Bingel87480d02014-01-17 14:07:46 +0000799 break;
800 case "FI":
801 position = "leftrightmatch-noident";
802 break;
803 case "N": // for OPIN only - exclusion constraint formulated in parseOPINOptions
804 position = "leftrightmatch";
805 break;
806 case "X": // for OPOV only
807 position = "residual";
808 break;
809 }
810 return position;
811 }
812
Joachim Bingelcc1dc242014-01-15 09:32:38 +0000813 @SuppressWarnings("unchecked")
814 private void putIntoSuperObject(LinkedHashMap<String, Object> object, int objStackPosition) {
Joachim Bingele98d0882014-01-21 12:58:54 +0000815 if (distributedOperandsLists.size()>0) {
816 ArrayList<ArrayList<Object>> distributedOperands = distributedOperandsLists.pop();
817 for (ArrayList<Object> operands : distributedOperands) {
818 operands.add(object);
819 }
820 } else if (objectStack.size()>objStackPosition) {
Joachim Bingel11d5b152014-02-11 21:33:47 +0000821 ArrayList<Object> topObjectOperands = (ArrayList<Object>) objectStack.get(objStackPosition).get("operands");
Joachim Bingelcc1dc242014-01-15 09:32:38 +0000822 if (!invertedOperandsLists.contains(topObjectOperands)) {
823 topObjectOperands.add(object);
824 } else {
825 topObjectOperands.add(0, object);
826 }
827
828 } else {
829 requestMap.put("query", object);
830 }
831 }
832
833 private void putIntoSuperObject(LinkedHashMap<String, Object> object) {
834 putIntoSuperObject(object, 0);
835 }
Joachim Bingel5c93f902013-11-19 14:49:04 +0000836
Joachim Bingelb5f7bf02014-01-07 16:36:54 +0000837
Joachim Bingelc8a28e42014-04-24 15:06:42 +0000838 private Tree parseCosmasQuery(String q) throws RecognitionException {
Joachim Bingel81812632014-02-18 08:55:22 +0000839 Pattern p = Pattern.compile("(\\w+):((\\+|-)?(sa|se|pa|pe|ta|te),?)+");
840 Matcher m = p.matcher(q);
841
842 String rewrittenQuery = q;
843 while (m.find()) {
844 String match = m.group();
845 String conditionsString = match.split(":")[1];
846 Pattern conditionPattern = Pattern.compile("(\\+|-)?(sa|se|pa|pe|ta|te)");
847 Matcher conditionMatcher = conditionPattern.matcher(conditionsString);
848 String replacement = "#BED("+m.group(1)+" , ";
849 while (conditionMatcher.find()) {
850 replacement = replacement+conditionMatcher.group()+",";
851 }
852 replacement = replacement.substring(0, replacement.length()-1)+")"; //remove trailing comma and close parenthesis
853 System.out.println(replacement);
854 rewrittenQuery = rewrittenQuery.replace(match, replacement);
855 }
856 q = rewrittenQuery;
Joachim Bingel5c93f902013-11-19 14:49:04 +0000857 Tree tree = null;
Joachim Bingel81812632014-02-18 08:55:22 +0000858 ANTLRStringStream ss = new ANTLRStringStream(q);
Joachim Bingel87480d02014-01-17 14:07:46 +0000859 c2psLexer lex = new c2psLexer(ss);
860 org.antlr.runtime.CommonTokenStream tokens = new org.antlr.runtime.CommonTokenStream(lex); //v3
Joachim Bingelc8a28e42014-04-24 15:06:42 +0000861 parser = new c2psParser(tokens);
862 c2psParser.c2ps_query_return c2Return = ((c2psParser) parser).c2ps_query(); // statt t().
Joachim Bingel5c93f902013-11-19 14:49:04 +0000863 // AST Tree anzeigen:
864 tree = (Tree)c2Return.getTree();
Joachim Bingel87480d02014-01-17 14:07:46 +0000865
866 String treestring = tree.toStringTree();
867 if (treestring.contains("<mismatched token") || treestring.contains("<error") || treestring.contains("<unexpected")) {
868 throw new RecognitionException();
869 }
Joachim Bingel5c93f902013-11-19 14:49:04 +0000870 return tree;
871 }
872
873 /**
874 * @param args
875 */
876 public static void main(String[] args) {
877 /*
Joachim Bingel87480d02014-01-17 14:07:46 +0000878 * For debugging
Joachim Bingel5c93f902013-11-19 14:49:04 +0000879 */
880 String[] queries = new String[] {
881 /* COSMAS 2 */
Joachim Bingel8c640e42014-02-07 16:20:47 +0000882// "MORPH(V)",
883// "MORPH(V PRES)",
884// "wegen #IN(%, L) <s>",
885// "wegen #IN(%) <s>",
886// "(Mann oder Frau) #IN <s>",
887// "#BEG(der /w3:5 Mann) /+w10 kommt",
888// "&würde /w0 MORPH(V)",
Joachim Bingel81812632014-02-18 08:55:22 +0000889// "#NHIT(gehen /w1:10 voran)",
890// "#BED(der Mann , sa,-pa)",
891// "Mann /t0 Frau",
892 "sagt der:sa Bundeskanzler",
893// "Der:sa,-pe,+te ",
Joachim Bingel402c6e12014-05-08 17:09:06 +0000894 "#ELEM(W POS!='N V' title=tada)",
895 "#ELEM(W ANA != 'N V')"
896// "(&Baum #IN #ELEM(NP)) #IN(L) #ELEM(S)"
Joachim Bingel5c93f902013-11-19 14:49:04 +0000897 };
Joachim Bingel5dd91682014-02-14 13:10:29 +0000898// CosmasTree.debug=true;
Joachim Bingel5c93f902013-11-19 14:49:04 +0000899 for (String q : queries) {
900 try {
901 System.out.println(q);
Joachim Bingel87480d02014-01-17 14:07:46 +0000902 try {
Joachim Bingel87480d02014-01-17 14:07:46 +0000903 CosmasTree act = new CosmasTree(q);
Joachim Bingel402c6e12014-05-08 17:09:06 +0000904 System.out.println(act.parseCosmasQuery(q).toStringTree());
Joachim Bingel87480d02014-01-17 14:07:46 +0000905 } catch (QueryException e) {
906 e.printStackTrace();
Joachim Bingel402c6e12014-05-08 17:09:06 +0000907 } catch (RecognitionException e) {
908 e.printStackTrace();
Joachim Bingel87480d02014-01-17 14:07:46 +0000909 }
Joachim Bingel5c93f902013-11-19 14:49:04 +0000910 System.out.println();
911
912 } catch (NullPointerException npe) {
913 npe.printStackTrace();
914 System.out.println("null\n");
915 }
916 }
917 }
918}