Fixed serialization bug for empty classes and added documentation
diff --git a/Changes b/Changes
index 0fc0bb3..247c82a 100644
--- a/Changes
+++ b/Changes
@@ -1,10 +1,12 @@
-0.49.3 2014-01-29
+0.49.3 2014-01-30
         - [documentation] Improved documentation for API classes (diewald)
 	- [documentation] Improved documentation for various queries (margaretha)
 	- [feature] Added deserialization of SpanSubSpanQueries (margaretha,diewald)
 	- [bugfix] Null filters are now correctly extended (diewald)
 	- [cleanup] Refactoring of KorapResult, KorapResponse, KorapQuery,
 	  deprecated operation:or in favor of operation:junction (diewald)
+	- [bugfix] Empty class segments are now correctly serialized
+	  in sequences (diewald)
 
 0.49.2 2014-12-05
 	- [documentation] Improved documentation for various queries (margaretha)
@@ -223,43 +225,43 @@
 	- Support for distinct Match retrieval (diewald)
 
 0.25.3 2014-01-10
-        - Updated Lucene to 4.3.1.
-	- Eliza Margaretha has joined the team.
+        - Updated Lucene to 4.3.1 (diewald)
+	- Eliza Margaretha has joined the team
 
 0.25.2 2013-12-29
-        - Fixed highlight bug with empty reopened tags.
+        - Fixed highlight bug with empty reopened tags
 
 0.25.1 2013-12-28
-        - Support for pubDate collections.
-	- Changed versioning scheme.
+        - Support for pubDate collections
+	- Changed versioning scheme
 
 0.25 2013-12-20
-        - Support for Wildcard Queries.
-	- Improved support for regular expressions.
-	- Introduced keyword fields that store no positions.
+        - Support for Wildcard Queries
+	- Improved support for regular expressions
+	- Introduced keyword fields that store no positions
 
 0.24_1 2013-12-05
         - This is a pseudo version for demo versions with dirty hacks,
 	  meant to be rolled back!
-	- There is now an ignored broken test in TestKorapCollection!
+	- There is now an ignored broken test in TestKorapCollection
 
 0.24 2013-12-05
-        - Json deserializer finished for virtual collections.
+        - Json deserializer finished for virtual collections
 
 0.23 2013-12-05
-        - Error handling corrected in KorapResult.
-	- Json deserializer finished for queries.
+        - Error handling corrected in KorapResult
+	- Json deserializer finished for queries
 
 0.22 2013-12-04
-        - Introduced KorapSearch.
-	- Json deserializer (started).
+        - Introduced KorapSearch
+	- Json deserializer (started)
 
 0.21 2013-11-28
         - Virtual collections can now be defined,
-	  searched, nested and extended.
+	  searched, nested and extended
 
 0.20 2013-11-18
-        - Unboxing from sandbox.
+        - Unboxing from sandbox repository
 
 0.11 2013-11-14
 	- JSON file importer (plain and gzip)
@@ -267,43 +269,43 @@
 	- [bugfix] Sequence Query
 
 0.10 2013-11-11
-        - Added JSON input to indexer.
+        - Added JSON input to indexer
 
 0.09 2013-11-07
-        - Reconstruction of all wrapper queries using an interface.
-	- Finished KorapQuery (preliminary feature freeze).
+        - Reconstruction of all wrapper queries using an interface
+	- Finished KorapQuery (preliminary feature freeze)
 
 0.08 2013-10-18
-        - Changed methods to attributes in KorapMatch.
-	- Changed SimpleJSON to Jackson.
-	- Fixed Highlighting.
-	- Some Refactoring of result classes.
-	- Introduced KorapDocument.
-	- Introduced KorapHTML utility.
+        - Changed methods to attributes in KorapMatch
+	- Changed SimpleJSON to Jackson
+	- Fixed Highlighting
+	- Some Refactoring of result classes
+	- Introduced KorapDocument
+	- Introduced KorapHTML utility
 
 0.07 2013-10-14
-        - Added position to offset matching.
+        - Added position to offset matching
 
 0.06 2013-10-01
-        - Added SpanElementQuery for working WithinQeries.
-	- Added KorapResult and KorapMatching.
+        - Added SpanElementQuery for working WithinQeries
+	- Added KorapResult and KorapMatching
 
 0.05 2013-09-18
-        - Fixed bug in indexing (MultiTermTokenStream).
-	- Fixed SpanNext.
-	- Added KorapIndex.
-	- First draft for KorapFilter.
+        - Fixed bug in indexing (MultiTermTokenStream)
+	- Fixed SpanNext
+	- Added KorapIndex
+	- First draft for KorapFilter
 
 0.04 2013-09-01
         - Introduced optimized SpanNext class (not working atm),
-	  as SpanNear does not always work with nested synonyms.
+	  as SpanNear does not always work with nested synonyms
 
 0.03 2013-08-28
-        - Added within query (not working atm).
-	- Pushed query part to public repo.
+        - Added within query (not working atm)
+	- Pushed query part to public repo
 
 0.02 2013-08-26
-        - Added sequences.
+        - Added sequences
 
 0.01 2013-08-20
-        - First version as maven build environment.
+        - First version as maven build environment
diff --git a/src/main/java/de/ids_mannheim/korap/query/SpanMultipleDistanceQuery.java b/src/main/java/de/ids_mannheim/korap/query/SpanMultipleDistanceQuery.java
index b8ab9fe..31b8f26 100644
--- a/src/main/java/de/ids_mannheim/korap/query/SpanMultipleDistanceQuery.java
+++ b/src/main/java/de/ids_mannheim/korap/query/SpanMultipleDistanceQuery.java
@@ -122,7 +122,7 @@
             sb.append(c.getMaxDistance());
             sb.append("], ");
             sb.append(c.isOrdered() ? "ordered, " : "notOrdered, ");
-            sb.append(c.isExclusion() ? "excluded)]" : "notExcluded)");
+            sb.append(c.isExclusion() ? "excluded)" : "notExcluded)");
             if (i < size - 1)
                 sb.append(", ");
         }
diff --git a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanClassQueryWrapper.java b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanClassQueryWrapper.java
index d276cb1..2f59079 100644
--- a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanClassQueryWrapper.java
+++ b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanClassQueryWrapper.java
@@ -9,28 +9,45 @@
 import java.util.*;
 
 
+// TODO: If this.subquery.isNegative(), it may be an Expansion!
+// SpanExpansionQuery(x, y.negative, min, max. direction???, classNumber, true)
+
 public class SpanClassQueryWrapper extends SpanQueryWrapper {
     private SpanQueryWrapper subquery;
-    private byte number = (byte) 0;
 
     public SpanClassQueryWrapper (SpanQueryWrapper subquery, byte number) {
-	this.subquery = subquery;
-	this.number = number;
+        this.subquery = subquery;
+        this.number   = number;
+        if (number != (byte) 0)
+            this.hasClass = true;
     };
 
     public SpanClassQueryWrapper (SpanQueryWrapper subquery, short number) {
-	this.subquery = subquery;
-	this.number = (byte) number;
+        this(subquery, (byte) number);
     };
 
     public SpanClassQueryWrapper (SpanQueryWrapper subquery, int number) {
-	this.subquery = subquery;
-	this.number = (byte) number;
+        this(subquery, (byte) number);
     };
 
     public SpanClassQueryWrapper (SpanQueryWrapper subquery) {
-	this.subquery = subquery;
-	this.number = (byte) 0;
+        this(subquery, (byte) 0);
+    };
+
+    public boolean isEmpty () {
+        return this.subquery.isEmpty();
+    };
+
+    public boolean isOptional () {
+        return this.subquery.isOptional();
+    };
+
+    public boolean isNull () {
+        return this.subquery.isNull();
+    };
+
+    public boolean isNegative () {
+        return this.subquery.isNegative();
     };
 
     public SpanQuery toQuery () throws QueryException {
@@ -40,25 +57,10 @@
         SpanQuery sq = (SpanQuery) this.subquery.toQuery();
 
         if (sq == null) return (SpanQuery) null;
-
-        // TODO: If this.subquery.isNegative(), it may be an Expansion!
-        // SpanExpansionQuery(x, y.negative, min, max. direction???, classNumber, true)
 	
         if (this.number == (byte) 0) {
             return new SpanClassQuery(sq);
         };
         return new SpanClassQuery(sq, (byte) this.number);
     };
-
-    public boolean isOptional () {
-	return this.subquery.isOptional();
-    };
-
-    public boolean isNull () {
-	return this.subquery.isNull();
-    };
-
-    public boolean isNegative () {
-	return this.subquery.isNegative();
-    };
 };
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 9df3c6d..b13d6bc 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
@@ -13,23 +13,31 @@
 import org.slf4j.LoggerFactory;
 
 /*
-  TODO:
-  Make isNegative work!
-  Make isEmpty work!
-  Make isExtendedToTheRight work!
+  TODO: Make isNegative work!
+  TODO: Make isEmpty work!
+  TODO: Make isExtendedToTheRight work!
+  TODO: Evaluate if spanNext(spanNext(a,b),spanNext(c,d)) is faster
+        than spanNext(spanNext(spanNext(a,b),c),d)
+  TODO: Improve support for SpanElementQueryWrapper in constraints!
 */
 
 /**
- * Deserialize complexe sequence queries to Lucene SpanQueries.
+ * Deserialize complexe sequence queries to SpanQueries.
+ * This will try to make queries work, that by simple nesting won't
+ * (like queries with empty sequences), and will optimize queries 
+ * if possible.
  *
- * @author Nils Diewald
- * @version 0.03
+ * Todo: Synopsis
+ *
+ * @author diewald
  */
 public class SpanSequenceQueryWrapper extends SpanQueryWrapper {
     private String field;
     private ArrayList<SpanQueryWrapper> segments;
     private ArrayList<DistanceConstraint> constraints;
 
+    private QueryException constraintException = null;
+    
     private final String limitationError =
         "Distance constraints not supported with " +
         "empty or negative operands";
@@ -48,7 +56,10 @@
 
 
     /**
-     * Empty constructor.
+     * Constructs a new object for sequence deserialization.
+     *
+     * @param field The fields the nested SpanQueries should
+     *        search in.
      */
     public SpanSequenceQueryWrapper (String field) {
         this.field = field;
@@ -57,7 +68,19 @@
 
 
     /**
-     * Constructor accepting term sequences.
+     * Constructs a new object for sequence deserialization
+     * by passing a sequence of terms.
+     *
+     * <blockquote><pre>
+     *   SpanSequenceQueryWrapper ssqw =
+     *     new SpanSequenceQueryWrapper("tokens", "der", "Baum");
+     *   System.out.println(ssqw.toQuery());
+     *   // spanNext(tokens:der, tokens:Baum)
+     * </pre></blockquote>
+     *
+     * @param field The fields the nested SpanQueries should
+     *        search in.
+     * @param terms[] Arbitrary list of terms to search for.
      */
     public SpanSequenceQueryWrapper (String field, String ... terms) {
         this(field);
@@ -68,23 +91,30 @@
                 )
             );
         };
+        // Query can't be null anymore
         this.isNull = false;
     };
 
 
     /**
-     * Constructor accepting SpanQuery sequences.
+     * Constructs a new object for sequence deserialization
+     * by passing a single {@link SpanQuery} object.
+     *
+     * @param query Initial {@link SpanQuery} to search for.
      */
-    public SpanSequenceQueryWrapper (String field, SpanQuery sq) {
-        this(field);
-        this.segments.add(new SpanSimpleQueryWrapper(sq));
+    public SpanSequenceQueryWrapper (SpanQuery query) {
+        this(query.getField());
+        this.segments.add(new SpanSimpleQueryWrapper(query));
         this.isNull = false;
     };
 
 
     /**
-     * Constructor accepting SpanQueryWrapper sequences.
-     * These wrappers may be optional, negative or empty.
+     * Constructs a new object for sequence deserialization
+     * by passing a single {@link SpanQueryWrapper} object.
+     * These wrapper queries may be optional, negative, or empty.
+     *
+     * @param query Initial {@link SpanQueryWrapper} to search for.
      */
     public SpanSequenceQueryWrapper (String field, SpanQueryWrapper sswq) {
         this(field);
@@ -93,233 +123,465 @@
         if (sswq.isNull())
             return;
 
-        if (DEBUG && !sswq.isEmpty) {
-            try {
-                log.trace("New span sequence {}", sswq.toQuery().toString());
+        // Some debugging on initiating new sequences
+        if (DEBUG) {
+            if (!sswq.isEmpty()) {
+                try {
+                    log.trace("New span sequence {}", sswq.toQuery().toString());
+                }
+                catch (QueryException qe) {
+                    log.trace("Unable to serialize query {}", qe.getMessage());
+                };
             }
-            catch (QueryException qe) {
-                log.trace("Unable to serialize query {}", qe.getMessage());
+            else {
+                log.trace("New span sequence, that's initially empty");
             };
         };
-        /*
-          System.err.println("Is negative: ");
-          System.err.println(sswq.isNegative());
-        */
+
         this.segments.add(sswq);
         this.isNull = false;
     };
 
 
+
     /**
-     * Append a term to the sequence.
+     * Append a new term to the sequence.
+     *
+     * <blockquote><pre>
+     *   SpanSequenceQueryWrapper ssqw =
+     *     new SpanSequenceQueryWrapper("tokens");
+     *   ssqw.append("der").append("Baum");
+     *   System.out.println(ssqw.toQuery());
+     *   // spanNext(tokens:der, tokens:Baum)
+     * </pre></blockquote>
+     *
+     * @param term A new string to search for.
+     * @return The {@link SpanSequenceQueryWrapper} object for chaining.
      */
     public SpanSequenceQueryWrapper append (String term) {
-	return this.append(new SpanTermQuery(new Term(field, term)));
+        return this.append(new SpanTermQuery(new Term(field, term)));
     };
 
 
     /**
-     * Append a SpanQuery to the sequence.
+     * Append a new {@link SpanQuery} object to the sequence.
+     *
+     * @param query A new {@link SpanQuery} to search for.
+     * @return The {@link SpanSequenceQueryWrapper} object for chaining.
      */
     public SpanSequenceQueryWrapper append (SpanQuery query) {
-	return this.append(new SpanSimpleQueryWrapper(query));
+        return this.append(new SpanSimpleQueryWrapper(query));
     };
 
 
     /**
-     * Append a SpanQueryWrapper to the sequence.
+     * Append a new {@link SpanQueryWrapper} object to the sequence.
+     *
+     * @param query A new {@link SpanQueryWrapper} to search for.
+     * @return The {@link SpanSequenceQueryWrapper} object for chaining.
      */
     public SpanSequenceQueryWrapper append (SpanQueryWrapper ssq) {
-	if (ssq.isNull())
-	    return this;
 
-	this.isSolved = false;
-	this.isNull = false;
+        // The wrapper is null - ignore this in the sequence
+        if (ssq.isNull())
+            return this;
 
-	// Embed a sequence
-	if (ssq instanceof SpanSequenceQueryWrapper) {
+        // As the spanQueryWrapper is not null,
+        // the sequence can't be null as well
+        this.isNull = false;
 
-	    if (DEBUG)
-		log.trace("Add SpanSequenceQueryWrapper to sequence");
+        // The sequence may be problematic
+        this.isSolved = false;
 
-	    // There are no constraints - just next spans
-	    // Flatten!
-	    SpanSequenceQueryWrapper ssqw = (SpanSequenceQueryWrapper) ssq;
-	    if (!this.hasConstraints() &&
-		!ssqw.hasConstraints() &&
-		this.isInOrder() == ssqw.isInOrder()) {
-		for (int i = 0; i < ssqw.segments.size(); i++) {
-		    this.append(ssqw.segments.get(i));
-		};
-	    }
+        // Embed a nested sequence
+        if (ssq instanceof SpanSequenceQueryWrapper) {
 
-	    // No flattening
-	    else {
-		this.segments.add(ssq);
-	    };
-	}
+            if (DEBUG)
+                log.trace("Add SpanSequenceQueryWrapper to sequence");
 
-	// Only one segment
-	else {
-	    this.segments.add(ssq);
-	};
+            // Some casting
+            SpanSequenceQueryWrapper ssqw = (SpanSequenceQueryWrapper) ssq;
 
-	return this;
+            // There are no constraints and the order is equal - Flatten!
+            if (!this.hasConstraints() && !ssqw.hasConstraints() &&
+                this.isInOrder() == ssqw.isInOrder()) {
+                for (int i = 0; i < ssqw.segments.size(); i++) {
+                    this.append(ssqw.segments.get(i));
+                };
+            }
+
+            // Unable to flatten ... :-(
+            else {
+                this.segments.add(ssq);
+            };
+        }
+
+        // This is not a sequence
+        else {
+            this.segments.add(ssq);
+        };
+
+        return this;
     };
 
 
     /**
-     * Prepend a term to the sequence.
+     * Prepend a new term to the sequence.
+     *
+     * <blockquote><pre>
+     *   SpanSequenceQueryWrapper ssqw =
+     *     new SpanSequenceQueryWrapper("tokens", "Baum");
+     *   ssqw.prepend("der");
+     *   System.out.println(ssqw.toQuery());
+     *   // spanNext(tokens:der, tokens:Baum)
+     * </pre></blockquote>
+     *
+     * @param term A new string to search for.
+     * @return The {@link SpanSequenceQueryWrapper} object for chaining.
      */
     public SpanSequenceQueryWrapper prepend (String term) {
-	return this.prepend(new SpanTermQuery(new Term(field, term)));
+        return this.prepend(new SpanTermQuery(new Term(field, term)));
     };
 
 
     /**
-     * Prepend a SpanQuery to the sequence.
+     * Prepend a new {@link SpanQuery} object to the sequence.
+     *
+     * @param query A new {@link SpanQuery} to search for.
+     * @return The {@link SpanSequenceQueryWrapper} object for chaining.
      */
     public SpanSequenceQueryWrapper prepend (SpanQuery query) {
-	return this.prepend(new SpanSimpleQueryWrapper(query));
+        return this.prepend(new SpanSimpleQueryWrapper(query));
     };
 
 
     /**
-     * Prepend a SpanQueryWrapper to the sequence.
+     * Prepend a new {@link SpanQueryWrapper} object to the sequence.
+     *
+     * @param query A new {@link SpanQueryWrapper} to search for.
+     * @return The {@link SpanSequenceQueryWrapper} object for chaining.
      */
     public SpanSequenceQueryWrapper prepend (SpanQueryWrapper ssq) {
-	if (ssq.isNull())
-	    return this;
 
-	this.isSolved = false;
-	this.isNull = false;
+        // The wrapper is null - ignore this in the sequence
+        if (ssq.isNull())
+            return this;
 
-	// Embed a sequence
-	if (ssq instanceof SpanSequenceQueryWrapper) {
+        // As the spanQueryWrapper is not null,
+        // the sequence can't be null as well
+        this.isNull = false;
 
-	    // There are no constraints - just next spans
-	    // Flatten!
-	    SpanSequenceQueryWrapper ssqw = (SpanSequenceQueryWrapper) ssq;
-	    if (!this.hasConstraints() &&
-		!ssqw.hasConstraints() &&
-		this.isInOrder() == ssqw.isInOrder()) {
-		for (int i = ssqw.segments.size() - 1; i >= 0; i--) {
-		    this.prepend(ssqw.segments.get(i));
-		};
-	    }
+        // The sequence may be problematic
+        this.isSolved = false;
 
-	    // No flattening
-	    else {
-		this.segments.add(0, ssq);
-	    };
-	}
+        // Embed a nested sequence
+        if (ssq instanceof SpanSequenceQueryWrapper) {
 
-	// Only one segment
-	else {
-	    this.segments.add(0, ssq);
-	};
+            // There are no constraints and the order is equal - Flatten!
+            SpanSequenceQueryWrapper ssqw = (SpanSequenceQueryWrapper) ssq;
+            if (!this.hasConstraints() &&
+                !ssqw.hasConstraints() &&
+                this.isInOrder() == ssqw.isInOrder()) {
+                for (int i = ssqw.segments.size() - 1; i >= 0; i--) {
+                    this.prepend(ssqw.segments.get(i));
+                };
+            }
 
-	return this;
+            // Unable to flatten ... :-(
+            else {
+                this.segments.add(0, ssq);
+            };
+        }
+
+        // This is not a sequence
+        else {
+            this.segments.add(0, ssq);
+        };
+
+        return this;
     };
 
 
     /**
-     * Add a sequence constraint to the sequence for tokens,
-     * aka distance constraints.
+     * Add a token based sequence constraint (aka distance constraint)
+     * to the sequence.
+     *
+     * Multiple constraints are supported.
+     *
+     * A minimum value of zero means, there may be an overlap,
+     * a minimum value of 1 means, there is no token between the spans.
+     * It's weird - we know and dislike that. That's why we have to say:
+     *
+     * <strong>Warning!</strong> Sequence constraints are experimental and
+     * may (hopefully) change in future versions!
+     *
+     * @param min The minimum number of tokens between the elements
+     *        of the sequence.
+     * @param max The minimum number of tokens between the elements
+     *        of the sequence.
+     * @return The {@link SpanSequenceQueryWrapper} object for chaining.
+     * @see DistanceConstraint
      */
     public SpanSequenceQueryWrapper withConstraint (int min, int max) {
-	return this.withConstraint(min, max, false);
+        return this.withConstraint(min, max, false);
     };
 
 
     /**
-     * Add a sequence constraint to the sequence for tokens,
-     * aka distance constraints (with exclusion).
+     * Add a token based sequence constraint (aka distance constraint)
+     * to the sequence with an exclusion constraint, meaning
+     * the constraint is fine in case the operands are <em>not</em>
+     * within the distance.
+     *
+     * Multiple constraints are supported.
+     *
+     * A minimum value of zero means, there may be an overlap,
+     * a minimum value of 1 means, there is no token between the spans.
+     * It's weird - we know and dislike that. That's why we have to say:
+     *
+     * <strong>Warning!</strong> Sequence constraints are experimental and
+     * may (hopefully) change in future versions!
+     *
+     * @param min The minimum number of tokens between the elements
+     *        of the sequence.
+     * @param max The minimum number of tokens between the elements
+     *        of the sequence.
+     * @param exclusion Boolean value indicating, the distance constraint
+     *        has to fail.
+     * @return The {@link SpanSequenceQueryWrapper} object for chaining.
+     * @see DistanceConstraint
      */
     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, isInOrder, exclusion));
-	return this;
+        if (this.constraints == null)
+            this.constraints = new ArrayList<DistanceConstraint>(1);
+        this.constraints.add(new DistanceConstraint(min, max, this.isInOrder, exclusion));
+        return this;
     };
 
 
     /**
-     * Add a sequence constraint to the sequence for various units,
-     * aka distance constraints.
+     * Add a sequence constraint (aka distance constraint)
+     * to the sequence based on a certain unit.
+     * The unit has to be a valid {@link SpanElementQuery} term
+     * or <tt>w</tt> for tokens.
+     *
+     * Multiple constraints are supported.
+     *
+     * A minimum value of zero means, there may be an overlap,
+     * a minimum value of 1 means, there is no token between the spans.
+     * It's weird - we know and dislike that. That's why we have to say:
+     *
+     * <strong>Warning!</strong> Sequence constraints are experimental and
+     * may (hopefully) change in future versions!
+     *
+     * @param min The minimum number of tokens between the elements
+     *        of the sequence.
+     * @param max The minimum number of tokens between the elements
+     *        of the sequence.
+     * @param unit Unit for distance - will be evaluated to a {@link SpanElementQuery}.
+     * @return The {@link SpanSequenceQueryWrapper} object for chaining.
+     * @see DistanceConstraint
      */
     public SpanSequenceQueryWrapper withConstraint (int min, int max, String unit) {
-	return this.withConstraint(min, max, unit, false);
+        return this.withConstraint(min, max, unit, false);
     };
 
     
+
     /**
-     * Add a sequence constraint to the sequence for various units,
-     * aka distance constraints (with exclusion).
+     * Add a sequence constraint (aka distance constraint)
+     * to the sequence based on a certain unit and with an
+     * exclusion constraint, meaning the constraint is fine
+     * in case the operands are <em>not</em> within the distance.
+     * The unit has to be a valid {@link SpanElementQuery} term
+     * or <tt>w</tt> for tokens.
+     *
+     * Multiple constraints are supported.
+     *
+     * A minimum value of zero means, there may be an overlap,
+     * a minimum value of 1 means, there is no token between the spans.
+     * It's weird - we know and dislike that. That's why we have to say:
+     *
+     * <strong>Warning!</strong> Sequence constraints are experimental and
+     * may (hopefully) change in future versions!
+     *
+     * @param min The minimum number of tokens between the elements
+     *        of the sequence.
+     * @param max The minimum number of tokens between the elements
+     *        of the sequence.
+     * @param unit Unit for distance - will be evaluated to a {@link SpanElementQuery}.
+     * @param exclusion Boolean value indicating, the distance constraint
+     *        has to fail.
+     * @return The {@link SpanSequenceQueryWrapper} object for chaining.
+     * @see DistanceConstraint
      */
-    public SpanSequenceQueryWrapper withConstraint (int min,
-						    int max,
-						    String unit,
-						    boolean exclusion) {
-	if (this.constraints == null)
-	    this.constraints = new ArrayList<DistanceConstraint>(1);
+    public SpanSequenceQueryWrapper withConstraint
+        (int min, int max, String unit, boolean exclusion) {
 
-	// Word unit
-	if (unit.equals("w"))
-	    this.constraints.add(new DistanceConstraint(min, max, isInOrder, exclusion));
+        // Word unit
+        if (unit.equals("w")) {
+            if (this.constraints == null)
+                this.constraints = new ArrayList<DistanceConstraint>(1);
+            this.constraints.add(new DistanceConstraint(min, max, isInOrder, exclusion));
+            return this;
+        };
 
-	// Element unit (sentence or paragraph)
-	else
-	    this.constraints.add(
-		 new DistanceConstraint(
-                     new SpanElementQuery(this.field, unit), min, max, isInOrder, exclusion)
-	    );
-	return this;
+        // Element unit (sentence or paragraph)
+        return this.withConstraint(
+            min, max, new SpanElementQueryWrapper(this.field, unit), exclusion
+        );
     };
 
 
     /**
-     * Respect the order of distances.
+     * Add a sequence constraint (aka distance constraint)
+     * to the sequence based on a certain unit and with an
+     * exclusion constraint, meaning the constraint is fine
+     * in case the operands are <em>not</em> within the distance.
+     *
+     * Multiple constraints are supported.
+     *
+     * A minimum value of zero means, there may be an overlap,
+     * a minimum value of 1 means, there is no token between the spans.
+     * It's weird - we know and dislike that. That's why we have to say:
+     *
+     * <strong>Warning!</strong> Sequence constraints are experimental and
+     * may (hopefully) change in future versions!
+     *
+     * @param min The minimum number of tokens between the elements
+     *        of the sequence.
+     * @param max The minimum number of tokens between the elements
+     *        of the sequence.
+     * @param unit A {@link SpanElementQueryWrapper} as the unit for distance.
+     * @param exclusion Boolean value indicating, the distance constraint
+     *        has to fail.
+     * @return The {@link SpanSequenceQueryWrapper} object for chaining.
+     * @see DistanceConstraint
      */
-    public void setInOrder (boolean isInOrder) {
-	this.isInOrder = isInOrder;
+    public SpanSequenceQueryWrapper withConstraint
+        (int min, int max, SpanElementQueryWrapper unit, boolean exclusion) {
+        if (this.constraints == null)
+            this.constraints = new ArrayList<DistanceConstraint>(1);
+
+        // Element unit (sentence or paragraph)
+        // Todo: This should possibly be evaluated to a query later on!
+        try {
+            this.constraints.add(
+                new DistanceConstraint(
+                    (SpanElementQuery) unit.toQuery(),
+                    min,
+                    max,
+                    isInOrder,
+                    exclusion
+                )
+            );
+        }
+        catch (QueryException qe) {
+            this.constraintException = qe;
+        };
+        return this;
     };
 
 
     /**
-     * Check if the order is relevant.
+     * Check if the sequence has to be in order.
+     *
+     * @return <tt>true</tt> in case the sequence
+     *         has to be in order and <tt>false</tt>
+     *         in case the order is not relevant.
      */
     public boolean isInOrder () {
-	return this.isInOrder;
+        return this.isInOrder;
     };
 
 
     /**
-     * Check if there are constraints defined for the sequence.
+     * Set the boolean value indicating if the sequence
+     * has to be in order.
+     *
+     * @param order <tt>true</tt> in case the sequence
+     *        has to be in order and <tt>false</tt>
+     *        in case the order is not relevant.
+     */
+    public void setInOrder (boolean order) {
+        this.isInOrder = order;
+    };
+
+
+    /**
+     * Check if the sequence has constraints.
+     *
+     * @return <tt>true</tt> in case the sequence
+     *         has any constraints and <tt>false</tt>
+     *         in case it is a simple next query.
      */
     public boolean hasConstraints () {
-	if (this.constraints == null)
-	    return false;
-	if (this.constraints.size() <= 0)
-	    return false;
+        if (this.constraints == null)
+            return false;
 
-	// The constraint is in fact a next query
-	if (this.constraints.size() == 1) {
-	    DistanceConstraint dc = this.constraints.get(0);
-	    if (dc.getUnit().equals("w") &&
-		dc.getMinDistance() == 1 &&
-		dc.getMaxDistance() == 1) {
-		return false;
-	    };
-	};
+        if (this.constraints.size() <= 0)
+            return false;
+        
+        // The constraint is in fact a next query,
+        // that will be optimized away later on
+        if (this.constraints.size() == 1) {
+            DistanceConstraint dc = this.constraints.get(0);
+            if (dc.getUnit().equals("w") &&
+                dc.getMinDistance() == 1 &&
+                dc.getMaxDistance() == 1) {
+                return false;
+            };
+        };
 
-	return true;
+        return true;
     };
 
+
+    public boolean isEmpty () {
+        if (this.segments.size() == 1)
+            return this.segments.get(0).isEmpty();
+
+        if (!this.isSolved)
+            _solveProblematicSequence();
+        return super.isEmpty();
+    };
+
+
+    public boolean isOptional () {
+        if (this.segments.size() == 1)
+            return this.segments.get(0).isOptional();
+        if (!this.isSolved)
+            _solveProblematicSequence();
+        return super.isOptional();
+    };
+
+    public boolean isNegative () {
+        if (this.segments.size() == 1)
+            return this.segments.get(0).isNegative();
+        if (!this.isSolved)
+            _solveProblematicSequence();
+        return super.isNegative();
+    };
+
+    public boolean isExtendedToTheRight () {
+        if (!this.isSolved)
+            _solveProblematicSequence();
+        return this.isExtendedToTheRight;
+    };
+
+
     /**
-     * Serialize Query to Lucene SpanQueries
+     * Serialize the wrapped sequence to a {@link SpanQuery} object.
+     *
+     * @return A {@link SpanQuery} object.
+     * @throws QueryException
      */
     public SpanQuery toQuery () throws QueryException {
+
+        // There was a serialization failure not yet reported
+        if (this.constraintException != null)
+            throw constraintException;
+
         int size = this.segments.size();
 
         // Nothing to do
@@ -340,13 +602,19 @@
                 return (SpanQuery) this.segments.get(0).toQuery();
 
             if (this.segments.get(0).isEmpty())
-                throw new QueryException(613, "Sequence is not allowed to be empty");
+                throw new QueryException(
+                    613, "Sequence is not allowed to be empty"
+                );
 
             if (this.segments.get(0).isOptional())
-                throw new QueryException(613, "Sequence is not allowed to be optional");
+                throw new QueryException(
+                    613, "Sequence is not allowed to be optional"
+                );
 
             if (this.segments.get(0).isNegative())
-                throw new QueryException(613, "Sequence is not allowed to be negative");
+                throw new QueryException(
+                    613, "Sequence is not allowed to be negative"
+                );
         };
 
         if (!this.isSolved) {
@@ -465,259 +733,202 @@
         return (SpanQuery) query;
     };
 
+
+
     /*
+      Check if there are problematic segments in the sequence
+      (either negative, optional or empty) and deal with them
+      (make optional segments to or-queries and negative and empty
+      segments to extensions).
+      This has to be done as long as there are problematic segments
+      In the queries.
+
       While there is a segment isNegative() or isOptional() or isEmpty() do
       - look for an anchor next to it
       - merge the problematic segment with the anchor
       - go on
     */
     private boolean _solveProblematicSequence () {
+        int size = this.segments.size();
+        // Check if there is a problematic segment
+        SpanQueryWrapper underScrutiny;
+        boolean noRemainingProblem = true;
+        int i = 0;
 
-	int size = this.segments.size();
+        if (DEBUG)
+            log.trace("Try to solve a query of {} segments", size);
 
-	// Check if there is a problematic segment
-	SpanQueryWrapper underScrutiny;
-	boolean noRemainingProblem = true;
-	int i = 0;
+        // Iterate over all segments
+        for (; i < size;) {
+            underScrutiny = this.segments.get(i);
 
-	if (DEBUG)
-	    log.trace("Try to solve a query of {} segments", size);
+            // Check if there is a problem with the current segment
+            if (!underScrutiny.maybeAnchor()) {
 
-	for (; i < size;) {
-	    underScrutiny = this.segments.get(i);
+                if (DEBUG)
+                    log.trace("segment {} is problematic", i);
 
-	    // Check if there is a problem!
-	    if (!underScrutiny.maybeAnchor()) {
+                // [problem][anchor]
+                if (i < (size-1) && this.segments.get(i+1).maybeAnchor()) {
+                    if (DEBUG)
+                        log.trace("Situation is [problem][anchor]");
 
-		if (DEBUG)
-		    log.trace("segment {} is problematic", i);
+                    // Insert the solution
+                    try {
+                        this.segments.set(
+                          i+1,
+                          _merge(this.segments.get(i+1), underScrutiny, false)
+                        );
+                    }
 
-		// [problem][anchor]
-		if (i < (size-1) && this.segments.get(i+1).maybeAnchor()) {
-		    if (DEBUG)
-			log.trace("Situation is [problem][anchor]");
+                    // An error occurred while solving the problem
+                    catch (QueryException e) {
+                        return false;
+                    };
 
-		    // Insert the solution
-		    try {
-	 	        this.segments.set(
-		            i+1,
-		            _merge(this.segments.get(i+1), underScrutiny, false)
-		        );
-		    }
-		    catch (QueryException e) {
-			return false;
-		    };
+                    // Remove the problem
+                    this.segments.remove(i);
+                    size--;
 
-		    // Remove the problem
-		    this.segments.remove(i);
-		    size--;
+                    if (DEBUG)
+                        log.trace("Remove segment {} - now size {}", i, size);
 
-		    if (DEBUG)
-			log.trace("Remove segment {} - now size {}", i, size);
+                    // Restart checking
+                    i = 0;
+                }
 
-		    // Restart checking
-		    i = 0;
-		}
+                // [anchor][problem]
+                else if (i >= 1 && this.segments.get(i-1).maybeAnchor()) {
+                    if (DEBUG)
+                        log.trace("Situation is [anchor][problem]");
 
-		// [anchor][problem]
-		else if (i >= 1 && this.segments.get(i-1).maybeAnchor()) {
-		    if (DEBUG)
-			log.trace("Situation is [anchor][problem]");
+                    // Insert the solution
+                    try {
+                        this.segments.set(
+                            i-1,
+                            _merge(this.segments.get(i-1), underScrutiny, true)
+                        );
+                    }
+                    catch (QueryException e) {
+                        return false;
+                    };
 
-		    // Insert the solution
-		    try {
-			this.segments.set(
-			    i-1,
-			    _merge(this.segments.get(i-1), underScrutiny, true)
-			);
-		    }
-		    catch (QueryException e) {
-			return false;
-		    };
+                    // Remove the problem
+                    this.segments.remove(i);
+                    size--;
 
-		    // Remove the problem
-		    this.segments.remove(i);
-		    size--;
+                    if (DEBUG)
+                        log.trace("Remove segment {} - now size {}", i, size);
 
-		    if (DEBUG)
-			log.trace("Remove segment {} - now size {}", i, size);
+                    // Restart checking
+                    i = 0;
+                }
+                // [problem][problem]
+                else {
+                    if (DEBUG)
+                        log.trace("Situation is [problem][problem]");
+                    noRemainingProblem = false;
+                    i++;
+                };
+            }
+            else {
+                if (DEBUG)
+                    log.trace("segment {} can be an anchor", i);
+                i++;
+            };
+        };
 
-		    // Restart checking
-		    i = 0;
-		}
-		// [problem][problem]
-		else {
-		    if (DEBUG)
-			log.trace("Situation is [problem][problem]");
-		    noRemainingProblem = false;
-		    i++;
-		};
-	    }
-	    else {
-		if (DEBUG)
-		    log.trace("segment {} can be an anchor", i);
-		i++;
-	    };
-	};
+        // There is still a remaining problem
+        if (!noRemainingProblem) {
 
-	// There is still a remaining problem
-	if (!noRemainingProblem) {
+            // The size has changed - retry!
+            if (size != this.segments.size())
+                return _solveProblematicSequence();
 
-	    // The size has changed - retry!
-	    if (size != this.segments.size())
-		return _solveProblematicSequence();
+            this.isSolved = true;
+            return true;
+        };
 
-	    this.isSolved = true;
-	    return true;
-	};
-
-	this.isSolved = true;
-	return false;
+        this.isSolved = true;
+        return false;
     };
 
 
     // Todo: Deal with negative and optional!
     // [base=der][base!=Baum]?
-    private SpanQueryWrapper _merge (
-        SpanQueryWrapper anchor,
-	SpanQueryWrapper problem,
-	boolean mergeLeft) throws QueryException {
+    private SpanQueryWrapper _merge (SpanQueryWrapper anchor,
+                                     SpanQueryWrapper problem,
+                                     boolean mergeLeft) throws QueryException {
 
-	// Extend to the right - merge to the left
-	int direction = 1;
-	if (!mergeLeft)
-	    direction = -1;
+        // Extend to the right - merge to the left
+        int direction = mergeLeft ? 1 : -1;
 
-	if (DEBUG)
-	    log.trace("Will merge two spans to {}", mergeLeft ? "left" : "right");
+        if (DEBUG)
+            log.trace("Will merge two spans to {}",
+                      mergeLeft ? "left" : "right");
 	    
-	// Make empty extension to anchor
-	if (problem.isEmpty()) {
-	    SpanQuery query;
+        // Make empty extension to anchor
+        if (problem.isEmpty()) {
+            SpanQuery query;
 
-	    if (DEBUG)
-		log.trace("Problem is empty");
+            if (DEBUG)
+                log.trace("Problem is empty with class {}",
+                          problem.getClassNumber());
 
-	    if (problem.hasClass) {
+            query = new SpanExpansionQuery(
+                anchor.toQuery(),
+                problem.getMin(),
+                problem.getMax(),
+                direction,
+                problem.hasClass() ? problem.getClassNumber() : (byte) 0,
+                true
+            );
+            return new SpanSimpleQueryWrapper(query).isExtended(true);
+        }
 
-		if (DEBUG)
-		    log.trace("Problem has class {}", problem.getClassNumber());
+        // make negative extension to anchor
+        else if (problem.isNegative()) {
 
-		query = new SpanExpansionQuery(
-		    anchor.toQuery(),
-		    problem.getMin(),
-		    problem.getMax(),
-		    direction,
-		    problem.getClassNumber(),
-		    true
-		);
-	    }
-	    else {
+            SpanQuery query;
 
-		if (DEBUG)
-		    log.trace("Problem has no class");
+            if (DEBUG)
+                log.trace("Problem is negative with class {}",
+                          problem.getClassNumber());
 
-		query = new SpanExpansionQuery(
-		    anchor.toQuery(),
-		    problem.getMin(),
-		    problem.getMax(),
-		    direction,
-		    true
-		);
-	    };
-	    return new SpanSimpleQueryWrapper(query).isExtended(true);
-	}
+            query = new SpanExpansionQuery(
+                anchor.toQuery(),
+                problem.toQuery(),
+                problem.getMin(),
+                problem.getMax(),
+                direction,
+                problem.hasClass() ? problem.getClassNumber() : (byte) 0,
+                true
+            );
+            return new SpanSimpleQueryWrapper(query).isExtended(true);
+        };
 
-	// make negative extension to anchor
-	else if (problem.isNegative()) {
+        if (DEBUG)
+            log.trace("Problem is optional");
 
-	    if (DEBUG)
-		log.trace("Problem is negative");
+        // [base=der][base=baum]?
 
-	    SpanQuery query;
-	    if (problem.hasClass) {
+        // [base=der]
+        SpanAlterQueryWrapper saqw =
+            new SpanAlterQueryWrapper(this.field, anchor);
 
-		if (DEBUG)
-		    log.trace("Problem has class {}", problem.getClassNumber());
+        // [base=der]
+        SpanSequenceQueryWrapper ssqw =
+            new SpanSequenceQueryWrapper(this.field, anchor);
 
-		query = new SpanExpansionQuery(
-		    anchor.toQuery(),
-		    problem.toQuery(),
-		    problem.getMin(),
-		    problem.getMax(),
-		    direction,
-		    problem.getClassNumber(),
-		    true
-		);
-	    }
-	    else {
-		if (DEBUG)
-		    log.trace("Problem has no class");
-
-		query = new SpanExpansionQuery(
-		    anchor.toQuery(),
-		    problem.toQuery(),
-		    problem.getMin(),
-		    problem.getMax(),
-		    direction,
-		    true
-		);
-	    };
-	    return new SpanSimpleQueryWrapper(query).isExtended(true);
-	};
-
-	if (DEBUG)
-	    log.trace("Problem is optional");
-
-	// [base=der][base=baum]?
-
-	// [base=der]
-	SpanAlterQueryWrapper saqw = new SpanAlterQueryWrapper(this.field, anchor);
-
-	// [base=der]
-	SpanSequenceQueryWrapper ssqw = new SpanSequenceQueryWrapper(this.field, anchor);
-
-	// [base=der][base=baum]
-	if (mergeLeft)
-	    ssqw.append(new SpanSimpleQueryWrapper(problem.toQuery()));
-	// [base=baum][base=der]
-	else
-	    ssqw.prepend(new SpanSimpleQueryWrapper(problem.toQuery()));
+        // [base=der][base=baum]
+        if (mergeLeft)
+            ssqw.append(new SpanSimpleQueryWrapper(problem.toQuery()));
+        // [base=baum][base=der]
+        else
+            ssqw.prepend(new SpanSimpleQueryWrapper(problem.toQuery()));
 	
-	saqw.or(ssqw);
+        saqw.or(ssqw);
 
-	return (SpanQueryWrapper) saqw;
-    };
-
-    public boolean isEmpty () {
-	if (this.segments.size() == 0)
-	    return this.segments.get(0).isEmpty();
-	if (!this.isSolved)
-	    _solveProblematicSequence();
-	return super.isEmpty();
-    };
-
-
-    public boolean isOptional () {
-	if (this.segments.size() == 0)
-	    return this.segments.get(0).isOptional();
-	if (!this.isSolved)
-	    _solveProblematicSequence();
-	return super.isOptional();
-    };
-
-    public boolean isNegative () {
-	if (this.segments.size() == 0)
-	    return this.segments.get(0).isNegative();
-	if (!this.isSolved)
-	    _solveProblematicSequence();
-	return super.isNegative();
-    };
-
-    public boolean isExtendedToTheRight () {
-	if (!this.isSolved) {
-	    _solveProblematicSequence();
-	};
-	return this.isExtendedToTheRight;
+        return (SpanQueryWrapper) saqw;
     };
 };
diff --git a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanSimpleQueryWrapper.java b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanSimpleQueryWrapper.java
index dcc38da..39c1a7d 100644
--- a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanSimpleQueryWrapper.java
+++ b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanSimpleQueryWrapper.java
@@ -8,21 +8,21 @@
     private SpanQuery query;
 
     public SpanSimpleQueryWrapper (String field, String term) {
-	this.isNull = false;
-	this.query = new SpanTermQuery(new Term(field, term));
+        this.isNull = false;
+        this.query = new SpanTermQuery(new Term(field, term));
     };
 
     public SpanSimpleQueryWrapper (SpanQuery query) {
-	this.isNull = false;
-	this.query = query;
+        this.isNull = false;
+        this.query = query;
     };
 
     public SpanQuery toQuery () {
-	return this.query;
+        return this.query;
     };
 
     public SpanSimpleQueryWrapper isExtended (boolean extended) {
-	this.isExtended = true;
-	return this;
+        this.isExtended = true;
+        return this;
     };
 };
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 c5fd542..5720aa2 100644
--- a/src/test/java/de/ids_mannheim/korap/query/TestKorapQuery.java
+++ b/src/test/java/de/ids_mannheim/korap/query/TestKorapQuery.java
@@ -12,227 +12,230 @@
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 
+
+/**
+ * @author diewald
+ */
 @RunWith(JUnit4.class)
 public class TestKorapQuery {
 
     @Test
     public void korapQuerySegment () throws QueryException {
-	SpanQuery sq = new KorapQuery("field1").seg("a").with("b").toQuery();
-	assertEquals("spanSegment(field1:a, field1:b)", sq.toString());
-
-	sq = new KorapQuery("field2").seg("a", "b").with("c").toQuery();
-	assertEquals("spanSegment(spanSegment(field2:a, field2:b), field2:c)", sq.toString());
+        SpanQuery sq = new KorapQuery("field1").seg("a").with("b").toQuery();
+        assertEquals("spanSegment(field1:a, field1:b)", sq.toString());
+        
+        sq = new KorapQuery("field2").seg("a", "b").with("c").toQuery();
+        assertEquals("spanSegment(spanSegment(field2:a, field2:b), field2:c)", sq.toString());
     };
 
     @Test
     public void korapQueryRegexSegment () throws QueryException {
-	KorapQuery kq = new KorapQuery("field1");
-	SpanQuery sq = kq.seg("a").with(kq.re("b.*c")).toQuery();
-	assertEquals("spanSegment(field1:a, SpanMultiTermQueryWrapper(field1:/b.*c/))", sq.toString());
+        KorapQuery kq = new KorapQuery("field1");
+        SpanQuery sq = kq.seg("a").with(kq.re("b.*c")).toQuery();
+        assertEquals("spanSegment(field1:a, SpanMultiTermQueryWrapper(field1:/b.*c/))", sq.toString());
 
-	kq = new KorapQuery("field2");
-	sq = kq.seg(kq.re("a.*")).with("b").toQuery();
-	assertEquals("spanSegment(SpanMultiTermQueryWrapper(field2:/a.*/), field2:b)", sq.toString());
+        kq = new KorapQuery("field2");
+        sq = kq.seg(kq.re("a.*")).with("b").toQuery();
+        assertEquals("spanSegment(SpanMultiTermQueryWrapper(field2:/a.*/), field2:b)", sq.toString());
     };
 
     @Test
     public void korapQueryRegexSegment2 () throws QueryException {
-	KorapQuery kq = new KorapQuery("field");
-	SpanQuery sq = kq.seg("a").with(kq.or("b").or("c")).toQuery();
-	assertEquals("spanSegment(field:a, spanOr([field:b, field:c]))", sq.toString());
+        KorapQuery kq = new KorapQuery("field");
+        SpanQuery sq = kq.seg("a").with(kq.or("b").or("c")).toQuery();
+        assertEquals("spanSegment(field:a, spanOr([field:b, field:c]))", sq.toString());
 
-	kq = new KorapQuery("field");
-	sq = kq.seg("a").with(kq.or("b", "c")).toQuery();
-	assertEquals("spanSegment(field:a, spanOr([field:b, field:c]))", sq.toString());
+        kq = new KorapQuery("field");
+        sq = kq.seg("a").with(kq.or("b", "c")).toQuery();
+        assertEquals("spanSegment(field:a, spanOr([field:b, field:c]))", sq.toString());
 
-
-	kq = new KorapQuery("field");
-	// [ a & (b | /c.*d/) ]
-	sq = kq.seg("a").with(kq.or("b").or(kq.re("c.*d"))).toQuery();
-	assertEquals("spanSegment(field:a, spanOr([field:b, SpanMultiTermQueryWrapper(field:/c.*d/)]))", sq.toString());
+        kq = new KorapQuery("field");
+        // [ a & (b | /c.*d/) ]
+        sq = kq.seg("a").with(kq.or("b").or(kq.re("c.*d"))).toQuery();
+        assertEquals("spanSegment(field:a, spanOr([field:b, SpanMultiTermQueryWrapper(field:/c.*d/)]))", sq.toString());
     };
 
     @Test
     public void korapQuerySequenceSegment () throws QueryException {
-	KorapQuery kq = new KorapQuery("field");
-	SpanQuery sq = kq.seq(kq.seg("a").with(kq.or("b", "c"))).append("d").append(kq.re("e.?f")).toQuery();
-	assertEquals("spanNext(spanNext(spanSegment(field:a, spanOr([field:b, field:c])), field:d), SpanMultiTermQueryWrapper(field:/e.?f/))", sq.toString());
+        KorapQuery kq = new KorapQuery("field");
+        SpanQuery sq = kq.seq(kq.seg("a").with(kq.or("b", "c"))).append("d").append(kq.re("e.?f")).toQuery();
+        assertEquals("spanNext(spanNext(spanSegment(field:a, spanOr([field:b, field:c])), field:d), SpanMultiTermQueryWrapper(field:/e.?f/))", sq.toString());
     };
 
     @Test
     public void KorapTagQuery () throws QueryException {
-	KorapQuery kq = new KorapQuery("field");
-	SpanQuery sq = kq.tag("np").toQuery();
-	assertEquals("<field:np />", sq.toString());
+        KorapQuery kq = new KorapQuery("field");
+        SpanQuery sq = kq.tag("np").toQuery();
+        assertEquals("<field:np />", sq.toString());
     };
 
     @Test
     public void KorapTagQuery2 () throws QueryException {
-	KorapQuery kq = new KorapQuery("field");
-	SpanQuery sq = kq.or(kq.tag("np"), kq.tag("vp")).toQuery();
-	assertEquals("spanOr([<field:np />, <field:vp />])", sq.toString());
+        KorapQuery kq = new KorapQuery("field");
+        SpanQuery sq = kq.or(kq.tag("np"), kq.tag("vp")).toQuery();
+        assertEquals("spanOr([<field:np />, <field:vp />])", sq.toString());
     };
 
     @Test
     public void KorapTagQuery3 () throws QueryException {
-	KorapQuery kq = new KorapQuery("field");
-	SpanQuery sq = kq.seq(kq.tag("np"), kq.tag("vp")).toQuery();
-	assertEquals("spanNext(<field:np />, <field:vp />)", sq.toString());
+        KorapQuery kq = new KorapQuery("field");
+        SpanQuery sq = kq.seq(kq.tag("np"), kq.tag("vp")).toQuery();
+        assertEquals("spanNext(<field:np />, <field:vp />)", sq.toString());
     };
 
     @Test
     public void KorapTagQuery4 () throws QueryException {
-	KorapQuery kq = new KorapQuery("field");
-	SpanQuery sq = kq.seq(kq.tag("np"), kq.tag("vp")).append("test").toQuery();
-	assertEquals("spanNext(spanNext(<field:np />, <field:vp />), field:test)", sq.toString());
+        KorapQuery kq = new KorapQuery("field");
+        SpanQuery sq = kq.seq(kq.tag("np"), kq.tag("vp")).append("test").toQuery();
+        assertEquals("spanNext(spanNext(<field:np />, <field:vp />), field:test)", sq.toString());
     };
 
     @Test
     public void KorapTagQuery5 () throws QueryException {
-	KorapQuery kq = new KorapQuery("field");
-	SpanQuery sq = kq.contains(kq.tag("s"), kq.tag("np")).toQuery();
-	assertEquals("spanContain(<field:s />, <field:np />)", sq.toString());
+        KorapQuery kq = new KorapQuery("field");
+        SpanQuery sq = kq.contains(kq.tag("s"), kq.tag("np")).toQuery();
+        assertEquals("spanContain(<field:s />, <field:np />)", sq.toString());
     };
 
     @Test
     public void KorapTagQuery6 () throws QueryException {
-	KorapQuery kq = new KorapQuery("field");
-	SpanQuery sq = kq.seq(kq.seg("tree"), kq.contains(kq.tag("s"), kq.tag("np")), kq.re("hey.*")).toQuery();
-	assertEquals("spanNext(spanNext(field:tree, spanContain(<field:s />, <field:np />)), SpanMultiTermQueryWrapper(field:/hey.*/))", sq.toString());
+        KorapQuery kq = new KorapQuery("field");
+        SpanQuery sq = kq.seq(kq.seg("tree"), kq.contains(kq.tag("s"), kq.tag("np")), kq.re("hey.*")).toQuery();
+        assertEquals("spanNext(spanNext(field:tree, spanContain(<field:s />, <field:np />)), SpanMultiTermQueryWrapper(field:/hey.*/))", sq.toString());
     };
-
+    
 
     @Test
     public void KorapClassQuery () throws QueryException {
-	KorapQuery kq = new KorapQuery("field");
-	SpanQuery sq = kq.seq(kq.seg("tree"), kq._(1, kq.contains(kq.tag("s"), kq.tag("np"))), kq.re("hey.*")).toQuery();
-	assertEquals("spanNext(spanNext(field:tree, {1: spanContain(<field:s />, <field:np />)}), SpanMultiTermQueryWrapper(field:/hey.*/))", sq.toString());
+        KorapQuery kq = new KorapQuery("field");
+        SpanQuery sq = kq.seq(kq.seg("tree"), kq._(1, kq.contains(kq.tag("s"), kq.tag("np"))), kq.re("hey.*")).toQuery();
+        assertEquals("spanNext(spanNext(field:tree, {1: spanContain(<field:s />, <field:np />)}), SpanMultiTermQueryWrapper(field:/hey.*/))", sq.toString());
     };
 
     @Test
     public void KorapClassQuery2 () throws QueryException {
-	KorapQuery kq = new KorapQuery("field");
-	SpanQuery sq = kq._(kq.seg("base:test")).toQuery();
-	assertEquals("{1: field:base:test}", sq.toString());
+        KorapQuery kq = new KorapQuery("field");
+        SpanQuery sq = kq._(kq.seg("base:test")).toQuery();
+        assertEquals("{1: field:base:test}", sq.toString());
     };
 
     @Test
     public void KorapClassQuery3 () throws QueryException {
-	KorapQuery kq = new KorapQuery("field");
-	SpanQuery sq = kq.seq(kq.seg("tree"), kq.contains(kq.tag("s"), kq._(kq.tag("np"))), kq.re("hey.*")).toQuery();
-	assertEquals("spanNext(spanNext(field:tree, spanContain(<field:s />, {1: <field:np />})), SpanMultiTermQueryWrapper(field:/hey.*/))", sq.toString());
+        KorapQuery kq = new KorapQuery("field");
+        SpanQuery sq = kq.seq(kq.seg("tree"), kq.contains(kq.tag("s"), kq._(kq.tag("np"))), kq.re("hey.*")).toQuery();
+        assertEquals("spanNext(spanNext(field:tree, spanContain(<field:s />, {1: <field:np />})), SpanMultiTermQueryWrapper(field:/hey.*/))", sq.toString());
     };
 
     @Test
     public void KorapShrinkQuery () throws QueryException {
-	KorapQuery kq = new KorapQuery("field");
-	SpanQuery sq = kq.shrink(kq.tag("np")).toQuery();
-	assertEquals("shrink(1: <field:np />)", sq.toString());
+        KorapQuery kq = new KorapQuery("field");
+        SpanQuery sq = kq.shrink(kq.tag("np")).toQuery();
+        assertEquals("shrink(1: <field:np />)", sq.toString());
     };
 
     @Test
     public void KorapShrinkQuery1 () throws QueryException {
-	KorapQuery kq = new KorapQuery("field");
-	SpanQuery sq = kq.shrink(1, kq.tag("np")).toQuery();
-	assertEquals("shrink(1: <field:np />)", sq.toString());
+        KorapQuery kq = new KorapQuery("field");
+        SpanQuery sq = kq.shrink(1, kq.tag("np")).toQuery();
+        assertEquals("shrink(1: <field:np />)", sq.toString());
     };
 
     @Test
     public void KorapShrinkQuery2 () throws QueryException {
-	KorapQuery kq = new KorapQuery("field");
-	SpanQuery sq = kq.shrink(1, kq._(1, kq.tag("np"))).toQuery();
-	assertEquals("shrink(1: {1: <field:np />})", sq.toString());
+        KorapQuery kq = new KorapQuery("field");
+        SpanQuery sq = kq.shrink(1, kq._(1, kq.tag("np"))).toQuery();
+        assertEquals("shrink(1: {1: <field:np />})", sq.toString());
     };
 
     @Test
     public void KorapShrinkQuery3 () throws QueryException {
-	KorapQuery kq = new KorapQuery("field");
-	SpanQuery sq = kq.shrink(1, kq._(1, kq.seq(kq.tag("np"), kq._(kq.seg("test").without("no"))))).toQuery();
-	assertEquals("shrink(1: {1: spanNext(<field:np />, {1: spanNot(field:test, field:no, 0, 0)})})", sq.toString());
+        KorapQuery kq = new KorapQuery("field");
+        SpanQuery sq = kq.shrink(1, kq._(1, kq.seq(kq.tag("np"), kq._(kq.seg("test").without("no"))))).toQuery();
+        assertEquals("shrink(1: {1: spanNext(<field:np />, {1: spanNot(field:test, field:no, 0, 0)})})", sq.toString());
     };
 
     @Test
     public void KorapShrinkQuery4 () throws QueryException {
-	KorapQuery kq = new KorapQuery("field");
-	SpanQuery sq = kq.seq(kq.seg("try1"), kq.shrink(1, kq._(1, kq.seg("try2"))), kq.seg("try3")).toQuery();
-	assertEquals("spanNext(spanNext(field:try1, shrink(1: {1: field:try2})), field:try3)", sq.toString());
+        KorapQuery kq = new KorapQuery("field");
+        SpanQuery sq = kq.seq(kq.seg("try1"), kq.shrink(1, kq._(1, kq.seg("try2"))), kq.seg("try3")).toQuery();
+        assertEquals("spanNext(spanNext(field:try1, shrink(1: {1: field:try2})), field:try3)", sq.toString());
     };
 
     @Test
     public void KorapSequenceQuery1 () throws QueryException {
-	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());
+        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 () throws QueryException {
-	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());
+        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 () throws QueryException {
-	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());
+        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 () throws QueryException {
-	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());
+        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 () throws QueryException {
-	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());
+        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 () throws QueryException {
-	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());
+        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 () throws QueryException {
-	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());
+        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 () throws QueryException {
-	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());
+        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());
     };
 
     @Test
     public void KorapWithinQuery1 () throws QueryException {
-	KorapQuery kq = new KorapQuery("field");
-	SpanQuery sq = kq.contains(kq.seg("test"), kq.seg("test2")).toQuery();
-	assertEquals("spanContain(field:test, field:test2)", sq.toString());
+        KorapQuery kq = new KorapQuery("field");
+        SpanQuery sq = kq.contains(kq.seg("test"), kq.seg("test2")).toQuery();
+        assertEquals("spanContain(field:test, field:test2)", sq.toString());
     };
 
     @Test
     public void KorapWithinQuery2 () throws QueryException {
-	KorapQuery kq = new KorapQuery("field");
-	SpanQuery sq = kq.overlaps(kq.seg("test"), kq.seg("test2")).toQuery();
-	assertEquals("spanOverlap(field:test, field:test2)", sq.toString());
+        KorapQuery kq = new KorapQuery("field");
+        SpanQuery sq = kq.overlaps(kq.seg("test"), kq.seg("test2")).toQuery();
+        assertEquals("spanOverlap(field:test, field:test2)", sq.toString());
     };
 
     @Test
     public void KorapWithinQuery3 () throws QueryException {
-	KorapQuery kq = new KorapQuery("field");
-	SpanQuery sq = kq.startswith(kq.seg("test"), kq.seg("test2")).toQuery();
-	assertEquals("spanStartsWith(field:test, field:test2)", sq.toString());
+        KorapQuery kq = new KorapQuery("field");
+        SpanQuery sq = kq.startswith(kq.seg("test"), kq.seg("test2")).toQuery();
+        assertEquals("spanStartsWith(field:test, field:test2)", sq.toString());
     };
    
     // kq.seg("a").append(kq.ANY).append("b:c");
diff --git a/src/test/java/de/ids_mannheim/korap/query/TestSpanSequenceQuery.java b/src/test/java/de/ids_mannheim/korap/query/TestSpanSequenceQuery.java
index f6fd664..4115e59 100644
--- a/src/test/java/de/ids_mannheim/korap/query/TestSpanSequenceQuery.java
+++ b/src/test/java/de/ids_mannheim/korap/query/TestSpanSequenceQuery.java
@@ -2,6 +2,9 @@
 
 import java.util.*;
 import de.ids_mannheim.korap.query.wrap.SpanSequenceQueryWrapper;
+import de.ids_mannheim.korap.query.wrap.SpanClassQueryWrapper;
+import de.ids_mannheim.korap.query.wrap.SpanElementQueryWrapper;
+import de.ids_mannheim.korap.query.wrap.SpanRepetitionQueryWrapper;
 
 import de.ids_mannheim.korap.util.QueryException;
 
@@ -11,42 +14,162 @@
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 
+
+/**
+ * @author margaretha, diewald
+ */
 @RunWith(JUnit4.class)
 public class TestSpanSequenceQuery {
 
     @Test
     public void spanSequenceQuery () throws QueryException {
-	SpanSequenceQueryWrapper sssq = new SpanSequenceQueryWrapper("field");
-	assertNull(sssq.toQuery());
-	assertFalse(sssq.hasConstraints());
+        SpanSequenceQueryWrapper sssq = new SpanSequenceQueryWrapper("field");
+        assertNull(sssq.toQuery());
+        assertFalse(sssq.hasConstraints());
 
-	sssq.append("a").append("b");
-	assertEquals("spanNext(field:a, field:b)", sssq.toQuery().toString());
-	assertFalse(sssq.hasConstraints());
+        sssq.append("a").append("b");
+        assertEquals("spanNext(field:a, field:b)", sssq.toQuery().toString());
+        assertFalse(sssq.hasConstraints());
 
-	sssq.append("c");
-	assertEquals("spanNext(spanNext(field:a, field:b), field:c)", sssq.toQuery().toString());
-	assertFalse(sssq.hasConstraints());
+        sssq.append("c");
+        assertEquals("spanNext(spanNext(field:a, field:b), field:c)", sssq.toQuery().toString());
+        assertFalse(sssq.hasConstraints());
 
-	sssq = new SpanSequenceQueryWrapper("field");
-	sssq.append("a");
-	assertEquals("field:a", sssq.toQuery().toString());
-	assertFalse(sssq.hasConstraints());
+        sssq = new SpanSequenceQueryWrapper("field");
+        sssq.append("a");
+        assertEquals("field:a", sssq.toQuery().toString());
+        assertFalse(sssq.hasConstraints());
 
-	sssq.append("b");
-	assertEquals("spanNext(field:a, field:b)", sssq.toQuery().toString());
-	assertFalse(sssq.hasConstraints());
+        sssq.append("b");
+        assertEquals("spanNext(field:a, field:b)", sssq.toQuery().toString());
+        assertFalse(sssq.hasConstraints());
 
-	sssq.withConstraint(2,3);
-	assertTrue(sssq.hasConstraints());
+        sssq.withConstraint(2,3);
+        assertTrue(sssq.hasConstraints());
 
-	assertEquals("spanDistance(field:a, field:b, [(w[2:3], ordered, notExcluded)])", sssq.toQuery().toString());
+        assertEquals("spanDistance(field:a, field:b, [(w[2:3], ordered, notExcluded)])", sssq.toQuery().toString());
 
-	sssq.append("c");
-	assertEquals("spanDistance(spanDistance(field:a, field:b, [(w[2:3], ordered, notExcluded)]), field:c, [(w[2:3], ordered, notExcluded)])", sssq.toQuery().toString());
-	sssq.withConstraint(6,8, "s");
-	assertTrue(sssq.hasConstraints());
+        sssq.append("c");
+        assertEquals("spanDistance(spanDistance(field:a, field:b, [(w[2:3], ordered, notExcluded)]), field:c, [(w[2:3], ordered, notExcluded)])", sssq.toQuery().toString());
+        sssq.withConstraint(6,8, "s");
+        assertTrue(sssq.hasConstraints());
 
-	assertEquals("spanMultipleDistance(spanMultipleDistance(field:a, field:b, [(w[2:3], ordered, notExcluded), (s[6:8], ordered, notExcluded)]), field:c, [(w[2:3], ordered, notExcluded), (s[6:8], ordered, notExcluded)])", sssq.toQuery().toString());
+        assertEquals("spanMultipleDistance(spanMultipleDistance(field:a, field:b, [(w[2:3], ordered, notExcluded), (s[6:8], ordered, notExcluded)]), field:c, [(w[2:3], ordered, notExcluded), (s[6:8], ordered, notExcluded)])", sssq.toQuery().toString());
+    };
+
+    @Test
+    public void spanSequenceQueryWrapper () throws QueryException {
+
+        SpanSequenceQueryWrapper ssqw, ssqw2;
+        SpanRepetitionQueryWrapper srqw;
+        SpanClassQueryWrapper scqw;
+
+        // Synopsis 1
+        ssqw =
+            new SpanSequenceQueryWrapper("tokens", "der", "Baum");
+        assertEquals("spanNext(tokens:der, tokens:Baum)", ssqw.toQuery().toString());
+
+        // Synopsis 2
+        ssqw = new SpanSequenceQueryWrapper("tokens");
+        ssqw.append("der").append("Baum");
+        assertEquals("spanNext(tokens:der, tokens:Baum)", ssqw.toQuery().toString());
+
+        // Append a sequence
+        ssqw = new SpanSequenceQueryWrapper("tokens");
+        ssqw2 = new SpanSequenceQueryWrapper("tokens");
+        ssqw.append("der").append("Baum");
+        ssqw2.append("fiel").append("still");
+        ssqw.append(ssqw2);
+        // This may not be final
+        assertEquals(
+            "spanNext(spanNext(spanNext(tokens:der, tokens:Baum), tokens:fiel), tokens:still)",
+            ssqw.toQuery().toString()
+        );
+
+        // Synopsis 3
+        ssqw = new SpanSequenceQueryWrapper("tokens", "Baum");
+        ssqw.prepend("der");
+        assertEquals("spanNext(tokens:der, tokens:Baum)", ssqw.toQuery().toString());
+
+        // Prepend a sequence
+        ssqw = new SpanSequenceQueryWrapper("tokens");
+        ssqw2 = new SpanSequenceQueryWrapper("tokens");
+        ssqw.append("fiel").append("still");
+        ssqw2.append("der").append("Baum");
+        ssqw.prepend(ssqw2);
+
+        // This may change
+        assertEquals(
+            "spanNext(spanNext(spanNext(tokens:der, tokens:Baum), tokens:fiel), tokens:still)",
+            ssqw.toQuery().toString()
+        );
+
+        // Add constraint
+        ssqw.withConstraint(2,4);
+        // This may change
+        assertEquals(
+            "spanDistance(spanDistance(spanDistance(tokens:der, "+
+            "tokens:Baum, [(w[2:4], ordered, notExcluded)]), "+
+            "tokens:fiel, [(w[2:4], ordered, notExcluded)]), "+
+            "tokens:still, [(w[2:4], ordered, notExcluded)])",
+            ssqw.toQuery().toString()
+        );
+
+        ssqw = new SpanSequenceQueryWrapper("tokens", "der", "Baum").withConstraint(1,1);
+        assertEquals("spanNext(tokens:der, tokens:Baum)", ssqw.toQuery().toString());
+
+        ssqw = new SpanSequenceQueryWrapper("tokens", "der", "Baum").withConstraint(1,2, "s");
+        assertEquals("spanElementDistance(tokens:der, tokens:Baum, [(s[1:2], ordered, notExcluded)])", ssqw.toQuery().toString());
+
+        ssqw = new SpanSequenceQueryWrapper("tokens", "der", "Baum")
+            .withConstraint(1,2, "s")
+            .withConstraint(2,3, "x");
+        assertEquals("spanMultipleDistance(tokens:der, tokens:Baum, " +
+                     "[(s[1:2], ordered, notExcluded), " +
+                     "(x[2:3], ordered, notExcluded)])",
+                     ssqw.toQuery().toString());
+
+        ssqw = new SpanSequenceQueryWrapper("tokens")
+            .append("Baum")
+            .prepend("der")
+            .withConstraint(1,2, "s", true)
+            .withConstraint(2,3, "x");
+        assertEquals("spanMultipleDistance(tokens:der, " +
+                     "tokens:Baum, [(s[1:2], ordered, excluded), " +
+                     "(x[2:3], ordered, notExcluded)])",
+                     ssqw.toQuery().toString());
+
+
+        // Support empty class ins sequence 
+        ssqw = new SpanSequenceQueryWrapper("field", "Der");
+        srqw = new SpanRepetitionQueryWrapper();
+        scqw = new SpanClassQueryWrapper(srqw, (short) 3);
+        ssqw.append(scqw);
+        assertEquals(
+            "spanExpansion(field:Der, []{1, 1}, right, class:3)",
+            ssqw.toQuery().toString()
+        );
+
+        // Support empty class ins sequence 
+        ssqw = new SpanSequenceQueryWrapper("field");
+        srqw = new SpanRepetitionQueryWrapper();
+        ssqw.append(srqw);
+        scqw = new SpanClassQueryWrapper(ssqw, (short) 2);
+        try {
+            scqw.toQuery();
+        }
+        catch (Exception e) {
+            fail(e.getMessage() + "(Known issue)");
+        };
+        // assertEquals("", scqw.toQuery().toString());
+
+        /*
+
+        sssq = new SpanSequenceQueryWrapper("field");
+        sssc = new SpanClassQueryWrapper(sssq, (short) 2);
+        SpanSequenceQueryWrapper sssq2 = new SpanSequenceQueryWrapper("field");
+        sssq2.append("hui").append(sssc);
+        assertEquals("", sssq2.toQuery().toString());
+        */
     };
 };
diff --git a/src/test/java/de/ids_mannheim/korap/query/TestSpanSequenceQueryJSON.java b/src/test/java/de/ids_mannheim/korap/query/TestSpanSequenceQueryJSON.java
index 766d6ee..fd3f239 100644
--- a/src/test/java/de/ids_mannheim/korap/query/TestSpanSequenceQueryJSON.java
+++ b/src/test/java/de/ids_mannheim/korap/query/TestSpanSequenceQueryJSON.java
@@ -14,6 +14,10 @@
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 
+/**
+ * @author diewald
+ */
+
 @RunWith(JUnit4.class)
 public class TestSpanSequenceQueryJSON {