layer mapping for query serializations!
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/CosmasTree.java b/src/main/java/de/ids_mannheim/korap/query/serialize/CosmasTree.java
index 29ae40b..3aa9322 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/CosmasTree.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/CosmasTree.java
@@ -1,14 +1,10 @@
package de.ids_mannheim.korap.query.serialize;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
+import de.ids_mannheim.korap.query.cosmas2.c2psLexer;
+import de.ids_mannheim.korap.query.cosmas2.c2psParser;
+import de.ids_mannheim.korap.query.serialize.util.CosmasCondition;
+import de.ids_mannheim.korap.query.serialize.util.ResourceMapper;
+import de.ids_mannheim.korap.util.QueryException;
import org.antlr.runtime.ANTLRStringStream;
import org.antlr.runtime.RecognitionException;
import org.antlr.runtime.tree.Tree;
@@ -16,250 +12,251 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import de.ids_mannheim.korap.query.cosmas2.c2psLexer;
-import de.ids_mannheim.korap.query.cosmas2.c2psParser;
-import de.ids_mannheim.korap.query.serialize.util.CosmasCondition;
-import de.ids_mannheim.korap.util.QueryException;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
/**
* Map representation of CosmasII syntax tree as returned by ANTLR
- * @author joachim
*
+ * @author joachim
*/
public class CosmasTree extends Antlr3AbstractSyntaxTree {
-
- private static Logger log = LoggerFactory.getLogger(CosmasTree.class);
-
- /*
- * Following collections have the following functions:
- * - the request is a map with two keys (meta/query): {meta=[], query=[]}
- * - the query is a list of token group maps: {meta=[], query=[tg1=[], tg2=[]]}
- * - each token group is a list of tokens: {meta=[], query=[tg1=[t1_1, t1_2], tg2=[t2_1, t2_2, t2_3]]}
- * - each token corresponds to a single 'fields' linked list {meta=[], query=[tg1=[t1_1=[], t1_2=[]], ... ]}
- * - each fields list contains a logical operator and 'field maps' defining attributes and values
- * {meta=[], query=[tg1=[t1_1=[[disj, {base=foo}, {base=bar}]], t1_2=[]], ... ]}
- */
- String query;
- LinkedHashMap<String,Object> requestMap = new LinkedHashMap<String,Object>();
- /**
- * Keeps track of active object.
- */
- LinkedList<LinkedHashMap<String,Object>> objectStack = new LinkedList<LinkedHashMap<String,Object>>();
- /**
- * Makes it possible to store several distantTokenGroups
- */
- LinkedList<ArrayList<List<Object>>> distantTokensStack = new LinkedList<ArrayList<List<Object>>>();
- /**
- * Field for repetition query (Kleene + or * operations, or min/max queries: {2,4}
- */
- String repetition = "";
- /**
- * Keeps track of open node categories
- */
- LinkedList<String> openNodeCats = new LinkedList<String>();
- /**
- * Global control structure for fieldGroups, keeps track of open fieldGroups.
- */
- LinkedList<ArrayList<Object>> openFieldGroups = new LinkedList<ArrayList<Object>>();
- /**
- * Keeps track of how many objects there are to pop after every recursion of {@link #processNode(ParseTree)}
- */
- LinkedList<Integer> objectsToPop = new LinkedList<Integer>();
- /**
- * Flag that indicates whether token fields or meta fields are currently being processed
- */
- boolean inMeta = false;
- /**
- *
- */
- int classRefCounter = 1;
- boolean negate = false;
-
- Tree cosmasTree;
-
- LinkedHashMap<String,Object> treeMap = new LinkedHashMap<String,Object>();
- /**
- * Keeps track of all visited nodes in a tree
- */
- List<Tree> visited = new ArrayList<Tree>();
- Integer stackedObjects = 0;
-
- private static boolean debug = false;
- /**
- * 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)
- */
- private final List<String> sequentiableCats = Arrays.asList(new String[] {"OPWF", "OPLEM", "OPMORPH", "OPBEG", "OPEND", "OPIN", "OPBED"});
- /**
- * Keeps track of sequenced nodes, i.e. nodes that implicitly govern a sequence, as in (C2PQ (OPWF der) (OPWF Mann)).
- * This is necessary in order to know when to take the sequence off the object stack, as the sequence is introduced by the
- * first child but cannot be closed after this first child in order not to lose its siblings
- */
- private LinkedList<Tree> sequencedNodes = new LinkedList<Tree>();
+ private static Logger log = LoggerFactory.getLogger(CosmasTree.class);
- private boolean hasSequentiableSiblings;
+ /*
+ * Following collections have the following functions:
+ * - the request is a map with two keys (meta/query): {meta=[], query=[]}
+ * - the query is a list of token group maps: {meta=[], query=[tg1=[], tg2=[]]}
+ * - each token group is a list of tokens: {meta=[], query=[tg1=[t1_1, t1_2], tg2=[t2_1, t2_2, t2_3]]}
+ * - each token corresponds to a single 'fields' linked list {meta=[], query=[tg1=[t1_1=[], t1_2=[]], ... ]}
+ * - each fields list contains a logical operator and 'field maps' defining attributes and values
+ * {meta=[], query=[tg1=[t1_1=[[disj, {base=foo}, {base=bar}]], t1_2=[]], ... ]}
+ */
+ String query;
+ LinkedHashMap<String, Object> requestMap = new LinkedHashMap<String, Object>();
+ /**
+ * Keeps track of active object.
+ */
+ LinkedList<LinkedHashMap<String, Object>> objectStack = new LinkedList<LinkedHashMap<String, Object>>();
+ /**
+ * Makes it possible to store several distantTokenGroups
+ */
+ LinkedList<ArrayList<List<Object>>> distantTokensStack = new LinkedList<ArrayList<List<Object>>>();
+ /**
+ * Field for repetition query (Kleene + or * operations, or min/max queries: {2,4}
+ */
+ String repetition = "";
+ /**
+ * Keeps track of open node categories
+ */
+ LinkedList<String> openNodeCats = new LinkedList<String>();
+ /**
+ * Global control structure for fieldGroups, keeps track of open fieldGroups.
+ */
+ LinkedList<ArrayList<Object>> openFieldGroups = new LinkedList<ArrayList<Object>>();
+ /**
+ * Keeps track of how many objects there are to pop after every recursion of {@link #processNode(ParseTree)}
+ */
+ LinkedList<Integer> objectsToPop = new LinkedList<Integer>();
+ /**
+ * Flag that indicates whether token fields or meta fields are currently being processed
+ */
+ boolean inMeta = false;
+ /**
+ *
+ */
+ int classRefCounter = 1;
+ boolean negate = false;
- /**
- * Keeps track of operands lists that are to be serialised in an inverted
- * order (e.g. the IN() operator) compared to their AST representation.
- */
- private LinkedList<ArrayList<Object>> invertedOperandsLists = new LinkedList<ArrayList<Object>>();
-
- private LinkedList<ArrayList<ArrayList<Object>>> distributedOperandsLists = new LinkedList<ArrayList<ArrayList<Object>>>();
- /**
- *
- * @param tree The syntax tree as returned by ANTLR
- * @param parser The ANTLR parser instance that generated the parse tree
- * @throws QueryException
- */
- public CosmasTree(String query) throws QueryException {
- this.query = query;
- process(query);
- System.out.println("\n"+requestMap.get("query"));
- log.info(">>> " + requestMap.get("query") + " <<<");
- }
-
- @Override
- public Map<String, Object> getRequestMap() {
- return this.requestMap;
- }
-
-
-
- @Override
- public void process(String query) throws QueryException {
- Tree tree = null;
- try {
- tree = parseCosmasQuery(query);
- } catch (RecognitionException e) {
- throw new QueryException("Your query could not be processed. Please make sure it is well-formed.");
- } catch (NullPointerException e) {
- throw new QueryException("Your query could not be processed. Please make sure it is well-formed.");
- }
- log.info("Processing CosmasII query");
- System.out.println("Processing Cosmas");
- requestMap.put("@context", "http://ids-mannheim.de/ns/KorAP/json-ld/v0.1/context.jsonld");
+ Tree cosmasTree;
+
+ LinkedHashMap<String, Object> treeMap = new LinkedHashMap<String, Object>();
+ /**
+ * Keeps track of all visited nodes in a tree
+ */
+ List<Tree> visited = new ArrayList<Tree>();
+
+ Integer stackedObjects = 0;
+
+ private static boolean debug = false;
+ /**
+ * 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)
+ */
+ private final List<String> sequentiableCats = Arrays.asList(new String[]{"OPWF", "OPLEM", "OPMORPH", "OPBEG", "OPEND", "OPIN", "OPBED"});
+ /**
+ * Keeps track of sequenced nodes, i.e. nodes that implicitly govern a sequence, as in (C2PQ (OPWF der) (OPWF Mann)).
+ * This is necessary in order to know when to take the sequence off the object stack, as the sequence is introduced by the
+ * first child but cannot be closed after this first child in order not to lose its siblings
+ */
+ private LinkedList<Tree> sequencedNodes = new LinkedList<Tree>();
+
+ private boolean hasSequentiableSiblings;
+
+ /**
+ * Keeps track of operands lists that are to be serialised in an inverted
+ * order (e.g. the IN() operator) compared to their AST representation.
+ */
+ private LinkedList<ArrayList<Object>> invertedOperandsLists = new LinkedList<ArrayList<Object>>();
+
+ private LinkedList<ArrayList<ArrayList<Object>>> distributedOperandsLists = new LinkedList<ArrayList<ArrayList<Object>>>();
+
+ /**
+ * @param tree The syntax tree as returned by ANTLR
+ * @param parser The ANTLR parser instance that generated the parse tree
+ * @throws QueryException
+ */
+ public CosmasTree(String query) throws QueryException {
+ this.query = query;
+ process(query);
+ System.out.println("\n" + requestMap.get("query"));
+ log.info(">>> " + requestMap.get("query") + " <<<");
+ }
+
+ @Override
+ public Map<String, Object> getRequestMap() {
+ return this.requestMap;
+ }
+
+
+ @Override
+ public void process(String query) throws QueryException {
+ Tree tree = null;
+ try {
+ tree = parseCosmasQuery(query);
+ } catch (RecognitionException e) {
+ throw new QueryException("Your query could not be processed. Please make sure it is well-formed.");
+ } catch (NullPointerException e) {
+ throw new QueryException("Your query could not be processed. Please make sure it is well-formed.");
+ }
+ log.info("Processing CosmasII query");
+ System.out.println("Processing Cosmas");
+ requestMap.put("@context", "http://ids-mannheim.de/ns/KorAP/json-ld/v0.1/context.jsonld");
// prepareContext(requestMap);
- processNode(tree);
- log.info(requestMap.toString());
- }
-
- @SuppressWarnings("unchecked")
- private void processNode(Tree node) {
-
- // Top-down processing
- if (visited.contains(node)) return;
- else visited.add(node);
-
-
- String nodeCat = getNodeCat(node);
- openNodeCats.push(nodeCat);
-
- stackedObjects = 0;
-
- if (debug) {
- System.err.println(" "+objectStack);
- System.out.println(openNodeCats);
- }
-
+ processNode(tree);
+ log.info(requestMap.toString());
+ }
+
+ @SuppressWarnings("unchecked")
+ private void processNode(Tree node) {
+
+ // Top-down processing
+ if (visited.contains(node)) return;
+ else visited.add(node);
+
+
+ String nodeCat = getNodeCat(node);
+ openNodeCats.push(nodeCat);
+
+ stackedObjects = 0;
+
+ if (debug) {
+ System.err.println(" " + objectStack);
+ System.out.println(openNodeCats);
+ }
+
/* ***************************************
- * Processing individual node categories *
+ * Processing individual node categories *
*****************************************/
-
- // Check for potential implicit sequences as in (C2PQ (OPWF der) (OPWF Mann)). The sequence is introduced
- // by the first child if it (and its siblings) is sequentiable.
- if (sequentiableCats.contains(nodeCat)) {
- // for each node, check if parent has more than one child (-> could be implicit sequence)
- Tree parent = node.getParent();
- if (parent.getChildCount()>1) {
- // if node is first child of parent...
- if (node == parent.getChild(0)) {
- hasSequentiableSiblings = false;
- for (int i=1; i<parent.getChildCount() ;i++) {
- if (sequentiableCats.contains(getNodeCat(parent.getChild(i)))) {
- hasSequentiableSiblings = true;
- continue;
- }
- }
- if (hasSequentiableSiblings) {
- // Step I: create sequence
- LinkedHashMap<String, Object> sequence = new LinkedHashMap<String, Object>();
- sequence.put("@type", "korap:group");
- sequence.put("operation", "operation:sequence");
- sequence.put("operands", new ArrayList<Object>());
- // push sequence on object stack but don't increment stackedObjects counter since
- // we've got to wait until the parent node is processed - therefore, add the parent
- // to the sequencedNodes list and remove the sequence from the stack when the parent
- // has been processed
- objectStack.push(sequence);
- sequencedNodes.push(parent);
- // Step II: decide where to put sequence
- putIntoSuperObject(sequence, 1);
- }
- }
- }
- }
-
- // Nodes introducing tokens. Process all in the same manner, except for the fieldMap entry
- if (nodeCat.equals("OPWF") || nodeCat.equals("OPLEM")) {
-
- //Step I: get info
- LinkedHashMap<String, Object> token = new LinkedHashMap<String, Object>();
- token.put("@type", "korap:token");
- objectStack.push(token);
- stackedObjects++;
- LinkedHashMap<String, Object> fieldMap = new LinkedHashMap<String, Object>();
- token.put("wrap", fieldMap);
-
- fieldMap.put("@type", "korap:term");
- // make category-specific fieldMap entry
- String attr = nodeCat.equals("OPWF") ? "orth" : "lemma";
- String value = node.getChild(0).toStringTree().replaceAll("\"", "");
- if (value.startsWith("$")) {
- value = value.substring(1);
- fieldMap.put("caseInsensitive", true);
- }
- fieldMap.put("key", value);
- fieldMap.put("layer", attr);
-
- // negate field (see above)
- if (negate) {
- fieldMap.put("match", "match:ne");
- } else {
- fieldMap.put("match", "match:eq");
- }
- //Step II: decide where to put
- if (! hasChild(node, "TPOS")) {
- putIntoSuperObject(token, 1);
- } else {
-
- }
-
- }
-
- if (nodeCat.equals("OPMORPH")) {
- //Step I: get info
- LinkedHashMap<String, Object> token = new LinkedHashMap<String, Object>();
- token.put("@type", "korap:token");
- LinkedHashMap<String, Object> fieldMap = new LinkedHashMap<String, Object>();
- token.put("wrap", fieldMap);
-
- fieldMap.put("@type", "korap:term");
+
+ // Check for potential implicit sequences as in (C2PQ (OPWF der) (OPWF Mann)). The sequence is introduced
+ // by the first child if it (and its siblings) is sequentiable.
+ if (sequentiableCats.contains(nodeCat)) {
+ // for each node, check if parent has more than one child (-> could be implicit sequence)
+ Tree parent = node.getParent();
+ if (parent.getChildCount() > 1) {
+ // if node is first child of parent...
+ if (node == parent.getChild(0)) {
+ hasSequentiableSiblings = false;
+ for (int i = 1; i < parent.getChildCount(); i++) {
+ if (sequentiableCats.contains(getNodeCat(parent.getChild(i)))) {
+ hasSequentiableSiblings = true;
+ continue;
+ }
+ }
+ if (hasSequentiableSiblings) {
+ // Step I: create sequence
+ LinkedHashMap<String, Object> sequence = new LinkedHashMap<String, Object>();
+ sequence.put("@type", "korap:group");
+ sequence.put("operation", "operation:sequence");
+ sequence.put("operands", new ArrayList<Object>());
+ // push sequence on object stack but don't increment stackedObjects counter since
+ // we've got to wait until the parent node is processed - therefore, add the parent
+ // to the sequencedNodes list and remove the sequence from the stack when the parent
+ // has been processed
+ objectStack.push(sequence);
+ sequencedNodes.push(parent);
+ // Step II: decide where to put sequence
+ putIntoSuperObject(sequence, 1);
+ }
+ }
+ }
+ }
+
+ // Nodes introducing tokens. Process all in the same manner, except for the fieldMap entry
+ if (nodeCat.equals("OPWF") || nodeCat.equals("OPLEM")) {
+
+ //Step I: get info
+ LinkedHashMap<String, Object> token = new LinkedHashMap<String, Object>();
+ token.put("@type", "korap:token");
+ objectStack.push(token);
+ stackedObjects++;
+ LinkedHashMap<String, Object> fieldMap = new LinkedHashMap<String, Object>();
+ token.put("wrap", fieldMap);
+
+ fieldMap.put("@type", "korap:term");
+ // make category-specific fieldMap entry
+ String attr = nodeCat.equals("OPWF") ? "orth" : "lemma";
+ String value = node.getChild(0).toStringTree().replaceAll("\"", "");
+ if (value.startsWith("$")) {
+ value = value.substring(1);
+ fieldMap.put("caseInsensitive", true);
+ }
+
+ attr = ResourceMapper.descriptor2policy(attr);
+ fieldMap.put("key", value);
+ fieldMap.put("layer", attr);
+
+ // negate field (see above)
+ if (negate) {
+ fieldMap.put("match", "match:ne");
+ } else {
+ fieldMap.put("match", "match:eq");
+ }
+ //Step II: decide where to put
+ if (!hasChild(node, "TPOS")) {
+ putIntoSuperObject(token, 1);
+ } else {
+
+ }
+
+ }
+
+ if (nodeCat.equals("OPMORPH")) {
+ //Step I: get info
+ LinkedHashMap<String, Object> token = new LinkedHashMap<String, Object>();
+ token.put("@type", "korap:token");
+ LinkedHashMap<String, Object> fieldMap = new LinkedHashMap<String, Object>();
+ token.put("wrap", fieldMap);
+
+ fieldMap.put("@type", "korap:term");
// fieldMap.put("key", "morph:"+node.getChild(0).toString().replace(" ", "_"));
- String[] morphValues = node.getChild(0).toString().split(" ");
- String pos = morphValues[0];
-
- fieldMap.put("key", pos);
- fieldMap.put("layer", "pos");
- // make category-specific fieldMap entry
- // negate field (see above)
- if (negate) {
- fieldMap.put("match", "match:ne");
- } else {
- fieldMap.put("match", "match:eq");
- }
+ String[] morphValues = node.getChild(0).toString().split(" ");
+ String pos = morphValues[0];
+
+ fieldMap.put("key", pos);
+
+ fieldMap.put("layer", ResourceMapper.descriptor2policy("pos"));
+ // make category-specific fieldMap entry
+ // negate field (see above)
+ if (negate) {
+ fieldMap.put("match", "match:ne");
+ } else {
+ fieldMap.put("match", "match:eq");
+ }
// List<String> morphValues = parseMorph(node.getChild(0).toStringTree());
// System.err.println(morphValues);
// if (morphValues.size() == 1) {
@@ -297,27 +294,27 @@
// }
// }
// }
-
-
- //Step II: decide where to put
- putIntoSuperObject(token, 0);
- }
-
- if (nodeCat.equals("OPELEM")) {
- // Step I: create element
- LinkedHashMap<String, Object> elem = new LinkedHashMap<String, Object>();
- elem.put("@type", "korap:span");
- if (node.getChild(0).toStringTree().equals("EMPTY")) {
-
- } else {
- int elname = 0;
- Tree elnameNode = getFirstChildWithCat(node, "ELNAME");
- if (elnameNode != null) {
- elem.put("key", elnameNode.getChild(0).toStringTree().toLowerCase());
- elname = 1;
- }
- if (node.getChildCount() > elname) {
- /*
+
+
+ //Step II: decide where to put
+ putIntoSuperObject(token, 0);
+ }
+
+ if (nodeCat.equals("OPELEM")) {
+ // Step I: create element
+ LinkedHashMap<String, Object> elem = new LinkedHashMap<String, Object>();
+ elem.put("@type", "korap:span");
+ if (node.getChild(0).toStringTree().equals("EMPTY")) {
+
+ } else {
+ int elname = 0;
+ Tree elnameNode = getFirstChildWithCat(node, "ELNAME");
+ if (elnameNode != null) {
+ elem.put("key", elnameNode.getChild(0).toStringTree().toLowerCase());
+ elname = 1;
+ }
+ if (node.getChildCount() > elname) {
+ /*
* Attributes can carry several values, like #ELEM(W ANA != 'N V'),
* denoting a word whose POS is neither N nor V.
* When seeing this, create a sub-termGroup and put it into the top-level
@@ -326,368 +323,370 @@
* top-level group (in order to avoid a top-level group that only
* contains a sub-group).
*/
- LinkedHashMap<String, Object> termGroup = makeTermGroup("and");
- ArrayList<Object> termGroupOperands = (ArrayList<Object>) termGroup.get("operands");
- for (int i=elname; i<node.getChildCount(); i++) {
- Tree attrNode = node.getChild(i);
- if (attrNode.getChildCount()==2) {
- LinkedHashMap<String, Object> term = makeTerm();
- termGroupOperands.add(term);
- String layer = attrNode.getChild(0).toStringTree();
- String[] splitted = layer.split("/");
- if (splitted.length > 1) {
- term.put("foundry", splitted[0]);
- layer = splitted[1];
- }
- term.put("layer", translateMorph(layer));
- term.put("key", attrNode.getChild(1).toStringTree());
- String match = getNodeCat(attrNode).equals("EQ") ? "eq" : "ne";
- term.put("match", "match:"+match);
- } else {
- LinkedHashMap<String, Object> subTermGroup = makeTermGroup("and");
- ArrayList<Object> subTermGroupOperands = (ArrayList<Object>) subTermGroup.get("operands");
- int j;
- for (j=1; j<attrNode.getChildCount(); j++) {
- LinkedHashMap<String, Object> term = makeTerm();
- String layer = attrNode.getChild(0).toStringTree();
- String[] splitted = layer.split("/");
- if (splitted.length > 1) {
- term.put("foundry", splitted[0]);
- layer = splitted[1];
- }
- term.put("layer", translateMorph(layer));
- term.put("key", attrNode.getChild(j).toStringTree());
- String match = getNodeCat(attrNode).equals("EQ") ? "eq" : "ne";
- term.put("match", "match:"+match);
- if (node.getChildCount()==elname+1) {
- termGroupOperands.add(term);
- System.err.println("taga");
- } else {
- subTermGroupOperands.add(term);
- System.err.println(layer);
- }
- }
- if (node.getChildCount()>elname+1) {
- System.err.println(termGroupOperands);
- termGroupOperands.add(subTermGroup);
- System.err.println(termGroupOperands);
- }
- }
- if (getNodeCat(attrNode).equals("NOTEQ")) negate=true;
- }
- elem.put("attr", termGroup);
- }
- }
-
- //Step II: decide where to put
- putIntoSuperObject(elem);
- }
-
- if (nodeCat.equals("OPLABEL")) {
- // Step I: create element
- LinkedHashMap<String, Object> elem = new LinkedHashMap<String, Object>();
- elem.put("@type", "korap:span");
- elem.put("key", node.getChild(0).toStringTree().replaceAll("<|>", ""));
- //Step II: decide where to put
- putIntoSuperObject(elem);
- }
-
- if (nodeCat.equals("OPAND") || nodeCat.equals("OPNOT")) {
- // Step I: create group
- LinkedHashMap<String, Object> distgroup = new LinkedHashMap<String, Object>();
- distgroup.put("@type", "korap:group");
- distgroup.put("operation", "operation:sequence");
- ArrayList<Object> distances = new ArrayList<Object>();
- LinkedHashMap<String, Object> zerodistance = new LinkedHashMap<String, Object>();
- zerodistance.put("@type", "korap:distance");
- zerodistance.put("key", "t");
- zerodistance.put("min", 0);
- zerodistance.put("max", 0);
- if (nodeCat.equals("OPNOT")) zerodistance.put("exclude", true);
- distances.add(zerodistance);
- distgroup.put("distances", distances);
- distgroup.put("operands", new ArrayList<Object>());
- objectStack.push(distgroup);
- stackedObjects++;
- // Step II: decide where to put
- putIntoSuperObject(distgroup, 1);
- }
-
- if (nodeCat.equals("OPOR")) {
- // Step I: create group
- LinkedHashMap<String, Object> disjunction = new LinkedHashMap<String, Object>();
- disjunction.put("@type", "korap:group");
- disjunction.put("operation", "operation:or");
- disjunction.put("operands", new ArrayList<Object>());
- objectStack.push(disjunction);
- stackedObjects++;
- // Step II: decide where to put
- putIntoSuperObject(disjunction, 1);
- }
-
- if (nodeCat.equals("OPPROX")) {
- //TODO direction "both": wrap in "or" group with operands once flipped, once not
- // collect info
- Tree prox_opts = node.getChild(0);
- Tree typ = prox_opts.getChild(0);
- Tree dist_list = prox_opts.getChild(1);
- // Step I: create group
- LinkedHashMap<String, Object> proxSequence = new LinkedHashMap<String, Object>();
- proxSequence.put("@type", "korap:group");
- proxSequence.put("operation", "operation:"+ "sequence");
- objectStack.push(proxSequence);
- stackedObjects++;
- ArrayList<Object> constraints = new ArrayList<Object>();
- boolean exclusion = ! typ.getChild(0).toStringTree().equals("PROX");
-
- boolean inOrder = false;
- proxSequence.put("inOrder", inOrder);
- proxSequence.put("distances", constraints);
-
- ArrayList<Object> operands = new ArrayList<Object>();
- proxSequence.put("operands", operands);
-
- // possibly several distance constraints
- for (int i=0; i<dist_list.getChildCount(); i++) {
- String direction = dist_list.getChild(i).getChild(0).getChild(0).toStringTree().toLowerCase();
- String min = dist_list.getChild(i).getChild(1).getChild(0).toStringTree();
- String max = dist_list.getChild(i).getChild(1).getChild(1).toStringTree();
- String meas = dist_list.getChild(i).getChild(2).getChild(0).toStringTree();
- if (min.equals("VAL0")) {
- min="0";
- }
- LinkedHashMap<String, Object> distance = new LinkedHashMap<String, Object>();
- distance.put("@type", "korap:distance");
- distance.put("key", meas);
- distance.put("min", Integer.parseInt(min));
- distance.put("max", Integer.parseInt(max));
- if (exclusion) {
- distance.put("exclude", exclusion);
- }
- constraints.add(distance);
- if (direction.equals("plus")) {
- inOrder=true;
- } else if (direction.equals("minus")) {
- inOrder=true;
- invertedOperandsLists.add(operands);
- }
- }
- proxSequence.put("inOrder", inOrder);
- // Step II: decide where to put
- putIntoSuperObject(proxSequence, 1);
- }
-
- // inlcusion or overlap
- if (nodeCat.equals("OPIN") || nodeCat.equals("OPOV")) {
- // Step I: create group
- LinkedHashMap<String, Object> submatchgroup = new LinkedHashMap<String, Object>();
- submatchgroup.put("@type", "korap:group");
- submatchgroup.put("operation", "operation:"+ "submatch");
- ArrayList<Integer> classRef = new ArrayList<Integer>();
- classRef.add(classRefCounter);
- submatchgroup.put("classRef", classRef);
-
- ArrayList<Object> submatchoperands = new ArrayList<Object>();
- LinkedHashMap<String, Object> posgroup = new LinkedHashMap<String, Object>();
- submatchgroup.put("operands", submatchoperands);
- submatchoperands.add(posgroup);
- posgroup.put("@type", "korap:group");
-// String relation = nodeCat.equals("OPIN") ? "position" : "overlaps";
- posgroup.put("operation", "operation:"+ "position");
- if (nodeCat.equals("OPIN")) {
- parseOPINOptions(node, posgroup);
- } else {
- parseOPOVOptions(node, posgroup);
- }
- ArrayList<Object> posoperands = new ArrayList<Object>();
- posgroup.put("operands", posoperands);
- objectStack.push(posgroup);
- // mark this an inverted list
- invertedOperandsLists.push(posoperands);
- stackedObjects++;
- // Step II: decide where to put
- putIntoSuperObject(submatchgroup, 1);
- }
-
-
- // Wrap the first argument of an #IN operator in a class group
- if (nodeCat.equals("ARG1") && (openNodeCats.get(1).equals("OPIN") || openNodeCats.get(1).equals("OPOV") || openNodeCats.get(2).equals("OPNHIT"))) {
- // Step I: create group
- LinkedHashMap<String, Object> classGroup = new LinkedHashMap<String, Object>();
- classGroup.put("@type", "korap:group");
- classGroup.put("operation", "operation:"+ "class");
- classGroup.put("class", classRefCounter);
- classRefCounter++;
- classGroup.put("operands", new ArrayList<Object>());
- objectStack.push(classGroup);
- stackedObjects++;
- // Step II: decide where to put
- putIntoSuperObject(classGroup, 1);
- }
-
- // Wrap the 2nd argument of an #IN operator embedded in NHIT in a class group
- if (nodeCat.equals("ARG2") && openNodeCats.get(2).equals("OPNHIT")) {
- // Step I: create group
- LinkedHashMap<String, Object> classGroup = new LinkedHashMap<String, Object>();
- classGroup.put("@type", "korap:group");
- classGroup.put("operation", "operation:"+ "class");
- classGroup.put("class", classRefCounter);
- classRefCounter++;
- classGroup.put("operands", new ArrayList<Object>());
- objectStack.push(classGroup);
- stackedObjects++;
- // Step II: decide where to put
- putIntoSuperObject(classGroup, 1);
- }
-
-
- if (nodeCat.equals("OPNHIT")) {
- LinkedHashMap<String, Object> exclGroup = new LinkedHashMap<String, Object>();
- exclGroup.put("@type", "korap:group");
- exclGroup.put("operation", "operation:"+ "submatch");
- ArrayList<Integer> classRef = new ArrayList<Integer>();
-
- classRef.add(classRefCounter);
-// classRefCounter++;
- // yes, do this twice!
- classRef.add(classRefCounter+1);
-// classRefCounter++;
- exclGroup.put("classRef", classRef);
- exclGroup.put("classRefOp", "classRefOp:"+"intersection");
- ArrayList<Object> operands = new ArrayList<Object>();
- exclGroup.put("operands", operands);
- objectStack.push(exclGroup);
- stackedObjects++;
- putIntoSuperObject(exclGroup, 1);
- }
-
- if (nodeCat.equals("OPEND") || nodeCat.equals("OPBEG")) {
- // Step I: create group
- LinkedHashMap<String, Object> beggroup = new LinkedHashMap<String, Object>();
- beggroup.put("@type", "korap:group");
- beggroup.put("operation", "operation:"+ "submatch");
- ArrayList<Integer> spanRef = new ArrayList<Integer>();
- if (nodeCat.equals("OPBEG")) {
- spanRef.add(0); spanRef.add(1);
- } else {
- spanRef.add(-1); spanRef.add(1);
- }
- beggroup.put("spanRef", spanRef);
- beggroup.put("operands", new ArrayList<Object>());
- objectStack.push(beggroup);
- stackedObjects++;
-
- // Step II: decide where to put
- putIntoSuperObject(beggroup, 1);
- }
-
- if (nodeCat.equals("OPBED")) {
- // Step I: create group
- int optsChild = node.getChildCount()-1;
- Tree conditions = node.getChild(optsChild).getChild(0);
-
- // create a containing group expressing the submatch constraint on the first argument
- LinkedHashMap<String, Object> submatchgroup = new LinkedHashMap<String, Object>();
- submatchgroup.put("@type", "korap:group");
- submatchgroup.put("operation", "operation:"+ "submatch");
- ArrayList<Integer> spanRef = new ArrayList<Integer>();
- spanRef.add(1);
- submatchgroup.put("classRef", spanRef);
- ArrayList<Object> submatchoperands = new ArrayList<Object>();
- submatchgroup.put("operands", submatchoperands);
- putIntoSuperObject(submatchgroup, 0);
-
- // Distinguish two cases. Normal case: query has just one condition, like #BED(X, sa) ...
- if (conditions.getChildCount()==1) {
- CosmasCondition c = new CosmasCondition(conditions.getChild(0));
-
- // create the group expressing the position constraint
- LinkedHashMap<String, Object> posgroup = new LinkedHashMap<String, Object>();
- posgroup.put("@type", "korap:group");
- posgroup.put("operation", "operation:"+ "position");
-
- posgroup.put("frame", "frame:"+c.position);
- if (c.negated) posgroup.put("exclude", true);
- ArrayList<Object> operands = new ArrayList<Object>();
- posgroup.put("operands", operands);
+ LinkedHashMap<String, Object> termGroup = makeTermGroup("and");
+ ArrayList<Object> termGroupOperands = (ArrayList<Object>) termGroup.get("operands");
+ for (int i = elname; i < node.getChildCount(); i++) {
+ Tree attrNode = node.getChild(i);
+ if (attrNode.getChildCount() == 2) {
+ LinkedHashMap<String, Object> term = makeTerm();
+ termGroupOperands.add(term);
+ String layer = attrNode.getChild(0).toStringTree();
+ String[] splitted = layer.split("/");
+ if (splitted.length > 1) {
+ term.put("foundry", splitted[0]);
+ layer = splitted[1];
+ }
+ term.put("layer", translateMorph(layer));
+ term.put("key", attrNode.getChild(1).toStringTree());
+ String match = getNodeCat(attrNode).equals("EQ") ? "eq" : "ne";
+ term.put("match", "match:" + match);
+ } else {
+ LinkedHashMap<String, Object> subTermGroup = makeTermGroup("and");
+ ArrayList<Object> subTermGroupOperands = (ArrayList<Object>) subTermGroup.get("operands");
+ int j;
+ for (j = 1; j < attrNode.getChildCount(); j++) {
+ LinkedHashMap<String, Object> term = makeTerm();
+ String layer = attrNode.getChild(0).toStringTree();
+ String[] splitted = layer.split("/");
+ if (splitted.length > 1) {
+ term.put("foundry", splitted[0]);
+ layer = splitted[1];
+ }
+ term.put("layer", translateMorph(layer));
+ term.put("key", attrNode.getChild(j).toStringTree());
+ String match = getNodeCat(attrNode).equals("EQ") ? "eq" : "ne";
+ term.put("match", "match:" + match);
+ if (node.getChildCount() == elname + 1) {
+ termGroupOperands.add(term);
+ System.err.println("taga");
+ } else {
+ subTermGroupOperands.add(term);
+ System.err.println(layer);
+ }
+ }
+ if (node.getChildCount() > elname + 1) {
+ System.err.println(termGroupOperands);
+ termGroupOperands.add(subTermGroup);
+ System.err.println(termGroupOperands);
+ }
+ }
+ if (getNodeCat(attrNode).equals("NOTEQ")) negate = true;
+ }
+ elem.put("attr", termGroup);
+ }
+ }
- // create span representing the element expressed in the condition
- LinkedHashMap<String, Object> bedElem = new LinkedHashMap<String, Object>();
- bedElem.put("@type", "korap:span");
- bedElem.put("key", c.elem);
-
- // create a class group containing the argument, in order to submatch the arg.
- LinkedHashMap<String, Object> classGroup = new LinkedHashMap<String, Object>();
- classGroup.put("@type", "korap:group");
- classGroup.put("operation", "operation:class");
- classGroup.put("class", classRefCounter);
- classRefCounter++;
- classGroup.put("operands", new ArrayList<Object>());
- objectStack.push(classGroup);
- stackedObjects++;
- operands.add(bedElem);
- operands.add(classGroup);
- // Step II: decide where to put
- submatchoperands.add(posgroup);
-
- // ... or the query has several conditions specified, like #BED(XY, sa,-pa). In that case,
- // create an 'and' group and embed the position groups in its operands
- } else {
- // node has several conditions (like 'sa, -pa')
- // -> create zero-distance sequence group and embed all position groups there
- LinkedHashMap<String, Object> conjunct = new LinkedHashMap<String, Object>();
- conjunct.put("@type", "korap:group");
- conjunct.put("operation", "operation:"+ "sequence");
- ArrayList<Object> distances = new ArrayList<Object>();
- conjunct.put("distances", distances);
- LinkedHashMap<String, Object> zerodistance = new LinkedHashMap<String, Object>();
- zerodistance.put("@type", "korap:distance");
- zerodistance.put("key", "w");
- zerodistance.put("min", 0);
- zerodistance.put("max", 0);
- distances.add(zerodistance);
- ArrayList<Object> operands = new ArrayList<Object>();
- conjunct.put("operands", operands);
- ArrayList<ArrayList<Object>> distributedOperands = new ArrayList<ArrayList<Object>>();
-
- for (int i=0; i<conditions.getChildCount(); i++) {
- // for each condition, create a position group containing a class group. problem: how to get argument into every operands list?
- // -> use distributedOperandsLists
- LinkedHashMap<String, Object> posGroup = new LinkedHashMap<String, Object>();
- operands.add(posGroup);
-
- // make position group
- CosmasCondition c = new CosmasCondition(conditions.getChild(i));
- posGroup.put("@type", "korap:group");
- posGroup.put("operation", "operation:"+ "position");
- posGroup.put("frame", "frame:"+c.position);
- if (c.negated) posGroup.put("exclude", "true");
- ArrayList<Object> posOperands = new ArrayList<Object>();
-
- // make class group
- LinkedHashMap<String, Object> classGroup = new LinkedHashMap<String, Object>();
- classGroup.put("@type", "korap:group");
- classGroup.put("operation", "operation:class");
- classGroup.put("class", classRefCounter);
- classRefCounter++;
- ArrayList<Object> classOperands = new ArrayList<Object>();
- classGroup.put("operands", classOperands);
- distributedOperands.add(classOperands); // subtree to be put into every class group -> distribute
-
- // put the span and the class group into the position group
- posGroup.put("operands", posOperands);
- LinkedHashMap<String, Object> span = new LinkedHashMap<String, Object>();
- posOperands.add(span);
- posOperands.add(classGroup);
- span.put("@type", "korap:span");
- span.put("key", c.elem);
- }
- submatchoperands.add(conjunct);
- distributedOperandsLists.push(distributedOperands);
- }
-
- }
- objectsToPop.push(stackedObjects);
+ //Step II: decide where to put
+ putIntoSuperObject(elem);
+ }
+
+ if (nodeCat.equals("OPLABEL")) {
+ // Step I: create element
+ LinkedHashMap<String, Object> elem = new LinkedHashMap<String, Object>();
+ elem.put("@type", "korap:span");
+ elem.put("key", node.getChild(0).toStringTree().replaceAll("<|>", ""));
+ //Step II: decide where to put
+ putIntoSuperObject(elem);
+ }
+
+ if (nodeCat.equals("OPAND") || nodeCat.equals("OPNOT")) {
+ // Step I: create group
+ LinkedHashMap<String, Object> distgroup = new LinkedHashMap<String, Object>();
+ distgroup.put("@type", "korap:group");
+ distgroup.put("operation", "operation:sequence");
+ ArrayList<Object> distances = new ArrayList<Object>();
+ LinkedHashMap<String, Object> zerodistance = new LinkedHashMap<String, Object>();
+ zerodistance.put("@type", "korap:distance");
+ zerodistance.put("key", "t");
+ zerodistance.put("min", 0);
+ zerodistance.put("max", 0);
+ if (nodeCat.equals("OPNOT")) zerodistance.put("exclude", true);
+ distances.add(zerodistance);
+ distgroup.put("distances", distances);
+ distgroup.put("operands", new ArrayList<Object>());
+ objectStack.push(distgroup);
+ stackedObjects++;
+ // Step II: decide where to put
+ putIntoSuperObject(distgroup, 1);
+ }
+
+ if (nodeCat.equals("OPOR")) {
+ // Step I: create group
+ LinkedHashMap<String, Object> disjunction = new LinkedHashMap<String, Object>();
+ disjunction.put("@type", "korap:group");
+ disjunction.put("operation", "operation:or");
+ disjunction.put("operands", new ArrayList<Object>());
+ objectStack.push(disjunction);
+ stackedObjects++;
+ // Step II: decide where to put
+ putIntoSuperObject(disjunction, 1);
+ }
+
+ if (nodeCat.equals("OPPROX")) {
+ //TODO direction "both": wrap in "or" group with operands once flipped, once not
+ // collect info
+ Tree prox_opts = node.getChild(0);
+ Tree typ = prox_opts.getChild(0);
+ Tree dist_list = prox_opts.getChild(1);
+ // Step I: create group
+ LinkedHashMap<String, Object> proxSequence = new LinkedHashMap<String, Object>();
+ proxSequence.put("@type", "korap:group");
+ proxSequence.put("operation", "operation:" + "sequence");
+ objectStack.push(proxSequence);
+ stackedObjects++;
+ ArrayList<Object> constraints = new ArrayList<Object>();
+ boolean exclusion = !typ.getChild(0).toStringTree().equals("PROX");
+
+ boolean inOrder = false;
+ proxSequence.put("inOrder", inOrder);
+ proxSequence.put("distances", constraints);
+
+ ArrayList<Object> operands = new ArrayList<Object>();
+ proxSequence.put("operands", operands);
+
+ // possibly several distance constraints
+ for (int i = 0; i < dist_list.getChildCount(); i++) {
+ String direction = dist_list.getChild(i).getChild(0).getChild(0).toStringTree().toLowerCase();
+ String min = dist_list.getChild(i).getChild(1).getChild(0).toStringTree();
+ String max = dist_list.getChild(i).getChild(1).getChild(1).toStringTree();
+ String meas = dist_list.getChild(i).getChild(2).getChild(0).toStringTree();
+ if (min.equals("VAL0")) {
+ min = "0";
+ }
+ LinkedHashMap<String, Object> distance = new LinkedHashMap<String, Object>();
+ distance.put("@type", "korap:distance");
+ distance.put("key", meas);
+ distance.put("min", Integer.parseInt(min));
+ distance.put("max", Integer.parseInt(max));
+ if (exclusion) {
+ distance.put("exclude", exclusion);
+ }
+ constraints.add(distance);
+ if (direction.equals("plus")) {
+ inOrder = true;
+ } else if (direction.equals("minus")) {
+ inOrder = true;
+ invertedOperandsLists.add(operands);
+ }
+ }
+ proxSequence.put("inOrder", inOrder);
+ // Step II: decide where to put
+ putIntoSuperObject(proxSequence, 1);
+ }
+
+ // inlcusion or overlap
+ if (nodeCat.equals("OPIN") || nodeCat.equals("OPOV")) {
+ // Step I: create group
+ LinkedHashMap<String, Object> submatchgroup = new LinkedHashMap<String, Object>();
+ submatchgroup.put("@type", "korap:group");
+ submatchgroup.put("operation", "operation:" + "submatch");
+ ArrayList<Integer> classRef = new ArrayList<Integer>();
+ classRef.add(classRefCounter);
+ submatchgroup.put("classRef", classRef);
+
+ ArrayList<Object> submatchoperands = new ArrayList<Object>();
+ LinkedHashMap<String, Object> posgroup = new LinkedHashMap<String, Object>();
+ submatchgroup.put("operands", submatchoperands);
+ submatchoperands.add(posgroup);
+ posgroup.put("@type", "korap:group");
+// String relation = nodeCat.equals("OPIN") ? "position" : "overlaps";
+ posgroup.put("operation", "operation:" + "position");
+ if (nodeCat.equals("OPIN")) {
+ parseOPINOptions(node, posgroup);
+ } else {
+ parseOPOVOptions(node, posgroup);
+ }
+ ArrayList<Object> posoperands = new ArrayList<Object>();
+ posgroup.put("operands", posoperands);
+ objectStack.push(posgroup);
+ // mark this an inverted list
+ invertedOperandsLists.push(posoperands);
+ stackedObjects++;
+ // Step II: decide where to put
+ putIntoSuperObject(submatchgroup, 1);
+ }
+
+
+ // Wrap the first argument of an #IN operator in a class group
+ if (nodeCat.equals("ARG1") && (openNodeCats.get(1).equals("OPIN") || openNodeCats.get(1).equals("OPOV") || openNodeCats.get(2).equals("OPNHIT"))) {
+ // Step I: create group
+ LinkedHashMap<String, Object> classGroup = new LinkedHashMap<String, Object>();
+ classGroup.put("@type", "korap:group");
+ classGroup.put("operation", "operation:" + "class");
+ classGroup.put("class", classRefCounter);
+ classRefCounter++;
+ classGroup.put("operands", new ArrayList<Object>());
+ objectStack.push(classGroup);
+ stackedObjects++;
+ // Step II: decide where to put
+ putIntoSuperObject(classGroup, 1);
+ }
+
+ // Wrap the 2nd argument of an #IN operator embedded in NHIT in a class group
+ if (nodeCat.equals("ARG2") && openNodeCats.get(2).equals("OPNHIT")) {
+ // Step I: create group
+ LinkedHashMap<String, Object> classGroup = new LinkedHashMap<String, Object>();
+ classGroup.put("@type", "korap:group");
+ classGroup.put("operation", "operation:" + "class");
+ classGroup.put("class", classRefCounter);
+ classRefCounter++;
+ classGroup.put("operands", new ArrayList<Object>());
+ objectStack.push(classGroup);
+ stackedObjects++;
+ // Step II: decide where to put
+ putIntoSuperObject(classGroup, 1);
+ }
+
+
+ if (nodeCat.equals("OPNHIT")) {
+ LinkedHashMap<String, Object> exclGroup = new LinkedHashMap<String, Object>();
+ exclGroup.put("@type", "korap:group");
+ exclGroup.put("operation", "operation:" + "submatch");
+ ArrayList<Integer> classRef = new ArrayList<Integer>();
+
+ classRef.add(classRefCounter);
+// classRefCounter++;
+ // yes, do this twice!
+ classRef.add(classRefCounter + 1);
+// classRefCounter++;
+ exclGroup.put("classRef", classRef);
+ exclGroup.put("classRefOp", "classRefOp:" + "intersection");
+ ArrayList<Object> operands = new ArrayList<Object>();
+ exclGroup.put("operands", operands);
+ objectStack.push(exclGroup);
+ stackedObjects++;
+ putIntoSuperObject(exclGroup, 1);
+ }
+
+ if (nodeCat.equals("OPEND") || nodeCat.equals("OPBEG")) {
+ // Step I: create group
+ LinkedHashMap<String, Object> beggroup = new LinkedHashMap<String, Object>();
+ beggroup.put("@type", "korap:group");
+ beggroup.put("operation", "operation:" + "submatch");
+ ArrayList<Integer> spanRef = new ArrayList<Integer>();
+ if (nodeCat.equals("OPBEG")) {
+ spanRef.add(0);
+ spanRef.add(1);
+ } else {
+ spanRef.add(-1);
+ spanRef.add(1);
+ }
+ beggroup.put("spanRef", spanRef);
+ beggroup.put("operands", new ArrayList<Object>());
+ objectStack.push(beggroup);
+ stackedObjects++;
+
+ // Step II: decide where to put
+ putIntoSuperObject(beggroup, 1);
+ }
+
+ if (nodeCat.equals("OPBED")) {
+ // Step I: create group
+ int optsChild = node.getChildCount() - 1;
+ Tree conditions = node.getChild(optsChild).getChild(0);
+
+ // create a containing group expressing the submatch constraint on the first argument
+ LinkedHashMap<String, Object> submatchgroup = new LinkedHashMap<String, Object>();
+ submatchgroup.put("@type", "korap:group");
+ submatchgroup.put("operation", "operation:" + "submatch");
+ ArrayList<Integer> spanRef = new ArrayList<Integer>();
+ spanRef.add(1);
+ submatchgroup.put("classRef", spanRef);
+ ArrayList<Object> submatchoperands = new ArrayList<Object>();
+ submatchgroup.put("operands", submatchoperands);
+ putIntoSuperObject(submatchgroup, 0);
+
+ // Distinguish two cases. Normal case: query has just one condition, like #BED(X, sa) ...
+ if (conditions.getChildCount() == 1) {
+ CosmasCondition c = new CosmasCondition(conditions.getChild(0));
+
+ // create the group expressing the position constraint
+ LinkedHashMap<String, Object> posgroup = new LinkedHashMap<String, Object>();
+ posgroup.put("@type", "korap:group");
+ posgroup.put("operation", "operation:" + "position");
+
+ posgroup.put("frame", "frame:" + c.position);
+ if (c.negated) posgroup.put("exclude", true);
+ ArrayList<Object> operands = new ArrayList<Object>();
+ posgroup.put("operands", operands);
+
+ // create span representing the element expressed in the condition
+ LinkedHashMap<String, Object> bedElem = new LinkedHashMap<String, Object>();
+ bedElem.put("@type", "korap:span");
+ bedElem.put("key", c.elem);
+
+ // create a class group containing the argument, in order to submatch the arg.
+ LinkedHashMap<String, Object> classGroup = new LinkedHashMap<String, Object>();
+ classGroup.put("@type", "korap:group");
+ classGroup.put("operation", "operation:class");
+ classGroup.put("class", classRefCounter);
+ classRefCounter++;
+ classGroup.put("operands", new ArrayList<Object>());
+ objectStack.push(classGroup);
+ stackedObjects++;
+ operands.add(bedElem);
+ operands.add(classGroup);
+ // Step II: decide where to put
+ submatchoperands.add(posgroup);
+
+ // ... or the query has several conditions specified, like #BED(XY, sa,-pa). In that case,
+ // create an 'and' group and embed the position groups in its operands
+ } else {
+ // node has several conditions (like 'sa, -pa')
+ // -> create zero-distance sequence group and embed all position groups there
+ LinkedHashMap<String, Object> conjunct = new LinkedHashMap<String, Object>();
+ conjunct.put("@type", "korap:group");
+ conjunct.put("operation", "operation:" + "sequence");
+ ArrayList<Object> distances = new ArrayList<Object>();
+ conjunct.put("distances", distances);
+ LinkedHashMap<String, Object> zerodistance = new LinkedHashMap<String, Object>();
+ zerodistance.put("@type", "korap:distance");
+ zerodistance.put("key", "w");
+ zerodistance.put("min", 0);
+ zerodistance.put("max", 0);
+ distances.add(zerodistance);
+ ArrayList<Object> operands = new ArrayList<Object>();
+ conjunct.put("operands", operands);
+ ArrayList<ArrayList<Object>> distributedOperands = new ArrayList<ArrayList<Object>>();
+
+ for (int i = 0; i < conditions.getChildCount(); i++) {
+ // for each condition, create a position group containing a class group. problem: how to get argument into every operands list?
+ // -> use distributedOperandsLists
+ LinkedHashMap<String, Object> posGroup = new LinkedHashMap<String, Object>();
+ operands.add(posGroup);
+
+ // make position group
+ CosmasCondition c = new CosmasCondition(conditions.getChild(i));
+ posGroup.put("@type", "korap:group");
+ posGroup.put("operation", "operation:" + "position");
+ posGroup.put("frame", "frame:" + c.position);
+ if (c.negated) posGroup.put("exclude", "true");
+ ArrayList<Object> posOperands = new ArrayList<Object>();
+
+ // make class group
+ LinkedHashMap<String, Object> classGroup = new LinkedHashMap<String, Object>();
+ classGroup.put("@type", "korap:group");
+ classGroup.put("operation", "operation:class");
+ classGroup.put("class", classRefCounter);
+ classRefCounter++;
+ ArrayList<Object> classOperands = new ArrayList<Object>();
+ classGroup.put("operands", classOperands);
+ distributedOperands.add(classOperands); // subtree to be put into every class group -> distribute
+
+ // put the span and the class group into the position group
+ posGroup.put("operands", posOperands);
+ LinkedHashMap<String, Object> span = new LinkedHashMap<String, Object>();
+ posOperands.add(span);
+ posOperands.add(classGroup);
+ span.put("@type", "korap:span");
+ span.put("key", c.elem);
+ }
+ submatchoperands.add(conjunct);
+ distributedOperandsLists.push(distributedOperands);
+ }
+
+ }
+ objectsToPop.push(stackedObjects);
/*
****************************************************************
@@ -696,223 +695,225 @@
****************************************************************
****************************************************************
*/
- for (int i=0; i<node.getChildCount(); i++) {
- Tree child = node.getChild(i);
- processNode(child);
- }
+ for (int i = 0; i < node.getChildCount(); i++) {
+ Tree child = node.getChild(i);
+ processNode(child);
+ }
/*
**************************************************************
* Stuff that happens after processing the children of a node *
**************************************************************
*/
-
- // remove sequence from object stack if node is implicitly sequenced
- if (sequencedNodes.size()>0) {
- if (node == sequencedNodes.getFirst()) {
- objectStack.pop();
- sequencedNodes.pop();
- }
- }
-
- for (int i=0; i<objectsToPop.get(0); i++) {
- objectStack.pop();
- }
- objectsToPop.pop();
-
- if (nodeCat.equals("ARG2") && openNodeCats.get(1).equals("OPNOT")) {
- negate = false;
- }
- openNodeCats.pop();
-
- }
+ // remove sequence from object stack if node is implicitly sequenced
+ if (sequencedNodes.size() > 0) {
+ if (node == sequencedNodes.getFirst()) {
+ objectStack.pop();
+ sequencedNodes.pop();
+ }
+ }
-
-
+ for (int i = 0; i < objectsToPop.get(0); i++) {
+ objectStack.pop();
+ }
+ objectsToPop.pop();
- private Object translateMorph(String layer) {
- LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();
- map.put("ANA", "pos");
- if (map.containsKey(layer))
- return map.get(layer);
- else
- return layer;
- }
+ if (nodeCat.equals("ARG2") && openNodeCats.get(1).equals("OPNOT")) {
+ negate = false;
+ }
+ openNodeCats.pop();
+ }
- private void parseOPINOptions(Tree node, LinkedHashMap<String, Object> posgroup) {
- Tree posnode = getFirstChildWithCat(node, "POS");
- Tree rangenode = getFirstChildWithCat(node, "RANGE");
- Tree exclnode = getFirstChildWithCat(node, "EXCL");
- Tree groupnode = getFirstChildWithCat(node, "GROUP");
- boolean negatePosition = false;
-
- String position = "";
- if (posnode != null) {
- String value = posnode.getChild(0).toStringTree();
- position = translateTextAreaArgument(value, "in");
- if (value.equals("N")) {
- negatePosition = !negatePosition;
- }
- } else {
- position = "contains";
- }
- posgroup.put("frame", "frame:"+position);
- position = openNodeCats.get(1).equals("OPIN") ? "contains" : "full";
-
- if (rangenode != null) {
- String range = rangenode.getChild(0).toStringTree();
- posgroup.put("range", range.toLowerCase());
- }
-
- if (exclnode != null) {
- if (exclnode.getChild(0).toStringTree().equals("YES")) {
- negatePosition = !negatePosition;
- }
- }
- System.err.println(negatePosition);
- if (negatePosition) {
- posgroup.put("exclude", "true");
+ private Object translateMorph(String layer) {
+ // todo: not very nicely solved! Does this require extension somehow? if not, why not use simple string comparison?!
+// LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();
+// map.put("ANA", "pos");
+// if (map.containsKey(layer))
+// return map.get(layer);
+// else
+// return layer;
+ if (layer.equals("ANA"))
+ return ResourceMapper.descriptor2policy(layer);
+ else
+ return layer;
+
+ }
+
+ private void parseOPINOptions(Tree node, LinkedHashMap<String, Object> posgroup) {
+ Tree posnode = getFirstChildWithCat(node, "POS");
+ Tree rangenode = getFirstChildWithCat(node, "RANGE");
+ Tree exclnode = getFirstChildWithCat(node, "EXCL");
+ Tree groupnode = getFirstChildWithCat(node, "GROUP");
+ boolean negatePosition = false;
+
+ String position = "";
+ if (posnode != null) {
+ String value = posnode.getChild(0).toStringTree();
+ position = translateTextAreaArgument(value, "in");
+ if (value.equals("N")) {
+ negatePosition = !negatePosition;
+ }
+ } else {
+ position = "contains";
+ }
+ posgroup.put("frame", "frame:" + position);
+ position = openNodeCats.get(1).equals("OPIN") ? "contains" : "full";
+
+ if (rangenode != null) {
+ String range = rangenode.getChild(0).toStringTree();
+ posgroup.put("range", range.toLowerCase());
+ }
+
+ if (exclnode != null) {
+ if (exclnode.getChild(0).toStringTree().equals("YES")) {
+ negatePosition = !negatePosition;
+ }
+ }
+ System.err.println(negatePosition);
+ if (negatePosition) {
+ posgroup.put("exclude", "true");
// negate = !negate;
- }
-
- if (groupnode != null) {
- String grouping = groupnode.getChild(0).toStringTree().equals("max") ? "true" : "false";
- posgroup.put("grouping", grouping);
- }
- }
-
- private void parseOPOVOptions(Tree node, LinkedHashMap<String, Object> posgroup) {
- Tree posnode = getFirstChildWithCat(node, "POS");
- Tree exclnode = getFirstChildWithCat(node, "EXCL");
- Tree groupnode = getFirstChildWithCat(node, "GROUP");
-
- String position = "";
- if (posnode != null) {
- String value = posnode.getChild(0).toStringTree();
- position = "-"+translateTextAreaArgument(value, "ov");
- }
- posgroup.put("frame", "frame:"+"overlaps"+position);
-
- if (exclnode != null) {
- if (exclnode.getChild(0).toStringTree().equals("YES")) {
- posgroup.put("match", "match:"+"ne");
- }
- }
- if (groupnode != null) {
- String grouping = groupnode.getChild(0).toStringTree().equals("@max") ? "true" : "false";
- posgroup.put("grouping", grouping);
- }
-
- }
+ }
- /**
- * Translates the text area specifications (position option arguments) to terms used in serialisation.
- * For the allowed argument types and their values for OPIN and OPOV, see
- * http://www.ids-mannheim.de/cosmas2/win-app/hilfe/suchanfrage/eingabe-grafisch/syntax/ARGUMENT_I.html or
- * http://www.ids-mannheim.de/cosmas2/win-app/hilfe/suchanfrage/eingabe-grafisch/syntax/ARGUMENT_O.html, respectively.
- * @param argument
- * @param mode
- * @return
- */
- private String translateTextAreaArgument(String argument, String mode) {
- String position = "";
- switch (argument) {
- case "L":
- position = mode.equals("in") ? "startswith" : "left";
- break;
- case "R":
- position = mode.equals("in") ? "endswith" : "right";
- break;
- case "F":
- position = "leftrightmatch";
- break;
- case "FE":
- position = "matches";
- break;
- case "FI":
- position = "leftrightmatch-noident";
- break;
- case "N": // for OPIN only - exclusion constraint formulated in parseOPINOptions
- position = "leftrightmatch";
- break;
- case "X": // for OPOV only
- position = "residual";
- break;
- }
- return position;
- }
-
- @SuppressWarnings("unchecked")
- private void putIntoSuperObject(LinkedHashMap<String, Object> object, int objStackPosition) {
- if (distributedOperandsLists.size()>0) {
- ArrayList<ArrayList<Object>> distributedOperands = distributedOperandsLists.pop();
- for (ArrayList<Object> operands : distributedOperands) {
- operands.add(object);
- }
- } else if (objectStack.size()>objStackPosition) {
- ArrayList<Object> topObjectOperands = (ArrayList<Object>) objectStack.get(objStackPosition).get("operands");
- if (!invertedOperandsLists.contains(topObjectOperands)) {
- topObjectOperands.add(object);
- } else {
- topObjectOperands.add(0, object);
- }
-
- } else {
- requestMap.put("query", object);
- }
- }
-
- private void putIntoSuperObject(LinkedHashMap<String, Object> object) {
- putIntoSuperObject(object, 0);
- }
-
+ if (groupnode != null) {
+ String grouping = groupnode.getChild(0).toStringTree().equals("max") ? "true" : "false";
+ posgroup.put("grouping", grouping);
+ }
+ }
- private Tree parseCosmasQuery(String q) throws RecognitionException {
- Pattern p = Pattern.compile("(\\w+):((\\+|-)?(sa|se|pa|pe|ta|te),?)+");
- Matcher m = p.matcher(q);
-
- String rewrittenQuery = q;
- while (m.find()) {
- String match = m.group();
- String conditionsString = match.split(":")[1];
- Pattern conditionPattern = Pattern.compile("(\\+|-)?(sa|se|pa|pe|ta|te)");
- Matcher conditionMatcher = conditionPattern.matcher(conditionsString);
- String replacement = "#BED("+m.group(1)+" , ";
- while (conditionMatcher.find()) {
- replacement = replacement+conditionMatcher.group()+",";
- }
- replacement = replacement.substring(0, replacement.length()-1)+")"; //remove trailing comma and close parenthesis
- System.out.println(replacement);
- rewrittenQuery = rewrittenQuery.replace(match, replacement);
- }
- q = rewrittenQuery;
- Tree tree = null;
- ANTLRStringStream ss = new ANTLRStringStream(q);
- c2psLexer lex = new c2psLexer(ss);
- org.antlr.runtime.CommonTokenStream tokens = new org.antlr.runtime.CommonTokenStream(lex); //v3
- parser = new c2psParser(tokens);
- c2psParser.c2ps_query_return c2Return = ((c2psParser) parser).c2ps_query(); // statt t().
- // AST Tree anzeigen:
- tree = (Tree)c2Return.getTree();
-
- String treestring = tree.toStringTree();
- if (treestring.contains("<mismatched token") || treestring.contains("<error") || treestring.contains("<unexpected")) {
- log.error("Invalid tree. Could not parse Cosmas query. Make sure it is well-formed.");
- throw new RecognitionException();
- }
-
- return tree;
- }
-
- /**
- * @param args
- */
- public static void main(String[] args) {
+ private void parseOPOVOptions(Tree node, LinkedHashMap<String, Object> posgroup) {
+ Tree posnode = getFirstChildWithCat(node, "POS");
+ Tree exclnode = getFirstChildWithCat(node, "EXCL");
+ Tree groupnode = getFirstChildWithCat(node, "GROUP");
+
+ String position = "";
+ if (posnode != null) {
+ String value = posnode.getChild(0).toStringTree();
+ position = "-" + translateTextAreaArgument(value, "ov");
+ }
+ posgroup.put("frame", "frame:" + "overlaps" + position);
+
+ if (exclnode != null) {
+ if (exclnode.getChild(0).toStringTree().equals("YES")) {
+ posgroup.put("match", "match:" + "ne");
+ }
+ }
+ if (groupnode != null) {
+ String grouping = groupnode.getChild(0).toStringTree().equals("@max") ? "true" : "false";
+ posgroup.put("grouping", grouping);
+ }
+
+ }
+
+ /**
+ * Translates the text area specifications (position option arguments) to terms used in serialisation.
+ * For the allowed argument types and their values for OPIN and OPOV, see
+ * http://www.ids-mannheim.de/cosmas2/win-app/hilfe/suchanfrage/eingabe-grafisch/syntax/ARGUMENT_I.html or
+ * http://www.ids-mannheim.de/cosmas2/win-app/hilfe/suchanfrage/eingabe-grafisch/syntax/ARGUMENT_O.html, respectively.
+ *
+ * @param argument
+ * @param mode
+ * @return
+ */
+ private String translateTextAreaArgument(String argument, String mode) {
+ String position = "";
+ switch (argument) {
+ case "L":
+ position = mode.equals("in") ? "startswith" : "left";
+ break;
+ case "R":
+ position = mode.equals("in") ? "endswith" : "right";
+ break;
+ case "F":
+ position = "leftrightmatch";
+ break;
+ case "FE":
+ position = "matches";
+ break;
+ case "FI":
+ position = "leftrightmatch-noident";
+ break;
+ case "N": // for OPIN only - exclusion constraint formulated in parseOPINOptions
+ position = "leftrightmatch";
+ break;
+ case "X": // for OPOV only
+ position = "residual";
+ break;
+ }
+ return position;
+ }
+
+ @SuppressWarnings("unchecked")
+ private void putIntoSuperObject(LinkedHashMap<String, Object> object, int objStackPosition) {
+ if (distributedOperandsLists.size() > 0) {
+ ArrayList<ArrayList<Object>> distributedOperands = distributedOperandsLists.pop();
+ for (ArrayList<Object> operands : distributedOperands) {
+ operands.add(object);
+ }
+ } else if (objectStack.size() > objStackPosition) {
+ ArrayList<Object> topObjectOperands = (ArrayList<Object>) objectStack.get(objStackPosition).get("operands");
+ if (!invertedOperandsLists.contains(topObjectOperands)) {
+ topObjectOperands.add(object);
+ } else {
+ topObjectOperands.add(0, object);
+ }
+
+ } else {
+ requestMap.put("query", object);
+ }
+ }
+
+ private void putIntoSuperObject(LinkedHashMap<String, Object> object) {
+ putIntoSuperObject(object, 0);
+ }
+
+
+ private Tree parseCosmasQuery(String q) throws RecognitionException {
+ Pattern p = Pattern.compile("(\\w+):((\\+|-)?(sa|se|pa|pe|ta|te),?)+");
+ Matcher m = p.matcher(q);
+
+ String rewrittenQuery = q;
+ while (m.find()) {
+ String match = m.group();
+ String conditionsString = match.split(":")[1];
+ Pattern conditionPattern = Pattern.compile("(\\+|-)?(sa|se|pa|pe|ta|te)");
+ Matcher conditionMatcher = conditionPattern.matcher(conditionsString);
+ String replacement = "#BED(" + m.group(1) + " , ";
+ while (conditionMatcher.find()) {
+ replacement = replacement + conditionMatcher.group() + ",";
+ }
+ replacement = replacement.substring(0, replacement.length() - 1) + ")"; //remove trailing comma and close parenthesis
+ System.out.println(replacement);
+ rewrittenQuery = rewrittenQuery.replace(match, replacement);
+ }
+ q = rewrittenQuery;
+ Tree tree = null;
+ ANTLRStringStream ss = new ANTLRStringStream(q);
+ c2psLexer lex = new c2psLexer(ss);
+ org.antlr.runtime.CommonTokenStream tokens = new org.antlr.runtime.CommonTokenStream(lex); //v3
+ parser = new c2psParser(tokens);
+ c2psParser.c2ps_query_return c2Return = ((c2psParser) parser).c2ps_query(); // statt t().
+ // AST Tree anzeigen:
+ tree = (Tree) c2Return.getTree();
+
+ String treestring = tree.toStringTree();
+ if (treestring.contains("<mismatched token") || treestring.contains("<error") || treestring.contains("<unexpected")) {
+ log.error("Invalid tree. Could not parse Cosmas query. Make sure it is well-formed.");
+ throw new RecognitionException();
+ }
+
+ return tree;
+ }
+
+ /**
+ * @param args
+ */
+ public static void main(String[] args) {
/*
* For debugging
*/
- String[] queries = new String[] {
+ String[] queries = new String[]{
/* COSMAS 2 */
// "MORPH(V)",
// "MORPH(V PRES)",
@@ -924,32 +925,32 @@
// "#NHIT(gehen /w1:10 voran)",
// "#BED(der Mann , sa,-pa)",
// "Mann /t0 Frau",
- "sagt der:sa Bundeskanzler",
+ "sagt der:sa Bundeskanzler",
// "Der:sa,-pe,+te ",
- "#ELEM(W POS!='N V' title=tada)",
- "#ELEM(W ANA != 'N V')",
- "#ELEM(W ANA != 'N V' Genre = Sport)",
- "(&Baum #IN #ELEM(xip/c=np)) #IN(L) #ELEM(s)"
+ "#ELEM(W POS!='N V' title=tada)",
+ "#ELEM(W ANA != 'N V')",
+ "#ELEM(W ANA != 'N V' Genre = Sport)",
+ "(&Baum #IN #ELEM(xip/c=np)) #IN(L) #ELEM(s)"
// "(&Baum #IN #ELEM(NP)) #IN(L) #ELEM(S)"
- };
+ };
// CosmasTree.debug=true;
- for (String q : queries) {
- try {
- System.out.println(q);
- try {
- CosmasTree act = new CosmasTree(q);
- System.out.println(act.parseCosmasQuery(q).toStringTree());
- } catch (QueryException e) {
- e.printStackTrace();
- } catch (RecognitionException e) {
- e.printStackTrace();
- }
- System.out.println();
-
- } catch (NullPointerException npe) {
- npe.printStackTrace();
- System.out.println("null\n");
- }
- }
- }
+ for (String q : queries) {
+ try {
+ System.out.println(q);
+ try {
+ CosmasTree act = new CosmasTree(q);
+ System.out.println(act.parseCosmasQuery(q).toStringTree());
+ } catch (QueryException e) {
+ e.printStackTrace();
+ } catch (RecognitionException e) {
+ e.printStackTrace();
+ }
+ System.out.println();
+
+ } catch (NullPointerException npe) {
+ npe.printStackTrace();
+ System.out.println("null\n");
+ }
+ }
+ }
}
\ No newline at end of file