Merge "Improve Benchmarking to check no-snippets retrieval"
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/java/de/ids_mannheim/korap/search/TestMetaFields.java b/src/test/java/de/ids_mannheim/korap/search/TestMetaFields.java
index 4eaa4db..d91e4f1 100644
--- a/src/test/java/de/ids_mannheim/korap/search/TestMetaFields.java
+++ b/src/test/java/de/ids_mannheim/korap/search/TestMetaFields.java
@@ -365,6 +365,19 @@
         assertEquals("base/p", ks.getMeta().getContext().getSpanContext());
     };
 
+  
+    @Test
+    public void searchMetaAndSnippets () throws IOException {
+
+        // All fields
+        String jsonString = getJsonString(getClass()
+                .getResource("/queries/metas/no-snippets.jsonld")
+                .getFile());
+
+        Krill ks = new Krill(jsonString);
+        assertFalse(ks.getMeta().hasSnippets());
+    };
+
 
     @Test
     public void searchMetaAssets () throws IOException {
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"
+}
+
diff --git a/src/test/resources/queries/metas/no-snippets.jsonld b/src/test/resources/queries/metas/no-snippets.jsonld
new file mode 100644
index 0000000..f50e54b
--- /dev/null
+++ b/src/test/resources/queries/metas/no-snippets.jsonld
@@ -0,0 +1,103 @@
+{
+    "meta": {
+        "startIndex": 0,
+        "snippets": false,
+        "count": 50,
+        "cutOff": true,
+        "fields": [
+            "corpusSigle",
+            "textSigle",
+            "pubDate",
+            "pubPlace",
+            "availability",
+            "textClass"
+        ],
+        "timeout": 90000
+    },
+    "query": {
+        "@type": "koral:token",
+        "wrap": {
+            "@type": "koral:term",
+            "match": "match:eq",
+            "layer": "orth",
+            "key": "Sockenpuppe",
+            "foundry": "opennlp",
+            "rewrites": [
+                {
+                    "@type": "koral:rewrite",
+                    "src": "Kustvakt",
+                    "operation": "operation:injection",
+                    "scope": "foundry"
+                }
+            ]
+        }
+    },
+    "collection": {
+        "@type": "koral:docGroup",
+        "operation": "operation:and",
+        "operands": [
+            {
+                "operands": [
+                    {
+                        "@type": "koral:doc",
+                        "match": "match:eq",
+                        "type": "type:regex",
+                        "value": "CC-BY.*",
+                        "key": "availability"
+                    },
+                    {
+                        "operands": [
+                            {
+                                "@type": "koral:doc",
+                                "match": "match:eq",
+                                "type": "type:regex",
+                                "value": "ACA.*",
+                                "key": "availability"
+                            },
+                            {
+                                "operands": [
+                                    {
+                                        "@type": "koral:doc",
+                                        "match": "match:eq",
+                                        "type": "type:regex",
+                                        "value": "QAO-NC",
+                                        "key": "availability"
+                                    },
+                                    {
+                                        "@type": "koral:doc",
+                                        "match": "match:eq",
+                                        "type": "type:regex",
+                                        "value": "QAO.*",
+                                        "key": "availability"
+                                    }
+                                ],
+                                "@type": "koral:docGroup",
+                                "operation": "operation:or"
+                            }
+                        ],
+                        "@type": "koral:docGroup",
+                        "operation": "operation:or"
+                    }
+                ],
+                "@type": "koral:docGroup",
+                "operation": "operation:or"
+            },
+            {
+                "@type": "koral:doc",
+                "match": "match:eq",
+                "type": "type:regex",
+                "value": "W.D.*",
+                "key": "corpusSigle"
+            }
+        ],
+        "rewrites": [
+            {
+                "@type": "koral:rewrite",
+                "src": "Kustvakt",
+                "operation": "operation:insertion",
+                "scope": "availability(ALL)"
+            }
+        ]
+    },
+    "@context": "http://korap.ids-mannheim.de/ns/koral/0.3/context.jsonld"
+}
\ No newline at end of file