Added exclusion to KorapQuery wrapper
diff --git a/src/main/java/de/ids_mannheim/korap/KorapQuery.java b/src/main/java/de/ids_mannheim/korap/KorapQuery.java
index 28fbcc0..bb6261c 100644
--- a/src/main/java/de/ids_mannheim/korap/KorapQuery.java
+++ b/src/main/java/de/ids_mannheim/korap/KorapQuery.java
@@ -40,6 +40,10 @@
     // Logger
     private final static Logger log = LoggerFactory.getLogger(KorapQuery.class);
 
+    // This advices the java compiler to ignore all loggings
+    public static final boolean DEBUG = false;
+
+
     /**
      * Constructs a new base object for query generation.
      * @param field The specific index field for the query.
diff --git a/src/main/java/de/ids_mannheim/korap/query/SpanElementQuery.java b/src/main/java/de/ids_mannheim/korap/query/SpanElementQuery.java
index ad97152..7e4ee9e 100644
--- a/src/main/java/de/ids_mannheim/korap/query/SpanElementQuery.java
+++ b/src/main/java/de/ids_mannheim/korap/query/SpanElementQuery.java
@@ -19,6 +19,9 @@
 import java.util.Map;
 import java.util.Set;
 
+/**
+ * @author Nils Diewald
+ */
 
 /** Matches spans wrapped by an element. */
 public class SpanElementQuery extends SpanQuery {
@@ -121,7 +124,9 @@
 	    return new ElementSpans(postings, element);
 
 	// element does exist, but has no positions
-	throw new IllegalStateException("field \"" + element.field() + "\" was indexed without position data; cannot run SpanElementQuery (element=" + element.text() + ")");
+	throw new IllegalStateException("field \"" + element.field() + "\" was indexed " +
+					"without position data; cannot run " +
+					"SpanElementQuery (element=" + element.text() + ")");
     };
 
     public String getElementStr () {
diff --git a/src/main/java/de/ids_mannheim/korap/query/spans/ElementSpans.java b/src/main/java/de/ids_mannheim/korap/query/spans/ElementSpans.java
index f10809c..a44ed49 100644
--- a/src/main/java/de/ids_mannheim/korap/query/spans/ElementSpans.java
+++ b/src/main/java/de/ids_mannheim/korap/query/spans/ElementSpans.java
@@ -23,7 +23,7 @@
 // TODO: Store payloads in 12 byte instead of the complicated ByteBuffer stuff!
 
 /**
- * @author ndiewald
+ * @author Nils Diewald
  */
 public class ElementSpans extends Spans {
 
@@ -47,6 +47,10 @@
 
     private final static Logger log = LoggerFactory.getLogger(ElementSpans.class);
 
+
+    /**
+     * The constructor.
+     */
     public ElementSpans(DocsAndPositionsEnum postings, Term term) {
 	this.postings = postings;
 	this.term = term;
@@ -61,7 +65,7 @@
     };
 
     // only for EmptyElementSpans (below)
-    ElementSpans() {
+    public ElementSpans() {
 	term = null;
 	postings = null;
     };
diff --git a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanSequenceQueryWrapper.java b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanSequenceQueryWrapper.java
index 5fa21d0..e6c0488 100644
--- a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanSequenceQueryWrapper.java
+++ b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanSequenceQueryWrapper.java
@@ -90,25 +90,37 @@
     };
 
     public SpanSequenceQueryWrapper withConstraint (int min, int max) {
+	return this.withConstraint(min, max, false);
+    };
+
+    public SpanSequenceQueryWrapper withConstraint (int min, int max, boolean exclusion) {
 	if (this.constraints == null)
 	    this.constraints = new ArrayList<DistanceConstraint>(1);
-	this.constraints.add(new DistanceConstraint(min, max,false));
+	this.constraints.add(new DistanceConstraint(min, max, exclusion));
 	return this;
     };
 
     public SpanSequenceQueryWrapper withConstraint (int min, int max, String unit) {
+	return this.withConstraint(min, max, unit, false);
+    };
+    
+    public SpanSequenceQueryWrapper withConstraint (int min,
+						    int max,
+						    String unit,
+						    boolean exclusion) {
 	if (this.constraints == null)
 	    this.constraints = new ArrayList<DistanceConstraint>(1);
 	if (unit.equals("w"))
-	    this.constraints.add(new DistanceConstraint(min, max,false));
+	    this.constraints.add(new DistanceConstraint(min, max, exclusion));
 	else
 	    this.constraints.add(
 		 new DistanceConstraint(
-                     new SpanElementQuery(this.field, unit), min, max,false)
+                     new SpanElementQuery(this.field, unit), min, max, exclusion)
 	    );
 	return this;
     };
 
+    
     public SpanQuery toQuery () {
 	if (this.segments.size() == 0) {
 	    return (SpanQuery) null;
diff --git a/src/main/resources/log4j.properties b/src/main/resources/log4j.properties
index e876668..c5ac092 100644
--- a/src/main/resources/log4j.properties
+++ b/src/main/resources/log4j.properties
@@ -1,6 +1,6 @@
 ## logger file can be used with
 
-# log4j.rootLogger = DEBUG, stdout
+log4j.rootLogger = DEBUG, stdout
 
 # Spans:
 #log4j.logger.de.ids_mannheim.korap.query.spans.ElementSpans = TRACE, stdout
diff --git a/src/test/java/de/ids_mannheim/korap/benchmark/TestBenchmarkElementSpans.java b/src/test/java/de/ids_mannheim/korap/benchmark/TestBenchmarkElementSpans.java
index 7bfed40..d177eb3 100644
--- a/src/test/java/de/ids_mannheim/korap/benchmark/TestBenchmarkElementSpans.java
+++ b/src/test/java/de/ids_mannheim/korap/benchmark/TestBenchmarkElementSpans.java
@@ -112,6 +112,45 @@
 	//  77.167124985 sec
     };
 
+
+    @Test
+    public void checkBenchmarkSentences () throws IOException {
+	Properties prop = new Properties();
+	InputStream fr = new FileInputStream(getClass().getResource("/korap.conf").getFile());
+	prop.load(fr);
+
+	// Get the real index
+	KorapIndex ki = new KorapIndex(new MMapDirectory(new File(prop.getProperty("lucene.indexDir"))));
+
+	// Create a container for virtual collections:
+	KorapCollection kc = new KorapCollection(ki);
+
+	long t1 = 0, t2 = 0;
+	/// cosmas20.json!!!
+	String json = getString(getClass().getResource("/queries/benchmark4.jsonld").getFile());
+
+	int rounds = 10;
+
+	KorapResult kr = new KorapResult();
+
+	t1 = System.nanoTime();
+	double length = 0;
+	for (int i = 1; i <= rounds; i++) {
+	    kr = new KorapSearch(json).run(ki);
+	};
+	t2 = System.nanoTime();
+
+	System.err.println(kr.getMatch(0).toJSON());
+
+	assertEquals("TotalResults1", 4116282, kr.getTotalResults());
+	assertEquals("TotalResults2", kr.getTotalResults(), ki.numberOf("sentences"));
+
+	double seconds = (double)(t2-t1) / 1000000000.0;
+	
+	System.out.println("It took " + seconds + " seconds");
+    };
+
+    
     @Test
     public void checkBenchmarkIndexDocuments () throws IOException {
 	long t1 = 0, t2 = 0;
diff --git a/src/test/java/de/ids_mannheim/korap/query/TestKorapQuery.java b/src/test/java/de/ids_mannheim/korap/query/TestKorapQuery.java
index 6442f29..6ed797c 100644
--- a/src/test/java/de/ids_mannheim/korap/query/TestKorapQuery.java
+++ b/src/test/java/de/ids_mannheim/korap/query/TestKorapQuery.java
@@ -155,6 +155,64 @@
 	assertEquals("spanNext(spanNext(field:try1, shrink(1: {1: field:try2})), field:try3)", sq.toString());
     };
 
+
+    @Test
+    public void KorapSequenceQuery1 () {
+	KorapQuery kq = new KorapQuery("field");
+	SpanQuery sq = kq.seq(kq.seg("try1")).append(kq.seg("try2")).toQuery();
+	assertEquals("spanNext(field:try1, field:try2)", sq.toString());
+    };
+
+    @Test
+    public void KorapSequenceQuery2 () {
+	KorapQuery kq = new KorapQuery("field");
+	SpanQuery sq = kq.seq(kq.seg("try1")).append(kq.seg("try2")).withConstraint(2,3).toQuery();
+	assertEquals("spanDistance(field:try1, field:try2, [(w[2:3], ordered, notExcluded)])", sq.toString());
+    };
+
+    @Test
+    public void KorapSequenceQuery3 () {
+	KorapQuery kq = new KorapQuery("field");
+	SpanQuery sq = kq.seq(kq.seg("try1")).append(kq.seg("try2")).withConstraint(2,3, "s").toQuery();
+	assertEquals("spanElementDistance(field:try1, field:try2, [(s[2:3], ordered, notExcluded)])", sq.toString());
+    };
+
+    @Test
+    public void KorapSequenceQuery4 () {
+	KorapQuery kq = new KorapQuery("field");
+	SpanQuery sq = kq.seq(kq.seg("try1")).append(kq.seg("try2")).withConstraint(2,3,"s").withConstraint(5,6,"w").toQuery();
+	assertEquals("spanMultipleDistance(field:try1, field:try2, [(s[2:3], ordered, notExcluded), (w[5:6], ordered, notExcluded)])", sq.toString());
+    };
+
+    @Test
+    public void KorapSequenceQuery5 () {
+	KorapQuery kq = new KorapQuery("field");
+	SpanQuery sq = kq.seq(kq.seg("try1")).append(kq.seg("try2")).withConstraint(2,3,true).toQuery();
+	assertEquals("spanDistance(field:try1, field:try2, [(w[2:3], ordered, excluded)])", sq.toString());
+    };
+
+    @Test
+    public void KorapSequenceQuery6 () {
+	KorapQuery kq = new KorapQuery("field");
+	SpanQuery sq = kq.seq(kq.seg("try1")).append(kq.seg("try2")).withConstraint(2,3,"s",true).toQuery();
+	assertEquals("spanElementDistance(field:try1, field:try2, [(s[2:3], ordered, excluded)])", sq.toString());
+    };
+
+    @Test
+    public void KorapSequenceQuery7 () {
+	KorapQuery kq = new KorapQuery("field");
+	SpanQuery sq = kq.seq(kq.seg("try1")).append(kq.seg("try2")).withConstraint(5,6).withConstraint(2,3,"s",true).toQuery();
+	assertEquals("spanMultipleDistance(field:try1, field:try2, [(w[5:6], ordered, notExcluded), (s[2:3], ordered, excluded)]])", sq.toString());
+    };
+
+    @Test
+    public void KorapSequenceQuery8 () {
+	KorapQuery kq = new KorapQuery("field");
+	SpanQuery sq = kq.seq(kq.seg("try1")).append(kq.seg("try2")).append("try3").withConstraint(5,6).withConstraint(2,3,"s",true).toQuery();
+	assertEquals("spanMultipleDistance(spanMultipleDistance(field:try1, field:try2, [(w[5:6], ordered, notExcluded), (s[2:3], ordered, excluded)]]), field:try3, [(w[5:6], ordered, notExcluded), (s[2:3], ordered, excluded)]])", sq.toString());
+    };
+
+    
     // kq.seg("a").append(kq.ANY).append("b:c");
     // kq.repeat(kq.seg("a", "b"), 5)
 };
diff --git a/src/test/java/de/ids_mannheim/korap/query/TestKorapQueryJSON.java b/src/test/java/de/ids_mannheim/korap/query/TestKorapQueryJSON.java
index 780a397..f4cc0a5 100644
--- a/src/test/java/de/ids_mannheim/korap/query/TestKorapQueryJSON.java
+++ b/src/test/java/de/ids_mannheim/korap/query/TestKorapQueryJSON.java
@@ -101,6 +101,15 @@
     };
 
     @Test
+    public void queryJSONBsp9b () {
+	SpanQueryWrapperInterface sqwi = jsonQuery(getClass().getResource("/queries/bsp9b.jsonld").getFile());
+
+	// [base=Katze&orth=Katzen]
+	assertEquals(sqwi.toQuery().toString(), "spanSegment(tokens:mate/m:number:pl, tokens:tt/p:NN)");
+    };
+
+
+    @Test
     public void queryJSONBsp10 () {
 	SpanQueryWrapperInterface sqwi = jsonQuery(getClass().getResource("/queries/bsp10.jsonld").getFile());
 
diff --git a/src/test/resources/queries/bsp9b.jsonld b/src/test/resources/queries/bsp9b.jsonld
new file mode 100644
index 0000000..d0f44b1
--- /dev/null
+++ b/src/test/resources/queries/bsp9b.jsonld
@@ -0,0 +1,24 @@
+{
+  "@context" : "http://ids-mannheim.de/ns/KorAP/json-ld/v0.1/context.jsonld",
+  "query" : {
+    "@type" : "korap:token",
+    "wrap" : {
+      "@type" : "korap:termGroup",
+      "relation" : "relation:and",
+      "operands" : [ {
+        "@type" : "korap:term",
+        "key" : "number",
+        "value" : "pl",
+        "layer" : "m",
+        "foundry" : "mate",
+        "match" : "match:eq"
+      }, {
+        "@type" : "korap:term",
+        "key" : "NN",
+        "layer" : "p",
+        "foundry" : "tt",
+        "match" : "match:eq"
+      } ]
+    }
+  }
+}
\ No newline at end of file