Improve context conversion in MetaQueryBuilder

Change-Id: Id2ea7411813964d8e788283a279bf6bf36ea3886
diff --git a/Changes b/Changes
index d423f6c..ef54526 100644
--- a/Changes
+++ b/Changes
@@ -1,10 +1,11 @@
-0.34 2019-07-17
+0.34 2019-08-26
     - [bugfix] Ignore min:max order in distance operators
       (#67; diewald)
     - [feature] Support #COND() operator alias in C2 (#70; diewald)
     - [bugfix] Fixed the distance serialization in CQL boolean queries
       (#69; margaretha)
-    - Updated supported foundries for FCSQL (margaretha)   
+    - Updated supported foundries for FCSQL (margaretha)
+    - Improved context conversion in MetaQueryBuilder (Kustvakt#32; diewald)
 
 0.33 2019-02-20
     - Added debug flags (margaretha)
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/MetaQueryBuilder.java b/src/main/java/de/ids_mannheim/korap/query/serialize/MetaQueryBuilder.java
index cad4319..3da5313 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/MetaQueryBuilder.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/MetaQueryBuilder.java
@@ -5,22 +5,21 @@
 import java.util.List;
 import java.util.Map;
 import java.util.regex.Pattern;
+import java.util.regex.Matcher;
 
 /**
- * @author hanl
- * @date 07/02/2014
+ * @author hanl, ndiewald
  */
 public class MetaQueryBuilder {
 
     private static Pattern p = Pattern
-            .compile("\\s*\\d+-(?:c(?:hars?)?|t(?:okens?)?)");
+            .compile("\\s*(\\d+)-(c(?:hars?)?|t(?:okens?)?)\\s*,\\s*(\\d+)-(c(?:hars?)?|t(?:okens?)?)\\s*");
     private Map meta;
     private SpanContext spanContext;
 
 
     public MetaQueryBuilder () {
         this.meta = new LinkedHashMap();
-        //        this.meta.put("fields", new LinkedList<>());
     }
 
 
@@ -57,14 +56,31 @@
      */
     public MetaQueryBuilder setSpanContext (String context) {
         if (context != null) {
-            if (!p.matcher(context).find())
+
+            Matcher m = p.matcher(context);
+            
+            if (!m.matches())
                 this.spanContext = new SpanContext(context);
             else {
-                String[] ct = context.replaceAll("\\s+", "").split(",");
-                String[] lc = ct[0].split("-");
-                String[] rc = ct[1].split("-");
-                this.spanContext = new SpanContext(Integer.valueOf(lc[0]),
-                        lc[1], Integer.valueOf(rc[0]), rc[1]);
+                int lcLen = Integer.valueOf(m.group(1));
+                String lcType = m.group(2);
+                int rcLen = Integer.valueOf(m.group(3));
+                String rcType = m.group(4);
+
+                if (lcType.startsWith("t")) {
+                    lcType = "token";
+                } else if (lcType.startsWith("c")) {
+                    lcType = "char";
+                }
+
+                if (rcType.startsWith("t")) {
+                    rcType = "token";
+                } else if (rcType.startsWith("c")) {
+                    rcType = "char";
+                }
+                
+                this.spanContext = new SpanContext(lcLen,
+                        lcType, rcLen, rcType);
             }
         }
         return this;
diff --git a/src/test/java/de/ids_mannheim/korap/query/test/MetaQueryTest.java b/src/test/java/de/ids_mannheim/korap/query/test/MetaQueryTest.java
new file mode 100644
index 0000000..e384482
--- /dev/null
+++ b/src/test/java/de/ids_mannheim/korap/query/test/MetaQueryTest.java
@@ -0,0 +1,68 @@
+package de.ids_mannheim.korap.query.test;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+import de.ids_mannheim.korap.query.serialize.MetaQueryBuilder;
+
+
+public class MetaQueryTest {
+
+    private static ObjectMapper mapper = new ObjectMapper();
+
+    @Test
+    public void testContext () { 
+        MetaQueryBuilder mqb = new MetaQueryBuilder();
+
+        mqb.setSpanContext("2-t,4-t");
+        JsonNode node = mapper.valueToTree(mqb.getSpanContext().raw());
+        assertEquals(node.at("/context/left/0").asText(),"token");
+        assertEquals(node.at("/context/right/0").asText(),"token");
+        assertEquals(node.at("/context/left/1").asInt(),2);
+        assertEquals(node.at("/context/right/1").asInt(),4);
+
+        mqb.setSpanContext("2-token,4-token");
+        node = mapper.valueToTree(mqb.getSpanContext().raw());
+        assertEquals(node.at("/context/left/0").asText(),"token");
+        assertEquals(node.at("/context/right/0").asText(),"token");
+        assertEquals(node.at("/context/left/1").asInt(),2);
+        assertEquals(node.at("/context/right/1").asInt(),4);
+
+        mqb.setSpanContext("2-tokens,4-tokens");
+        node = mapper.valueToTree(mqb.getSpanContext().raw());
+        assertEquals(node.at("/context/left/0").asText(),"token");
+        assertEquals(node.at("/context/right/0").asText(),"token");
+        assertEquals(node.at("/context/left/1").asInt(),2);
+        assertEquals(node.at("/context/right/1").asInt(),4);
+        
+        mqb.setSpanContext("2-c,4-c");
+        node = mapper.valueToTree(mqb.getSpanContext().raw());
+        assertEquals(node.at("/context/left/0").asText(),"char");
+        assertEquals(node.at("/context/right/0").asText(),"char");
+        assertEquals(node.at("/context/left/1").asInt(),2);
+        assertEquals(node.at("/context/right/1").asInt(),4);
+
+        mqb.setSpanContext("2-char,4-char");
+        node = mapper.valueToTree(mqb.getSpanContext().raw());
+        assertEquals(node.at("/context/left/0").asText(),"char");
+        assertEquals(node.at("/context/right/0").asText(),"char");
+        assertEquals(node.at("/context/left/1").asInt(),2);
+        assertEquals(node.at("/context/right/1").asInt(),4);
+
+        mqb.setSpanContext("2-chars,4-chars");
+        node = mapper.valueToTree(mqb.getSpanContext().raw());
+        assertEquals(node.at("/context/left/0").asText(),"char");
+        assertEquals(node.at("/context/right/0").asText(),"char");
+        assertEquals(node.at("/context/left/1").asInt(),2);
+        assertEquals(node.at("/context/right/1").asInt(),4);       
+
+        mqb.setSpanContext("2-r,4-r");
+        node = mapper.valueToTree(mqb.getSpanContext().raw());
+        assertEquals(node.at("/context").asText(),"2-r,4-r");
+    }
+}