Added reference query deserialization

Change-Id: I145e608ae114f34ced7788fa124aa0508d21ea5c
diff --git a/src/main/java/de/ids_mannheim/korap/KrillQuery.java b/src/main/java/de/ids_mannheim/korap/KrillQuery.java
index 578d10b..5a05bd5 100644
--- a/src/main/java/de/ids_mannheim/korap/KrillQuery.java
+++ b/src/main/java/de/ids_mannheim/korap/KrillQuery.java
@@ -9,6 +9,8 @@
 
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
 
 import de.ids_mannheim.korap.query.QueryBuilder;
 import de.ids_mannheim.korap.query.SpanWithinQuery;
@@ -17,6 +19,7 @@
 import de.ids_mannheim.korap.query.wrap.SpanClassQueryWrapper;
 import de.ids_mannheim.korap.query.wrap.SpanFocusQueryWrapper;
 import de.ids_mannheim.korap.query.wrap.SpanQueryWrapper;
+import de.ids_mannheim.korap.query.wrap.SpanReferenceQueryWrapper;
 import de.ids_mannheim.korap.query.wrap.SpanRegexQueryWrapper;
 import de.ids_mannheim.korap.query.wrap.SpanRelationWrapper;
 import de.ids_mannheim.korap.query.wrap.SpanRepetitionQueryWrapper;
@@ -220,7 +223,6 @@
                     throw new QueryException(766,
                             "Peripheral references are currently not supported");
                 }
-                ;
 
                 JsonNode operands = json.get("operands");
 
@@ -378,6 +380,11 @@
         if (DEBUG)
             log.trace("Operands are {}", operands);
 
+        SpanQueryWrapper spanReferenceQueryWrapper = _operationReferenceFromJSON(json, operands);
+        if (spanReferenceQueryWrapper != null) {
+            return spanReferenceQueryWrapper;
+        }
+
         // Branch on operation
         switch (operation) {
             case "operation:junction":
@@ -417,6 +424,87 @@
         throw new QueryException(711, "Unknown group operation");
     };
 
+    private SpanQueryWrapper _operationReferenceFromJSON(JsonNode node, JsonNode operands)
+            throws QueryException {
+        boolean isReference = false;
+        int classNum = -1;
+        int refOperandNum = -1;
+        JsonNode childNode;
+
+        for (int i = 0; i < operands.size(); i++) {
+            childNode = operands.get(i);
+            if (childNode.has("@type")
+                    && childNode.get("@type").asText()
+                            .equals("koral:reference")
+                    && childNode.has("operation")
+                    && childNode.get("operation").asText()
+                            .equals("operation:focus")
+                    && !childNode.has("operands")) {
+
+                if (childNode.has("classRef")) {
+                    classNum = childNode.get("classRef").get(0).asInt();
+                    refOperandNum = i;
+                    isReference = true;
+                    break;
+                }
+            }
+        }
+
+        if (isReference) {
+            JsonNode resolvedNode = _resolveReference(node, operands,
+                    refOperandNum, classNum);
+            return new SpanReferenceQueryWrapper(fromJson(resolvedNode),
+                    (byte) classNum);
+        }
+
+        return null;
+    }
+
+    private JsonNode _resolveReference(JsonNode node, JsonNode operands,
+            int refOperandNum, int classNum) throws QueryException {
+        JsonNode referent = null;
+        ObjectMapper m = new ObjectMapper();
+        ArrayNode newOperands = m.createArrayNode();
+        boolean isReferentFound = false;
+        for (int i = 0; i < operands.size(); i++) {
+            if (i != refOperandNum) {
+                if (!isReferentFound) {
+                    referent = _extractReferentClass(operands.get(i), classNum);
+                    if (referent != null) isReferentFound = true;
+                }
+                newOperands.insert(i, operands.get(i));
+            }
+        }
+
+        if (isReferentFound) {
+            newOperands.insert(refOperandNum, referent);
+            ((ObjectNode) node).set("operands", newOperands);
+            return node;
+        }
+        else
+            throw new QueryException("Referent node is not found");
+
+    }
+
+    private JsonNode _extractReferentClass(JsonNode node, int classNum) {
+        JsonNode referent;
+        if (node.has("classOut") && node.get("classOut").asInt() == classNum) {
+            // System.out.println("found: " + node.toString());
+            return node;
+        }
+        else {
+            if (node.has("operands") && node.get("operands").isArray()) {
+                for (JsonNode childOperand : node.get("operands")) {
+                    referent = _extractReferentClass(childOperand, classNum);
+                    if (referent != null) {
+                        return referent;
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
 
     private SpanQueryWrapper _operationRelationFromJson (JsonNode operands,
             JsonNode relation) throws QueryException {
diff --git a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanReferenceQueryWrapper.java b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanReferenceQueryWrapper.java
new file mode 100644
index 0000000..02a734f
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanReferenceQueryWrapper.java
@@ -0,0 +1,47 @@
+package de.ids_mannheim.korap.query.wrap;
+
+import org.apache.lucene.search.spans.SpanQuery;
+
+import de.ids_mannheim.korap.query.SpanReferenceQuery;
+import de.ids_mannheim.korap.util.QueryException;
+
+public class SpanReferenceQueryWrapper extends SpanQueryWrapper {
+
+    private SpanQueryWrapper subQuery;
+    private byte classNum;
+
+    public SpanReferenceQueryWrapper (SpanQueryWrapper subQueryWrapper,
+            byte classNum) {
+        this.subQuery = subQueryWrapper;
+        if (subQuery != null) {
+            this.isNull = false;
+        }
+        else
+            return;
+
+        if (subQuery.isEmpty) {
+            this.isEmpty = true;
+            return;
+        }
+
+        if (classNum < 0) {
+            throw new IllegalArgumentException(
+                    "Class number must be bigger than 0.");
+        }
+        this.classNum = classNum;
+    }
+    
+    @Override
+    public SpanQuery toQuery() throws QueryException {
+
+        if (this.isNull() || this.isEmpty()) {
+            return null;
+        }
+
+        SpanQuery sq = subQuery.retrieveNode(this.retrieveNode).toQuery();
+        if (sq == null) return null;
+        
+        return new SpanReferenceQuery(sq, classNum, true);
+    }
+
+}
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": {}
+}