Fixed bug in segments with negated components

Change-Id: I520115e4c1fc2ab497c6b5d8a322c7ea54b0a97d
diff --git a/Changes b/Changes
index 60ba114..571803c 100644
--- a/Changes
+++ b/Changes
@@ -1,5 +1,6 @@
-0.59.1 2020-01-28
+0.59.1 2020-02-04
     - [bugfix] Fix bug in classed group queries (diewald)
+    - [bugfix] Fix bug in segments with negated components (diewald)
 
 0.59.0 2019-11-28
     - [bugfix] Fix offset retrieval in concurrent searches
diff --git a/src/main/java/de/ids_mannheim/korap/KrillQuery.java b/src/main/java/de/ids_mannheim/korap/KrillQuery.java
index f6f1c74..abfc16e 100644
--- a/src/main/java/de/ids_mannheim/korap/KrillQuery.java
+++ b/src/main/java/de/ids_mannheim/korap/KrillQuery.java
@@ -1070,6 +1070,7 @@
 
                         for (JsonNode operand : operands) {
                             SpanQueryWrapper part = this._segFromJson(operand);
+                           
                             if (part instanceof SpanAlterQueryWrapper) {
                                 ssegqw.with((SpanAlterQueryWrapper) part);
                             }
@@ -1347,7 +1348,7 @@
                 saqw.or(v);
             };
                 
-			if (match.equals("match:ne")) {
+			if (match.equals("match:ne")) {                
 				if (DEBUG)
 					log.trace("Term is negated");
 
diff --git a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanSegmentQueryWrapper.java b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanSegmentQueryWrapper.java
index 4d1c712..cbc715b 100644
--- a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanSegmentQueryWrapper.java
+++ b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanSegmentQueryWrapper.java
@@ -119,9 +119,12 @@
 
     public SpanSegmentQueryWrapper with (SpanAlterQueryWrapper alter) {
         if (!alter.isNull()) {
-            if (alter.isNegative())
-                this.isNegative = true;
-            this.inclusive.add(alter);
+            if (alter.isNegative()) {
+                this.exclusive.add(alter);
+            }
+            else {
+                this.inclusive.add(alter);
+            };
             this.isNull = false;
         };
         return this;
@@ -167,18 +170,14 @@
 
 
     public SpanSegmentQueryWrapper without (SpanAlterQueryWrapper alter) {
-        if (!alter.isNull()) {
-            if (alter.isNegative()) {
-                this.inclusive.add(alter);
-            }
-            else {
-                this.exclusive.add(alter);
-            };
-            this.isNull = false;
-        };
-        return this;
+        if (alter.isNegative()) {
+            alter.setNegative(false);
+        } else {
+            alter.setNegative(true);
+        }
+        return this.with(alter);
     };
-
+   
 
     public SpanSegmentQueryWrapper without (SpanSegmentQueryWrapper seg) {
         if (!seg.isNull()) {
diff --git a/src/test/java/de/ids_mannheim/korap/query/TestKrillQueryJSON.java b/src/test/java/de/ids_mannheim/korap/query/TestKrillQueryJSON.java
index 5c6c565..0613d31 100644
--- a/src/test/java/de/ids_mannheim/korap/query/TestKrillQueryJSON.java
+++ b/src/test/java/de/ids_mannheim/korap/query/TestKrillQueryJSON.java
@@ -709,9 +709,56 @@
         catch (QueryException e) {
         };
     };
-    
 
     @Test
+    public void queryJSONnegationInGroup () throws QueryException {
+        // [orth=laufe/i & base!=Lauf]
+        String json = getJsonString(getClass()
+                                    .getResource("/queries/segment/negation-in-group.jsonld")
+                                    .getFile());
+
+        KrillQuery kq = new KrillQuery("tokens");
+        assertEquals("spanNot(tokens:i:laufe, tokens:tt/l:Lauf, 0, 0)",
+                     kq.fromKoral(json).toQuery().toString());
+    };   
+
+    @Test
+    public void queryJSONnegationInGroupAlt () throws QueryException {
+        // [orth=laufe/i & base!=Lauf & opennlp/l!=Lauf]
+        String json = getJsonString(getClass()
+                                    .getResource("/queries/segment/negation-in-group-alt.jsonld")
+                                    .getFile());
+
+        KrillQuery kq = new KrillQuery("tokens");
+        assertEquals("spanNot(tokens:i:laufe, spanOr([tokens:tt/l:Lauf, tokens:opennlp/l:Lauf]), 0, 0)",
+                     kq.fromKoral(json).toQuery().toString());
+    };   
+
+    @Test
+    public void queryJSONnegationInGroupAlt2 () throws QueryException {
+        // [orth=laufe/i & base!=Lauf & opennlp/l=Lauf]
+        String json = getJsonString(getClass()
+                                    .getResource("/queries/segment/negation-in-group-alt-2.jsonld")
+                                    .getFile());
+
+        KrillQuery kq = new KrillQuery("tokens");
+        assertEquals("spanNot(spanSegment(tokens:i:laufe, tokens:opennlp/l:Lauf), tokens:tt/l:Lauf, 0, 0)",
+                     kq.fromKoral(json).toQuery().toString());
+    };   
+    
+    @Test
+    public void queryJSONnegationInGroupRegex () throws QueryException {
+        // [orth=laufe/i & base!=/Lauf/]
+        String json = getJsonString(getClass()
+                                    .getResource("/queries/segment/negation-in-group-regex.jsonld")
+                                    .getFile());
+
+        KrillQuery kq = new KrillQuery("tokens");
+        assertEquals("spanNot(tokens:i:laufe, SpanMultiTermQueryWrapper(tokens:/tt/l:Lauf/), 0, 0)",
+                     kq.fromKoral(json).toQuery().toString());
+    };   
+    
+    @Test
     public void queryJSONregexVectorRewrite () throws QueryException {
         // der [base=f.?o|base=b[au]r|base=.*|base=ab+c]
         try {
diff --git a/src/test/resources/queries/segment/negation-in-group-alt-2.jsonld b/src/test/resources/queries/segment/negation-in-group-alt-2.jsonld
new file mode 100644
index 0000000..d52a976
--- /dev/null
+++ b/src/test/resources/queries/segment/negation-in-group-alt-2.jsonld
@@ -0,0 +1,37 @@
+{
+  "@context": "http://ids-mannheim.de/ns/KorAP/json-ld/v0.1/context.jsonld",
+  "query": {
+    "@type": "koral:token",
+    "wrap": {
+      "@type": "koral:termGroup",
+      "operands": [
+        {
+          "@type": "koral:term",
+          "flags": [
+            "flags:caseInsensitive"
+          ],
+          "foundry": "opennlp",
+          "key": "laufe",
+          "layer": "orth",
+          "match": "match:eq"
+        },
+        {
+          "@type": "koral:term",
+          "foundry": "tt",
+          "key": "Lauf",
+          "layer": "lemma",
+          "match": "match:ne"
+        },
+        {
+          "@type": "koral:term",
+          "foundry": "opennlp",
+          "key": "Lauf",
+          "layer": "lemma",
+          "match": "match:eq"
+        }
+
+      ],
+      "relation": "relation:and"
+    }
+  }
+}
diff --git a/src/test/resources/queries/segment/negation-in-group-alt.jsonld b/src/test/resources/queries/segment/negation-in-group-alt.jsonld
new file mode 100644
index 0000000..0854eea
--- /dev/null
+++ b/src/test/resources/queries/segment/negation-in-group-alt.jsonld
@@ -0,0 +1,37 @@
+{
+  "@context": "http://ids-mannheim.de/ns/KorAP/json-ld/v0.1/context.jsonld",
+  "query": {
+    "@type": "koral:token",
+    "wrap": {
+      "@type": "koral:termGroup",
+      "operands": [
+        {
+          "@type": "koral:term",
+          "flags": [
+            "flags:caseInsensitive"
+          ],
+          "foundry": "opennlp",
+          "key": "laufe",
+          "layer": "orth",
+          "match": "match:eq"
+        },
+        {
+          "@type": "koral:term",
+          "foundry": "tt",
+          "key": "Lauf",
+          "layer": "lemma",
+          "match": "match:ne"
+        },
+        {
+          "@type": "koral:term",
+          "foundry": "opennlp",
+          "key": "Lauf",
+          "layer": "lemma",
+          "match": "match:ne"
+        }
+
+      ],
+      "relation": "relation:and"
+    }
+  }
+}
diff --git a/src/test/resources/queries/segment/negation-in-group-regex.jsonld b/src/test/resources/queries/segment/negation-in-group-regex.jsonld
new file mode 100644
index 0000000..b0a3b72
--- /dev/null
+++ b/src/test/resources/queries/segment/negation-in-group-regex.jsonld
@@ -0,0 +1,30 @@
+{
+  "@context": "http://ids-mannheim.de/ns/KorAP/json-ld/v0.1/context.jsonld",
+  "query": {
+    "@type": "koral:token",
+    "wrap": {
+      "@type": "koral:termGroup",
+      "operands": [
+        {
+          "@type": "koral:term",
+          "flags": [
+            "flags:caseInsensitive"
+          ],
+          "foundry": "opennlp",
+          "key": "laufe",
+          "layer": "orth",
+          "match": "match:eq"
+        },
+        {
+          "@type": "koral:term",
+          "type" :"type:regex",
+          "foundry": "tt",
+          "key": "Lauf",
+          "layer": "lemma",
+          "match": "match:ne"
+        }
+      ],
+      "relation": "relation:and"
+    }
+  }
+}
diff --git a/src/test/resources/queries/segment/negation-in-group.jsonld b/src/test/resources/queries/segment/negation-in-group.jsonld
new file mode 100644
index 0000000..83e5b73
--- /dev/null
+++ b/src/test/resources/queries/segment/negation-in-group.jsonld
@@ -0,0 +1,29 @@
+{
+  "@context": "http://ids-mannheim.de/ns/KorAP/json-ld/v0.1/context.jsonld",
+  "query": {
+    "@type": "koral:token",
+    "wrap": {
+      "@type": "koral:termGroup",
+      "operands": [
+        {
+          "@type": "koral:term",
+          "flags": [
+            "flags:caseInsensitive"
+          ],
+          "foundry": "opennlp",
+          "key": "laufe",
+          "layer": "orth",
+          "match": "match:eq"
+        },
+        {
+          "@type": "koral:term",
+          "foundry": "tt",
+          "key": "Lauf",
+          "layer": "lemma",
+          "match": "match:ne"
+        }
+      ],
+      "relation": "relation:and"
+    }
+  }
+}