Merge "Test 'no snippets' deserialization"
diff --git a/Changes b/Changes
index 828386e..f2dd94e 100644
--- a/Changes
+++ b/Changes
@@ -1,9 +1,10 @@
-0.59.3 2021-02-18
+0.59.3 2021-06-28
     - [feature] Added "missing query reference" status code (diewald)
     - [cleanup] Added test coverage checking with
       $ mvn cobertura:cobertura (diewald, kupietz)
     - [cleanup] Added test statistics with referTo and pubDate (margaretha)
     - [cleanup] Fixed TestCollectionCache (margaretha)
+    - [cleanup] Fixed negative class number bug in span reference query (margaretha)
 
 0.59.2 2020-07-24
     - [feature] Add fingerprint method to index (diewald)
diff --git a/src/main/java/de/ids_mannheim/korap/KrillQuery.java b/src/main/java/de/ids_mannheim/korap/KrillQuery.java
index 0bcde58..a913460 100644
--- a/src/main/java/de/ids_mannheim/korap/KrillQuery.java
+++ b/src/main/java/de/ids_mannheim/korap/KrillQuery.java
@@ -538,8 +538,8 @@
         if (isReference) {
             JsonNode resolvedNode = _resolveReference(node, operands,
                     refOperandNum, classNum);
-            return new SpanReferenceQueryWrapper(this._fromKoral(resolvedNode),
-                    (byte) classNum);
+            SpanQueryWrapper queryWrapper = this._fromKoral(resolvedNode);
+            return new SpanReferenceQueryWrapper(queryWrapper,classNum);
         }
 
         return null;
diff --git a/src/main/java/de/ids_mannheim/korap/query/SpanReferenceQuery.java b/src/main/java/de/ids_mannheim/korap/query/SpanReferenceQuery.java
index c50bc78..0b3fbf2 100644
--- a/src/main/java/de/ids_mannheim/korap/query/SpanReferenceQuery.java
+++ b/src/main/java/de/ids_mannheim/korap/query/SpanReferenceQuery.java
@@ -20,7 +20,7 @@
  * For instance in the following Annis query
  * 
  * <pre>
- * cat="vb" & cat="prp" & cat="nn" & #1 .{0,1} #2 & #1 .{0,2} #3
+ * cat="vb" & cat="prp" & cat="nn" & #1 .1 #2 & #1 .{1,2} #3
  * & #3 -> #2
  * </pre>
  * 
@@ -36,9 +36,12 @@
  * SpanReferenceQuery ensures that cat="prp" spans in the third
  * operation are the same as the those in the first operation by
  * matching their positions using the class number 2 payloads kept in
- * spans focussing on the class number 3 (it keeps all the payloads
+ * spans focusing on the class number 3 (it keeps all the payloads
  * from previous operations).
  * 
+ * Distance in ANNIS starts with 1. 
+ * "VB" .1 "NN" means VB is directly on the left side of (next to) NN.
+ * 
  * @author margaretha
  *
  */
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
index 830fbfe..e537b1e 100644
--- a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanReferenceQueryWrapper.java
+++ b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanReferenceQueryWrapper.java
@@ -12,7 +12,7 @@
 
 
     public SpanReferenceQueryWrapper (SpanQueryWrapper subQueryWrapper,
-                                      byte classNum) {
+                                      int classNum) {
         this.subQuery = subQueryWrapper;
         if (subQuery != null) {
             this.isNull = false;
@@ -29,7 +29,7 @@
             throw new IllegalArgumentException(
                     "Class number must be bigger than 0.");
         }
-        this.classNum = classNum;
+        this.classNum = (byte) classNum;
         this.maybeUnsorted = subQueryWrapper.maybeUnsorted();
     }
 
diff --git a/src/test/java/de/ids_mannheim/korap/query/TestSpanReferenceQueryJSON.java b/src/test/java/de/ids_mannheim/korap/query/TestSpanReferenceQueryJSON.java
index 83bfb60..f515733 100644
--- a/src/test/java/de/ids_mannheim/korap/query/TestSpanReferenceQueryJSON.java
+++ b/src/test/java/de/ids_mannheim/korap/query/TestSpanReferenceQueryJSON.java
@@ -12,7 +12,24 @@
 import de.ids_mannheim.korap.util.QueryException;
 
 public class TestSpanReferenceQueryJSON {
-
+    
+    @Test
+    public void testNegativeClassNumBug () throws IOException, QueryException {
+        String filepath = getClass()
+                .getResource(
+                        "/queries/bugs/annis_reference_bug.jsonld")
+                .getFile();
+        SpanQueryWrapper sqwi = getJsonQuery(filepath);
+        SpanQuery sq = sqwi.toQuery();
+        
+        // "ich" & pos="VVFIN" & #1 ->malt/d[func="SUBJ"] #2 & #1 . #2
+        assertEquals(sq.toString(), "spanReference(spanNext("
+                + "focus(129: focus(#[1,2]spanSegment({130: tokens:tt/p:VVFIN}, "
+                + "focus(#2: spanSegment(spanRelation(tokens:>:malt/d:SUBJ), "
+                + "{129: tokens:s:ich}),sorting)),sorting),sorting), "
+                + "{130: tokens:tt/p:VVFIN}), -126)");
+    }
+    
     @Test
     public void testFirstOperandRef () throws IOException, QueryException {
 
diff --git a/src/test/resources/queries/bugs/annis_reference_bug.jsonld b/src/test/resources/queries/bugs/annis_reference_bug.jsonld
new file mode 100644
index 0000000..2b7c4d2
--- /dev/null
+++ b/src/test/resources/queries/bugs/annis_reference_bug.jsonld
@@ -0,0 +1,86 @@
+{
+    "operands": [
+        {
+            "operands": [
+                {
+                    "operands": [
+                        {
+                            "operands": [
+                                {
+                                    "@type": "koral:token",
+                                    "wrap": {
+                                        "@type": "koral:term",
+                                        "match": "match:eq",
+                                        "layer": "orth",
+                                        "key": "ich",
+                                        "foundry": "opennlp",
+                                        "rewrites": [
+                                            {
+                                                "@type": "koral:rewrite",
+                                                "src": "Kustvakt",
+                                                "operation": "operation:injection",
+                                                "scope": "foundry"
+                                            }
+                                        ]
+                                    }
+                                }
+                            ],
+                            "classOut": 129,
+                            "@type": "koral:group",
+                            "operation": "operation:class"
+                        },
+                        {
+                            "operands": [
+                                {
+                                    "@type": "koral:token",
+                                    "wrap": {
+                                        "@type": "koral:term",
+                                        "match": "match:eq",
+                                        "layer": "p",
+                                        "key": "VVFIN",
+                                        "foundry": "tt",
+                                        "rewrites": [
+                                            {
+                                                "@type": "koral:rewrite",
+                                                "src": "Kustvakt",
+                                                "operation": "operation:injection",
+                                                "scope": "foundry"
+                                            }
+                                        ]
+                                    }
+                                }
+                            ],
+                            "classOut": 130,
+                            "@type": "koral:group",
+                            "operation": "operation:class"
+                        }
+                    ],
+                    "@type": "koral:group",
+                    "relType": {
+                        "@type": "koral:relation",
+                        "wrap": {
+                            "foundry": "malt",
+                            "@type": "koral:term",
+                            "match": "match:eq",
+                            "layer": "d",
+                            "key": "SUBJ"
+                        }
+                    },
+                    "operation": "operation:relation"
+                }
+            ],
+            "@type": "koral:reference",
+            "operation": "operation:focus",
+            "classRef": [129]
+        },
+        {
+            "@type": "koral:reference",
+            "operation": "operation:focus",
+            "classRef": [130]
+        }
+    ],
+    "@type": "koral:group",
+    "inOrder": true,
+    "operation": "operation:sequence"
+}
+