Added reference query deserialization

Change-Id: I145e608ae114f34ced7788fa124aa0508d21ea5c
diff --git a/src/test/java/de/ids_mannheim/korap/query/TestSpanReferenceQueryJSON.java b/src/test/java/de/ids_mannheim/korap/query/TestSpanReferenceQueryJSON.java
new file mode 100644
index 0000000..b8a21b8
--- /dev/null
+++ b/src/test/java/de/ids_mannheim/korap/query/TestSpanReferenceQueryJSON.java
@@ -0,0 +1,84 @@
+package de.ids_mannheim.korap.query;
+
+import static de.ids_mannheim.korap.TestSimple.getJSONQuery;
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+
+import org.apache.lucene.search.spans.SpanQuery;
+import org.junit.Test;
+
+import de.ids_mannheim.korap.query.wrap.SpanQueryWrapper;
+import de.ids_mannheim.korap.util.QueryException;
+
+public class TestSpanReferenceQueryJSON {
+
+    @Test
+    public void testFirstOperandRef() throws IOException, QueryException {
+
+        String filepath = getClass().getResource(
+                "/queries/reference/first-operand-reference.jsonld").getFile();
+        SpanQueryWrapper sqwi = getJSONQuery(filepath);
+        SpanQuery sq = sqwi.toQuery();
+
+        // 'cat="V" & cat="NP" & cat="PP" & #2 . #1 & #1 ->dep #3 &
+        // #3 . #2
+        assertEquals(
+                "spanReference(spanNext({3: tokens:p:P}, focus(2: focus(#[1,2]spanSegment(focus(#2: "
+                        + "spanSegment(spanRelation(tokens:>:mate/d:HEAD), focus(1: spanNext("
+                        + "{2: tokens:p:V}, {1: <tokens:c:NP />})))), {3: tokens:p:P})))), 3)",
+                sq.toString());
+    }
+
+    @Test
+    public void testSecondOperandRef() throws QueryException {
+
+        String filepath = getClass().getResource(
+                "/queries/reference/second-operand-reference.jsonld").getFile();
+        SpanQueryWrapper sqwi = getJSONQuery(filepath);
+        SpanQuery sq = sqwi.toQuery();
+
+        // 'cat="V" & cat="NP" & cat="PP" & #2 . #1 & #1 ->dep #3 &
+        // #2 . #3
+        assertEquals(
+                "spanReference(spanNext(focus(2: focus(#[1,2]spanSegment(focus(#2: "
+                        + "spanSegment(spanRelation(tokens:>:mate/d:HEAD), focus(1: spanNext("
+                        + "{2: tokens:p:V}, {1: <tokens:c:NP />})))), {3: tokens:p:P}))), "
+                        + "{3: tokens:p:P}), 3)", sq.toString());
+    }
+
+    @Test
+    public void testMultipleReferences() throws QueryException {
+        String filepath = getClass().getResource(
+                "/queries/reference/multiple-references.jsonld").getFile();
+        SpanQueryWrapper sqwi = getJSONQuery(filepath);
+        SpanQuery sq = sqwi.toQuery();
+
+        // 'cat="VP" & cat="NP" & cat="PP" & #1 . #2 & #2 . #3 & #1 .
+        // #3 & #2 ->dep #1'
+        assertEquals(
+                "spanReference(focus(#[1,2]spanSegment(focus(#2: spanSegment(spanRelation(tokens:>:mate/d:HEAD), "
+                        + "focus(2: spanReference(spanNext(focus(1: spanNext(focus(2: spanNext({1: <tokens:c:VP />}, "
+                        + "{2: <tokens:c:NP />})), {3: <tokens:c:PP />})), {3: <tokens:c:PP />}), 3)))), "
+                        + "{1: <tokens:c:VP />})), 1)",
+                sq.toString());
+    }
+
+    @Test
+    public void testDistanceReferences() throws QueryException {
+        String filepath = getClass().getResource(
+        // "/queries/reference/distance-reference.jsonld").getFile();
+                "/queries/reference/bug-multiple-distance.jsonld").getFile();
+        SpanQueryWrapper sqwi = getJSONQuery(filepath);
+        SpanQuery sq = sqwi.toQuery();
+
+        // 'cat="VP" & cat="NP" & cat="PP" & #1 . #2 & #2 . #3 & #1 .
+        // #3 & #2 ->dep #1'
+        assertEquals(
+                "spanReference(focus(#[1,2]spanSegment(focus(#2: spanSegment(spanRelation(tokens:>:stanford/d:tag), "
+                        + "focus(2: spanDistance(focus(1: spanDistance(<tokens:c:vb />, {1: <tokens:c:prp />}, "
+                        + "[(w[1:1], notOrdered, notExcluded)])), {2: <tokens:c:nn />}, [(w[0:2], ordered, notExcluded)])))), "
+                        + "{1: <tokens:c:prp />})), 1)",
+                sq.toString());
+    }
+}
diff --git a/src/test/resources/queries/reference/bug-multiple-distance.jsonld b/src/test/resources/queries/reference/bug-multiple-distance.jsonld
new file mode 100644
index 0000000..4d59d1f
--- /dev/null
+++ b/src/test/resources/queries/reference/bug-multiple-distance.jsonld
@@ -0,0 +1,97 @@
+{
+    "query": {
+        "@type": "koral:group",
+        "operation": "operation:relation",
+        "operands": [
+            {
+                "@type": "koral:reference",
+                "operation": "operation:focus",
+                "classRef": [2],
+                "operands": [{
+                    "@type": "koral:group",
+                    "operation": "operation:sequence",
+                    "operands": [
+                        {
+                            "@type": "koral:reference",
+                            "operation": "operation:focus",
+                            "classRef": [1],
+                            "operands": [{
+                                "@type": "koral:group",
+                                "operation": "operation:sequence",
+                                "operands": [
+                                    {
+                                        "@type": "koral:span",
+                                        "layer": "c",
+                                        "key": "vb",
+                                        "match": "match:eq"
+                                    },
+                                    {
+                                        "@type": "koral:group",
+                                        "operation": "operation:class",
+                                        "classOut": 1,
+                                        "operands": [{
+                                            "@type": "koral:span",
+                                            "layer": "c",
+                                            "key": "prp",
+                                            "match": "match:eq"
+                                        }]
+                                    }
+                                ],
+                                "inOrder": false,
+                                "distances": [{
+                                    "@type": "koral:distance",
+                                    "key": "w",
+                                    "boundary": {
+                                        "@type": "koral:boundary",
+                                        "min": 1,
+                                        "max": 1
+                                    },
+                                    "min": 1,
+                                    "max": 1
+                                }]                                
+                            }]
+                        },
+                        {
+                            "@type": "koral:group",
+                            "operation": "operation:class",
+                            "classOut": 2,
+                            "operands": [{
+                                "@type": "koral:span",
+                                "layer": "c",
+                                "key": "nn",
+                                "match": "match:eq"
+                            }]
+                        }
+                    ],
+                    "distances": [{
+                        "@type": "koral:distance",
+                        "key": "w",
+                        "boundary": {
+                            "@type": "koral:boundary",
+                            "min": 0,
+                            "max": 2
+                        },
+                        "min": 0,
+                        "max": 2
+                    }],
+                    "inOrder": true
+                }]
+            },
+            {
+                "@type": "koral:reference",
+                "operation": "operation:focus",
+                "classRef": [1]
+            }
+        ],
+        "relation": {
+            "@type": "koral:relation",
+            "wrap": {
+                "@type": "koral:term",
+                "foundry": "stanford",
+                "layer": "d",
+                "key":"tag"
+            }
+        }
+    },
+    "meta": {}
+}
diff --git a/src/test/resources/queries/reference/distance-multiple-references.jsonld b/src/test/resources/queries/reference/distance-multiple-references.jsonld
new file mode 100644
index 0000000..31ef098
--- /dev/null
+++ b/src/test/resources/queries/reference/distance-multiple-references.jsonld
@@ -0,0 +1,124 @@
+{
+    "query": {
+        "@type": "koral:group",
+        "operation": "operation:relation",
+        "operands": [
+            {
+                "@type": "koral:reference",
+                "operation": "operation:focus",
+                "classRef": [1],
+                "operands": [{
+                    "@type": "koral:group",
+                    "operation": "operation:relation",
+                    "operands": [
+                        {
+                            "@type": "koral:reference",
+                            "operation": "operation:focus",
+                            "classRef": [3],
+                            "operands": [{
+                                "@type": "koral:group",
+                                "operation": "operation:sequence",
+                                "operands": [
+                                    {
+                                        "@type": "koral:reference",
+                                        "operation": "operation:focus",
+                                        "classRef": [1],
+                                        "operands": [{
+                                            "@type": "koral:group",
+                                            "operation": "operation:sequence",
+                                            "operands": [
+                                                {
+                                                    "@type": "koral:group",
+                                                    "operation": "operation:class",
+                                                    "classOut": 1,
+                                                    "operands": [{
+                                                        "@type": "koral:span",
+                                                        "key": "vb",
+                                                        "match": "match:eq"
+                                                    }]
+                                                },
+                                                {
+                                                    "@type": "koral:group",
+                                                    "operation": "operation:class",
+                                                    "classOut": 2,
+                                                    "operands": [{
+                                                        "@type": "koral:span",
+                                                        "key": "prp",
+                                                        "match": "match:eq"
+                                                    }]
+                                                }
+                                            ],
+                                            "distances": [{
+                                                "@type": "koral:distance",
+                                                "key": "w",
+                                                "boundary": {
+                                                    "@type": "koral:boundary",
+                                                    "min": 0,
+                                                    "max": 1
+                                                },
+                                                "min": 0,
+                                                "max": 1
+                                            }],
+                                            "inOrder": false
+                                        }]
+                                    },
+                                    {
+                                        "@type": "koral:group",
+                                        "operation": "operation:class",
+                                        "classOut": 3,
+                                        "operands": [{
+                                            "@type": "koral:span",
+                                            "key": "nn",
+                                            "match": "match:eq"
+                                        }]
+                                    }
+                                ],
+                                "distances": [{
+                                    "@type": "koral:distance",
+                                    "key": "w",
+                                    "boundary": {
+                                        "@type": "koral:boundary",
+                                        "min": 0,
+                                        "max": 2
+                                    },
+                                    "min": 0,
+                                    "max": 2
+                                }],
+                                "inOrder": false
+                            }]
+                        },
+                        {
+                            "@type": "koral:reference",
+                            "operation": "operation:focus",
+                            "classRef": [2]
+                        }
+                    ],
+                    "relation": {
+                        "@type": "koral:relation",
+                        "wrap": {
+                            "@type": "koral:term",
+                            "foundry": "stanford",
+                            "layer": "d",
+                            "key":"tag"
+                        }
+                    }
+                }]
+            },
+            {
+                "@type": "koral:reference",
+                "operation": "operation:focus",
+                "classRef": [3]
+            }
+        ],
+        "relation": {
+            "@type": "koral:relation",
+            "wrap": {
+                "@type": "koral:term",
+                "foundry": "stanford",
+                "layer": "d",
+                "key":"tag"
+            }
+        }
+    },
+    "meta": {}
+}
diff --git a/src/test/resources/queries/reference/distance-reference.jsonld b/src/test/resources/queries/reference/distance-reference.jsonld
new file mode 100644
index 0000000..cf23596
--- /dev/null
+++ b/src/test/resources/queries/reference/distance-reference.jsonld
@@ -0,0 +1,99 @@
+{
+    "query": {
+        "@type": "koral:group",
+        "operation": "operation:relation",
+        "operands": [
+            {
+                "@type": "koral:reference",
+                "operation": "operation:focus",
+                "classRef": [3],
+                "operands": [{
+                    "@type": "koral:group",
+                    "operation": "operation:sequence",
+                    "operands": [
+                        {
+                            "@type": "koral:reference",
+                            "operation": "operation:focus",
+                            "classRef": [1],
+                            "operands": [{
+                                "@type": "koral:group",
+                                "operation": "operation:sequence",
+                                "operands": [
+                                    {
+                                        "@type": "koral:group",
+                                        "operation": "operation:class",
+                                        "classOut": 1,
+                                        "operands": [{
+                                            "@type": "koral:span",
+                                            "key": "vb",
+                                            "match": "match:eq"
+                                        }]
+                                    },
+                                    {
+                                        "@type": "koral:group",
+                                        "operation": "operation:class",
+                                        "classOut": 2,
+                                        "operands": [{
+                                            "@type": "koral:span",
+                                            "key": "prp",
+                                            "match": "match:eq"
+                                        }]
+                                    }
+                                ],
+                                "distances": [{
+                                    "@type": "koral:distance",
+                                    "key": "w",
+                                    "boundary": {
+                                        "@type": "koral:boundary",
+                                        "min": 0,
+                                        "max": 1
+                                    },
+                                    "min": 0,
+                                    "max": 1
+                                }],
+                                "inOrder": false
+                            }]
+                        },
+                        {
+                            "@type": "koral:group",
+                            "operation": "operation:class",
+                            "classOut": 3,
+                            "operands": [{
+                                "@type": "koral:span",
+                                "key": "nn",
+                                "match": "match:eq"
+                            }]
+                        }
+                    ],
+                    "distances": [{
+                        "@type": "koral:distance",
+                        "key": "w",
+                        "boundary": {
+                            "@type": "koral:boundary",
+                            "min": 0,
+                            "max": 2
+                        },
+                        "min": 0,
+                        "max": 2
+                    }],
+                    "inOrder": false
+                }]
+            },
+            {
+                "@type": "koral:reference",
+                "operation": "operation:focus",
+                "classRef": [2]
+            }
+        ],
+        "relation": {
+            "@type": "koral:relation",
+            "wrap": {
+                "@type": "koral:term",
+                "foundry": "stanford",
+                "layer": "d",
+                "key":"tag"
+            }
+        }
+    },
+    "meta": {}
+}
diff --git a/src/test/resources/queries/reference/first-operand-reference.jsonld b/src/test/resources/queries/reference/first-operand-reference.jsonld
new file mode 100644
index 0000000..44792db
--- /dev/null
+++ b/src/test/resources/queries/reference/first-operand-reference.jsonld
@@ -0,0 +1,86 @@
+{
+    "query": {
+        "@type": "koral:group",
+        "operation": "operation:sequence",
+        "operands": [
+            {
+                "@type": "koral:reference",
+                "operation": "operation:focus",
+                "classRef": [3]
+            },
+            {
+                "@type": "koral:reference",
+                "operation": "operation:focus",
+                "classRef": [2],
+                "operands": [{
+                    "@type": "koral:group",
+                    "operation": "operation:relation",
+                    "operands": [
+                        {
+                            "@type": "koral:reference",
+                            "operation": "operation:focus",
+                            "classRef": [1],
+                            "operands": [{
+                                "@type": "koral:group",
+                                "operation": "operation:sequence",
+                                "operands": [
+                                    {
+                                        "@type": "koral:group",
+                                        "operation": "operation:class",
+                                        "classOut": 2,
+                                        "operands": [{
+                                            "@type": "koral:token",
+                                            "wrap": {
+                                                "@type": "koral:term",
+                                                "layer": "p",
+                                                "key": "V",
+                                                "match": "match:eq"
+                                            }
+                                        }]
+                                    },
+                                    {
+                                        "@type": "koral:group",
+                                        "operation": "operation:class",
+                                        "classOut": 1,
+                                        "operands": [{
+                                            "@type": "koral:span",
+                                            "layer": "c",
+                                            "key": "NP",
+                                            "match": "match:eq"
+                                        }]
+                                    }                                    
+                                ],
+                                "inOrder": true
+                            }]
+                        },
+                        {
+                            "@type": "koral:group",
+                            "operation": "operation:class",
+                            "classOut": 3,
+                            "operands": [{
+                                "@type": "koral:token",
+                                "wrap": {
+                                    "@type": "koral:term",
+                                    "layer": "p",
+                                    "key": "P",
+                                    "match": "match:eq"
+                                }
+                            }]
+                        }
+                    ],
+                    "relation": {
+                        "@type": "koral:relation",
+                        "wrap": {
+                            "@type": "koral:term",
+                            "foundry": "mate",
+                            "layer": "d",
+                            "key" : "HEAD"
+                        }
+                    }
+                }]
+            }         
+        ],
+        "inOrder": true
+    },
+    "meta": {}
+}
diff --git a/src/test/resources/queries/reference/multiple-references.jsonld b/src/test/resources/queries/reference/multiple-references.jsonld
new file mode 100644
index 0000000..f94cfb5
--- /dev/null
+++ b/src/test/resources/queries/reference/multiple-references.jsonld
@@ -0,0 +1,97 @@
+{
+    "query": {
+        "@type": "koral:group",
+        "operation": "operation:relation",
+        "operands": [
+            {
+                "@type": "koral:reference",
+                "operation": "operation:focus",
+                "classRef": [2],
+                "operands": [{
+                    "@type": "koral:group",
+                    "operation": "operation:sequence",
+                    "operands": [
+                        {
+                            "@type": "koral:reference",
+                            "operation": "operation:focus",
+                            "classRef": [1],
+                            "operands": [{
+                                "@type": "koral:group",
+                                "operation": "operation:sequence",
+                                "operands": [
+                                    {
+                                        "@type": "koral:reference",
+                                        "operation": "operation:focus",
+                                        "classRef": [2],
+                                        "operands": [{
+                                            "@type": "koral:group",
+                                            "operation": "operation:sequence",
+                                            "operands": [
+                                                {
+                                                    "@type": "koral:group",
+                                                    "operation": "operation:class",
+                                                    "classOut": 1,
+                                                    "operands": [{
+                                                        "@type": "koral:span",
+                                                        "layer": "c",
+                                                        "key": "VP",
+                                                        "match": "match:eq"
+                                                    }]
+                                                },
+                                                {
+                                                    "@type": "koral:group",
+                                                    "operation": "operation:class",
+                                                    "classOut": 2,
+                                                    "operands": [{
+                                                        "@type": "koral:span",
+                                                        "layer": "c",
+                                                        "key": "NP",
+                                                        "match": "match:eq"
+                                                    }]
+                                                }
+                                            ],
+                                            "inOrder": true
+                                        }]
+                                    },
+                                    {
+                                        "@type": "koral:group",
+                                        "operation": "operation:class",
+                                        "classOut": 3,
+                                        "operands": [{
+                                            "@type": "koral:span",
+                                            "layer": "c",
+                                            "key": "PP",
+                                            "match": "match:eq"
+                                        }]
+                                    }
+                                ],
+                                "inOrder": true
+                            }]
+                        },
+                        {
+                            "@type": "koral:reference",
+                            "operation": "operation:focus",
+                            "classRef": [3]
+                        }
+                    ],
+                    "inOrder": true
+                }]
+            },
+            {
+                "@type": "koral:reference",
+                "operation": "operation:focus",
+                "classRef": [1]
+            }
+        ],
+        "relation": {
+            "@type": "koral:relation",
+            "wrap": {
+                "@type": "koral:term",
+                "foundry" : "mate",
+                "layer": "d",
+                "key" : "HEAD"
+            }
+        }
+    },
+    "meta": {}
+}
diff --git a/src/test/resources/queries/reference/second-operand-reference.jsonld b/src/test/resources/queries/reference/second-operand-reference.jsonld
new file mode 100644
index 0000000..47388cc
--- /dev/null
+++ b/src/test/resources/queries/reference/second-operand-reference.jsonld
@@ -0,0 +1,86 @@
+{
+    "query": {
+        "@type": "koral:group",
+        "operation": "operation:sequence",
+        "operands": [
+            {
+                "@type": "koral:reference",
+                "operation": "operation:focus",
+                "classRef": [2],
+                "operands": [{
+                    "@type": "koral:group",
+                    "operation": "operation:relation",
+                    "operands": [
+                        {
+                            "@type": "koral:reference",
+                            "operation": "operation:focus",
+                            "classRef": [1],
+                            "operands": [{
+                                "@type": "koral:group",
+                                "operation": "operation:sequence",
+                                "operands": [
+                                    {
+                                        "@type": "koral:group",
+                                        "operation": "operation:class",
+                                        "classOut": 2,
+                                        "operands": [{
+                                            "@type": "koral:token",
+                                            "wrap": {
+                                                "@type": "koral:term",
+                                                "layer": "p",
+                                                "key": "V",
+                                                "match": "match:eq"
+                                            }
+                                        }]
+                                    },
+                                    {
+                                        "@type": "koral:group",
+                                        "operation": "operation:class",
+                                        "classOut": 1,
+                                        "operands": [{
+                                            "@type": "koral:span",
+                                            "layer": "c",
+                                            "key": "NP",
+                                            "match": "match:eq"
+                                        }]
+                                    }                                    
+                                ],
+                                "inOrder": true
+                            }]
+                        },
+                        {
+                            "@type": "koral:group",
+                            "operation": "operation:class",
+                            "classOut": 3,
+                            "operands": [{
+                                "@type": "koral:token",
+                                "wrap": {
+                                    "@type": "koral:term",
+                                    "layer": "p",
+                                    "key": "P",
+                                    "match": "match:eq"
+                                }
+                            }]
+                        }
+                    ],
+                    "relation": {
+                        "@type": "koral:relation",
+                        "wrap": {
+                            "@type": "koral:term",
+                            "foundry": "mate",
+                            "layer": "d",
+                            "key" : "HEAD"
+                        }
+                    }
+                }]
+            },
+            {
+                "@type": "koral:reference",
+                "operation": "operation:focus",
+                "classRef": [3]
+            }
+        ],
+        "inOrder": true
+    },
+    "meta": {}
+}