Sort focus operations on demand

Change-Id: Ia2809078a4b7c6ed485740895f77fadfa6bde2bf
diff --git a/Changes b/Changes
index 8df015e..2ba1664 100644
--- a/Changes
+++ b/Changes
@@ -1,4 +1,4 @@
-0.58.1 2018-11-28
+0.58.1 2018-12-05
     - [bugfix] Security upgrade of Jackson for CVE-2017-17485 and
       CVE-2018-7489 (diewald)
     - [bugfix] Span expansion with negation (margaretha)
@@ -15,6 +15,7 @@
     - [bugfix] Fixed right expansion match order & expansion over start (margaretha)
     - [feature] Added opt() method to QueryBuilder (diewald)
     - [bugfix] Improved FocusSpans sorting (margaretha)
+    - [bugfix] Adopt sorting for FocusSpans in SpanQueryWrappers (diewald)
 
 0.58.0 2018-09-03
     - [feature] Implemented referencing cached collection (margaretha)
diff --git a/src/main/java/de/ids_mannheim/korap/query/SpanFocusQuery.java b/src/main/java/de/ids_mannheim/korap/query/SpanFocusQuery.java
index 959c7ff..ae2e8d5 100644
--- a/src/main/java/de/ids_mannheim/korap/query/SpanFocusQuery.java
+++ b/src/main/java/de/ids_mannheim/korap/query/SpanFocusQuery.java
@@ -99,6 +99,9 @@
             buffer.append((short) classNumbers.get(0) & 0xFF).append(": ");
         }
         buffer.append(this.firstClause.toString());
+        if (!this.isSorted()) {
+            buffer.append(",sorting");
+        }
         buffer.append(')');
         buffer.append(ToStringUtils.boost(getBoost()));
         return buffer.toString();
diff --git a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanAlterQueryWrapper.java b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanAlterQueryWrapper.java
index 9b71cbf..4ed669f 100644
--- a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanAlterQueryWrapper.java
+++ b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanAlterQueryWrapper.java
@@ -1,23 +1,16 @@
 package de.ids_mannheim.korap.query.wrap;
 
-import de.ids_mannheim.korap.query.wrap.SpanRegexQueryWrapper;
-import de.ids_mannheim.korap.query.wrap.SpanWildcardQueryWrapper;
-import de.ids_mannheim.korap.query.wrap.SpanSegmentQueryWrapper;
-import de.ids_mannheim.korap.query.wrap.SpanSimpleQueryWrapper;
-import de.ids_mannheim.korap.query.wrap.SpanQueryWrapper;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.lucene.search.spans.SpanOrQuery;
+import org.apache.lucene.search.spans.SpanQuery;
 
 import de.ids_mannheim.korap.util.QueryException;
 
-import org.apache.lucene.search.spans.SpanQuery;
-import org.apache.lucene.search.spans.SpanTermQuery;
-import org.apache.lucene.search.spans.SpanOrQuery;
-import org.apache.lucene.index.Term;
-
-import java.util.*;
-
 public class SpanAlterQueryWrapper extends SpanQueryWrapper {
     private String field;
-    private SpanQuery query;
     private List<SpanQueryWrapper> alternatives;
 
 
@@ -27,18 +20,10 @@
     };
 
 
-    public SpanAlterQueryWrapper (String field, SpanQuery query) {
-        this.field = field;
-        this.alternatives = new ArrayList<>();
-        this.alternatives.add(new SpanSimpleQueryWrapper(query));
-    };
-
-
     public SpanAlterQueryWrapper (String field, SpanQueryWrapper query) {
         this.field = field;
         this.alternatives = new ArrayList<>();
-        if (query.maybeUnsorted())
-            this.maybeUnsorted = true;
+        this.maybeUnsorted = query.maybeUnsorted();
         this.alternatives.add(query);
     };
 
@@ -48,21 +33,16 @@
         this.alternatives = new ArrayList<>();
         for (String term : terms) {
             this.isNull = false;
-            this.alternatives.add(new SpanSimpleQueryWrapper(
-                    new SpanTermQuery(new Term(this.field, term))));
+            this.alternatives.add(
+                new SpanSimpleQueryWrapper(this.field, term)
+                );
         };
     };
 
 
     public SpanAlterQueryWrapper or (String term) {
-        return this.or(new SpanTermQuery(new Term(this.field, term)));
-    };
-
-
-    public SpanAlterQueryWrapper or (SpanQuery query) {
-        this.alternatives.add(new SpanSimpleQueryWrapper(query));
-        this.isNull = false;
-        return this;
+        SpanQueryWrapper sqw = new SpanSimpleQueryWrapper(this.field, term);
+        return this.or(sqw);
     };
 
 
diff --git a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanAttributeQueryWrapper.java b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanAttributeQueryWrapper.java
index d2941f9..0e22fd7 100644
--- a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanAttributeQueryWrapper.java
+++ b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanAttributeQueryWrapper.java
@@ -31,8 +31,7 @@
             this.isNegative = true;
         };
 
-        if (sqw.maybeUnsorted())
-            this.maybeUnsorted = true;
+        this.maybeUnsorted = sqw.maybeUnsorted();
     };
 
 
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 c06194f..ff9ae05 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
@@ -18,6 +18,7 @@
         this.number = number;
         if (number != (byte) 0)
             this.hasClass = true;
+        this.maybeUnsorted = subquery.maybeUnsorted();
     };
 
 
@@ -59,13 +60,6 @@
         return this.subquery.isNegative();
     };
 
-
-    @Override
-    public boolean maybeUnsorted () {
-        return this.subquery.maybeUnsorted();
-    };
-
-
     public SpanQuery toFragmentQuery () throws QueryException {
         if (this.subquery.isNull())
             return (SpanQuery) null;
diff --git a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanElementQueryWrapper.java b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanElementQueryWrapper.java
index 3112dc2..811d0e3 100644
--- a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanElementQueryWrapper.java
+++ b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanElementQueryWrapper.java
@@ -15,7 +15,7 @@
  */
 
 public class SpanElementQueryWrapper extends SpanQueryWrapper {
-    String element;
+    protected String element;
     String field;
 
 
diff --git a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanExpansionQueryWrapper.java b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanExpansionQueryWrapper.java
index f4011c2..a445781 100644
--- a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanExpansionQueryWrapper.java
+++ b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanExpansionQueryWrapper.java
@@ -1,15 +1,10 @@
 package de.ids_mannheim.korap.query.wrap;
 
-import org.apache.lucene.search.RegexpQuery;
 import org.apache.lucene.search.spans.SpanQuery;
-import org.apache.lucene.util.automaton.RegExp;
-import org.apache.lucene.index.Term;
-import de.ids_mannheim.korap.query.wrap.SpanQueryWrapper;
+
 import de.ids_mannheim.korap.query.SpanExpansionQuery;
 import de.ids_mannheim.korap.util.QueryException;
 
-import java.util.*;
-
 /*
  * TODO: SpanExpansionQueryWrapper currently does not support negative extensions!
  */
@@ -40,6 +35,7 @@
         this.isExtended = true;
         if (direction >= 0)
             this.isExtendedToTheRight = true;
+        this.maybeUnsorted = anchor.maybeUnsorted();
     };
 
 
diff --git a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanFocusQueryWrapper.java b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanFocusQueryWrapper.java
index 89d8f65..2c3a39a 100644
--- a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanFocusQueryWrapper.java
+++ b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanFocusQueryWrapper.java
@@ -2,24 +2,11 @@
 
 import org.apache.lucene.search.spans.SpanQuery;
 
+import de.ids_mannheim.korap.query.SpanFocusQuery;
 import de.ids_mannheim.korap.util.QueryException;
 
-import de.ids_mannheim.korap.query.SpanFocusQuery;
-import de.ids_mannheim.korap.query.wrap.SpanQueryWrapper;
-
-import java.util.*;
-
-// Support maybeUnsorted!
-// Rename this to SpanFocusQueryWrapper
 // Support multiple classes
 
-// Sorting:
-// - Sort with a buffer of matches, e.g. 25/50,
-// So gather 50 hits, sort them, return the first 25,
-// Add new 25, sort the last 50, return 25 etc.
-// On processing, there should be an ability to raise
-// a warning, in case an unordered result bubbles up.
-
 public class SpanFocusQueryWrapper extends SpanQueryWrapper {
     private SpanQueryWrapper subquery;
     private byte number;
@@ -52,9 +39,16 @@
     public SpanQuery toFragmentQuery () throws QueryException {
         if (this.subquery.isNull())
             return (SpanQuery) null;
-        return new SpanFocusQuery(
-                this.subquery.retrieveNode(this.retrieveNode).toFragmentQuery(),
-                this.number);
+
+        SpanFocusQuery sfq = new SpanFocusQuery(
+            this.subquery.retrieveNode(this.retrieveNode).toFragmentQuery(),
+            this.number);
+
+        if (this.subquery.maybeUnsorted())
+            sfq.setSorted(false);
+
+        return sfq;
+        
     };
 
 
diff --git a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanQueryWrapper.java b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanQueryWrapper.java
index 20d19ff..4fca2a6 100644
--- a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanQueryWrapper.java
+++ b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanQueryWrapper.java
@@ -72,9 +72,18 @@
 
         // Wrap the query in a <base/s=t>, if it's extended to the right
         if (this.isExtendedToTheRight()) {
-            return new SpanFocusQuery(new SpanWithinQuery("base/s:t",
+            SpanFocusQuery sfc = new SpanFocusQuery(new SpanWithinQuery("base/s:t",
                     new SpanClassQuery(this.toFragmentQuery(), (byte) 254)),
                     (byte) 254);
+
+            // Only sort, in case it wraps an unsorted query,
+            // within base/s:t is sorted per definition.
+            if (this.maybeUnsorted()) {
+                sfc.setSorted(false);
+            };
+
+            return sfc;
+
         };
         
         SpanQuery sq = this.toFragmentQuery();
@@ -280,7 +289,7 @@
      * Normally spans are always sorted, but in case of
      * a wrapped relation query, classed operands may
      * be in arbitrary order. When focussing on these
-     * classes, the span has to me reordered.
+     * classes, the span has to be reordered.
      * 
      * @return <tt>true</tt> in case the wrapped query
      *         has to be sorted on focussing,
@@ -429,7 +438,8 @@
                 + (this.isEmpty() ? "isEmpty" : "notEmpty") + "-"
                 + (this.isOptional() ? "isOptional" : "notOptional") + "-"
                 + (this.isExtendedToTheRight() ? "isExtendedToTheRight"
-                        : "notExtendedToTheRight");;
+                   : "notExtendedToTheRight") + "-"
+            + (this.maybeUnsorted() ? "maybeUnsorted" : "notUnsorted");
         return string;
     };
 };
diff --git a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanReferenceQueryWrapper.java b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanReferenceQueryWrapper.java
index c874fef..830fbfe 100644
--- a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanReferenceQueryWrapper.java
+++ b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanReferenceQueryWrapper.java
@@ -30,6 +30,7 @@
                     "Class number must be bigger than 0.");
         }
         this.classNum = classNum;
+        this.maybeUnsorted = subQueryWrapper.maybeUnsorted();
     }
 
 
diff --git a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanRegexQueryWrapper.java b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanRegexQueryWrapper.java
index 30ea49b..a3ed45a 100644
--- a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanRegexQueryWrapper.java
+++ b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanRegexQueryWrapper.java
@@ -1,13 +1,10 @@
 package de.ids_mannheim.korap.query.wrap;
 
-import org.apache.lucene.search.RegexpQuery;
-import org.apache.lucene.search.spans.SpanQuery;
-import org.apache.lucene.search.spans.SpanMultiTermQueryWrapper;
-import org.apache.lucene.util.automaton.RegExp;
 import org.apache.lucene.index.Term;
-import de.ids_mannheim.korap.query.wrap.SpanQueryWrapper;
-
-import java.util.*;
+import org.apache.lucene.search.RegexpQuery;
+import org.apache.lucene.search.spans.SpanMultiTermQueryWrapper;
+import org.apache.lucene.search.spans.SpanQuery;
+import org.apache.lucene.util.automaton.RegExp;
 
 /*
   TODO: Don't allow queries like ".*?"!!!
diff --git a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanRelationWrapper.java b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanRelationWrapper.java
index fe980c9..c87d551 100644
--- a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanRelationWrapper.java
+++ b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanRelationWrapper.java
@@ -1,8 +1,6 @@
 package de.ids_mannheim.korap.query.wrap;
 
-import org.apache.lucene.search.spans.SpanMultiTermQueryWrapper;
 import org.apache.lucene.search.spans.SpanQuery;
-import org.apache.lucene.search.spans.SpanTermQuery;
 
 import de.ids_mannheim.korap.constants.RelationDirection;
 import de.ids_mannheim.korap.query.SpanFocusQuery;
@@ -35,6 +33,7 @@
 
         this.subQuery1 = operand1;
         this.subQuery2 = operand2;
+        this.maybeUnsorted = true;
     }
 
 
diff --git a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanRepetitionQueryWrapper.java b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanRepetitionQueryWrapper.java
index ec88b04..4279640 100644
--- a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanRepetitionQueryWrapper.java
+++ b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanRepetitionQueryWrapper.java
@@ -30,8 +30,7 @@
 
         if (!subquery.isEmpty()) {
             this.subquery = subquery;
-            if (subquery.maybeUnsorted())
-                this.maybeUnsorted = true;
+            this.maybeUnsorted = subquery.maybeUnsorted();
 			this.isEmpty = false;
         }
         else
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 8623671..18752ce 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
@@ -1,18 +1,13 @@
 package de.ids_mannheim.korap.query.wrap;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Iterator;
 
-import org.apache.lucene.index.Term;
-import org.apache.lucene.search.Query;
-import org.apache.lucene.search.spans.SpanQuery;
-import org.apache.lucene.search.spans.SpanTermQuery;
 import org.apache.lucene.search.spans.SpanNotQuery;
 import org.apache.lucene.search.spans.SpanOrQuery;
-import de.ids_mannheim.korap.query.wrap.SpanQueryWrapper;
-import de.ids_mannheim.korap.query.wrap.SpanRegexQueryWrapper;
-import de.ids_mannheim.korap.query.wrap.SpanWildcardQueryWrapper;
-import de.ids_mannheim.korap.query.SpanSegmentQuery;
+import org.apache.lucene.search.spans.SpanQuery;
 
+import de.ids_mannheim.korap.query.SpanSegmentQuery;
 import de.ids_mannheim.korap.util.QueryException;
 
 
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 b457d77..a8673fc 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
@@ -99,20 +99,6 @@
 
     /**
      * Constructs a new object for sequence deserialization
-     * by passing a single {@link SpanQuery} object.
-     * 
-     * @param query
-     *            Initial {@link SpanQuery} to search for.
-     */
-    public SpanSequenceQueryWrapper (SpanQuery query) {
-        this(query.getField());
-        this.segments.add(new SpanSimpleQueryWrapper(query));
-        this.isNull = false;
-    };
-
-
-    /**
-     * Constructs a new object for sequence deserialization
      * by passing a single {@link SpanQueryWrapper} object.
      * These wrapper queries may be optional, negative, or empty.
      * 
@@ -126,8 +112,7 @@
         if (sswq.isNull())
             return;
 
-        if (sswq.maybeUnsorted())
-            this.maybeUnsorted = true;
+        this.maybeUnsorted = sswq.maybeUnsorted();
 
         // Some debugging on initiating new sequences
         if (DEBUG) {
@@ -168,20 +153,9 @@
      *         chaining.
      */
     public SpanSequenceQueryWrapper append (String term) {
-        return this.append(new SpanTermQuery(new Term(field, term)));
-    };
-
-
-    /**
-     * 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(field, term)
+            );
     };
 
 
@@ -258,20 +232,9 @@
      *         chaining.
      */
     public SpanSequenceQueryWrapper prepend (String term) {
-        return this.prepend(new SpanTermQuery(new Term(field, term)));
-    };
-
-
-    /**
-     * 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(field, term)
+            );
     };
 
 
@@ -580,6 +543,8 @@
      */
     public void setInOrder (boolean order) {
         this.isInOrder = order;
+        if (order == false)
+            this.maybeUnsorted = true;
     };
 
 
diff --git a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanSubspanQueryWrapper.java b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanSubspanQueryWrapper.java
index 7e91844..eb370e3 100644
--- a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanSubspanQueryWrapper.java
+++ b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanSubspanQueryWrapper.java
@@ -48,6 +48,7 @@
         else if (subquery.isNegative()) {
             handleNegativeSubquery();
         }
+        this.maybeUnsorted = sqw.maybeUnsorted();
     }
 
 
@@ -144,10 +145,4 @@
             return false;
         return this.subquery.isOptional();
     };
-
-
-    @Override
-    public boolean maybeUnsorted () {
-        return this.subquery.maybeUnsorted();
-    };
 }
diff --git a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanWildcardQueryWrapper.java b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanWildcardQueryWrapper.java
index 5ac346e..faba7fc 100644
--- a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanWildcardQueryWrapper.java
+++ b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanWildcardQueryWrapper.java
@@ -1,12 +1,9 @@
 package de.ids_mannheim.korap.query.wrap;
 
-import org.apache.lucene.search.WildcardQuery;
-import org.apache.lucene.search.spans.SpanQuery;
-import org.apache.lucene.search.spans.SpanMultiTermQueryWrapper;
-import de.ids_mannheim.korap.query.wrap.SpanQueryWrapper;
 import org.apache.lucene.index.Term;
-
-import java.util.*;
+import org.apache.lucene.search.WildcardQuery;
+import org.apache.lucene.search.spans.SpanMultiTermQueryWrapper;
+import org.apache.lucene.search.spans.SpanQuery;
 
 public class SpanWildcardQueryWrapper extends SpanQueryWrapper {
     private SpanQuery query;
diff --git a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanWithAttributeQueryWrapper.java b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanWithAttributeQueryWrapper.java
index 266e051..efb476d 100644
--- a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanWithAttributeQueryWrapper.java
+++ b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanWithAttributeQueryWrapper.java
@@ -37,7 +37,9 @@
                     "The query requires a positive attribute.");
         }
         this.attrQueryWrapper = attrQuery;
+        this.maybeUnsorted = attrQuery.maybeUnsorted();
         this.isSingleAttribute = true;
+        
     }
 
 
diff --git a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanWithinQueryWrapper.java b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanWithinQueryWrapper.java
index ceb58f2..b601fac 100644
--- a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanWithinQueryWrapper.java
+++ b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanWithinQueryWrapper.java
@@ -1,17 +1,10 @@
 package de.ids_mannheim.korap.query.wrap;
 
-import de.ids_mannheim.korap.query.SpanWithinQuery;
-import de.ids_mannheim.korap.query.wrap.SpanSegmentQueryWrapper;
-import de.ids_mannheim.korap.query.wrap.SpanRegexQueryWrapper;
-import de.ids_mannheim.korap.query.wrap.SpanSequenceQueryWrapper;
-import de.ids_mannheim.korap.query.wrap.SpanQueryWrapper;
-
-import de.ids_mannheim.korap.util.QueryException;
-
-import java.util.*;
-
 import org.apache.lucene.search.spans.SpanQuery;
 
+import de.ids_mannheim.korap.query.SpanWithinQuery;
+import de.ids_mannheim.korap.util.QueryException;
+
 /*
   Todo:
 
@@ -121,7 +114,15 @@
         if (this.element.maybeUnsorted())
             return true;
 
-        return this.maybeUnsorted;
+        if (this.flag == SpanWithinQuery.MATCH ||
+            this.flag == SpanWithinQuery.STARTSWITH) {
+            return false;
+        };
+
+        // TODO:
+        //   Optimize by checking for containing classes!
+
+        return true;
     };
 
 
diff --git a/src/test/java/de/ids_mannheim/korap/index/TestFocusIndex.java b/src/test/java/de/ids_mannheim/korap/index/TestFocusIndex.java
index e79ae03..d337a8c 100644
--- a/src/test/java/de/ids_mannheim/korap/index/TestFocusIndex.java
+++ b/src/test/java/de/ids_mannheim/korap/index/TestFocusIndex.java
@@ -12,13 +12,16 @@
 
 import de.ids_mannheim.korap.KrillIndex;
 import de.ids_mannheim.korap.constants.RelationDirection;
+import de.ids_mannheim.korap.query.QueryBuilder;
 import de.ids_mannheim.korap.query.SpanClassQuery;
 import de.ids_mannheim.korap.query.SpanElementQuery;
 import de.ids_mannheim.korap.query.SpanFocusQuery;
 import de.ids_mannheim.korap.query.SpanNextQuery;
 import de.ids_mannheim.korap.query.SpanRelationQuery;
 import de.ids_mannheim.korap.query.SpanWithinQuery;
+import de.ids_mannheim.korap.query.wrap.SpanQueryWrapper;
 import de.ids_mannheim.korap.response.Result;
+import de.ids_mannheim.korap.util.QueryException;
 
 public class TestFocusIndex {
     private KrillIndex ki;
@@ -98,6 +101,7 @@
         SpanFocusQuery focus = new SpanFocusQuery(within, (byte) 1);
         focus.setSorted(false);
         kr = ki.search(focus, (short) 10);
+        assertEquals("focus(1: spanContain(<tokens:x />, spanOr([{1: tokens:s:b}, {1: tokens:s:c}])),sorting)", focus.toString());
         assertEquals("a[[{1:b}]]cd", kr.getMatch(0).getSnippetBrackets());
         assertEquals("a[[{1:b}]]cd", kr.getMatch(1).getSnippetBrackets());
         assertEquals("ab[[{1:c}]]d", kr.getMatch(2).getSnippetBrackets());
@@ -139,6 +143,35 @@
 
     }
 
+    @Test
+    public void testFocusSortingWrapping () throws QueryException, IOException {
+        ki = new KrillIndex();
+        ki.addDoc(createFieldDoc());
+        ki.commit();
+
+        QueryBuilder kq = new QueryBuilder("tokens");
+
+        SpanQueryWrapper focus = kq.focus(kq.within(kq.tag("x"), kq.or(kq.nr(1, kq.seg("s:b")), kq.nr(1, kq.seg("s:c")))));
+        assertEquals("focus(1: spanContain(<tokens:x />, spanOr([{1: tokens:s:b}, {1: tokens:s:c}])),sorting)", focus.toQuery().toString());
+        
+        kr = ki.search(focus.toQuery(), (short) 10);
+        assertEquals("a[[{1:b}]]cd", kr.getMatch(0).getSnippetBrackets());
+        assertEquals("a[[{1:b}]]cd", kr.getMatch(1).getSnippetBrackets());
+        assertEquals("ab[[{1:c}]]d", kr.getMatch(2).getSnippetBrackets());
+        assertEquals("ab[[{1:c}]]d", kr.getMatch(3).getSnippetBrackets());
+        assertEquals(4, kr.getTotalResults());
+
+
+        focus = kq.focus(kq.startswith(kq.tag("x"), kq.or(kq.nr(1, kq.seg("s:b")), kq.nr(1, kq.seg("s:c")))));
+        assertEquals("focus(1: spanStartsWith(<tokens:x />, spanOr([{1: tokens:s:b}, {1: tokens:s:c}])))",
+                     focus.toQuery().toString());
+
+        kr = ki.search(focus.toQuery(), (short) 10);
+        assertEquals("a[[{1:b}]]cd", kr.getMatch(0).getSnippetBrackets());
+        assertEquals(1, kr.getTotalResults());
+    }
+
+    
     public static FieldDocument createFieldDoc () {
         FieldDocument fd = new FieldDocument();
         fd.addString("ID", "doc-0");
diff --git a/src/test/java/de/ids_mannheim/korap/index/TestReferenceIndex.java b/src/test/java/de/ids_mannheim/korap/index/TestReferenceIndex.java
index 4e01093..3c603fa 100644
--- a/src/test/java/de/ids_mannheim/korap/index/TestReferenceIndex.java
+++ b/src/test/java/de/ids_mannheim/korap/index/TestReferenceIndex.java
@@ -1,6 +1,6 @@
 package de.ids_mannheim.korap.index;
 
-import static de.ids_mannheim.korap.TestSimple.*;
+import static de.ids_mannheim.korap.TestSimple.getJsonQuery;
 import static org.junit.Assert.assertEquals;
 
 import java.io.IOException;
@@ -77,7 +77,7 @@
         assertEquals(
                 "spanReference(spanDistance(focus(1: focus(#[1,2]spanSegment("
                         + "focus(#1: spanSegment(spanRelation(base:<:child-of), focus(2: spanNext("
-                        + "{1: base:pos:V}, {2: <base:np />})))), {3: <base:pp />}))), "
+                        + "{1: base:pos:V}, {2: <base:np />})))), {3: <base:pp />}),sorting)), "
                         + "{3: <base:pp />}, [(w[3:3], ordered, notExcluded)]), 3)",
                 ref.toString());
 
@@ -87,6 +87,7 @@
 
 
     @Test
+//    @Ignore
     public void testCase2 () throws IOException, QueryException {
 
         String filepath = getClass()
@@ -102,9 +103,9 @@
                 "spanReference(focus(#[1,2]spanSegment({2: <tokens:prp />}, focus(#2: "
                         + "spanSegment(spanRelation(tokens:>:stanford/d:tag), "
                         + "focus(3: spanDistance(focus(1: spanDistance({1: <tokens:vb />}, "
-                        + "{2: <tokens:prp />}, [(w[1:2], notOrdered, notExcluded)])), "
-                        + "{3: <tokens:nn />}, [(w[1:3], notOrdered, notExcluded)]))))"
-                        + ")), 2)",
+                        + "{2: <tokens:prp />}, [(w[1:2], notOrdered, notExcluded)]),sorting), "
+                        + "{3: <tokens:nn />}, [(w[1:3], notOrdered, notExcluded)]),sorting)),sorting)"
+                        + "),sorting), 2)",
                 sq.toString());
 
         SpanElementQuery seq1 = new SpanElementQuery("tokens", "vb");
@@ -120,10 +121,12 @@
         SpanDistanceQuery sdq1 = new SpanDistanceQuery(scq1, scq2,
                 new DistanceConstraint(1, 2, false, false), true);
         SpanFocusQuery sfq1 = new SpanFocusQuery(sdq1, (byte) 1);
+        sfq1.setSorted(false);
 
         SpanDistanceQuery sdq2 = new SpanDistanceQuery(sfq1, scq3,
                 new DistanceConstraint(1, 3, false, false), true);
         SpanFocusQuery sfq2 = new SpanFocusQuery(sdq2, (byte) 3);
+        sfq2.setSorted(false);
 
         // nn -> prp
         SpanRelationQuery srq = new SpanRelationQuery(
@@ -199,8 +202,8 @@
                         + "focus(1: spanReference(focus(#[1,2]spanSegment({2: <tokens:prp />}, "
                         + "focus(#2: spanSegment(spanRelation(tokens:>:stanford/d:tag), "
                         + "focus(3: spanDistance(focus(1: spanDistance({1: <tokens:vb />}, "
-                        + "{2: <tokens:prp />}, [(w[1:2], notOrdered, notExcluded)])), "
-                        + "{3: <tokens:nn />}, [(w[1:3], notOrdered, notExcluded)])))))), 2)))))), 3)",
+                        + "{2: <tokens:prp />}, [(w[1:2], notOrdered, notExcluded)]),sorting), "
+                        + "{3: <tokens:nn />}, [(w[1:3], notOrdered, notExcluded)]),sorting)),sorting)),sorting), 2),sorting)),sorting)),sorting), 3)",
                 sq.toString());
         kr = ki.search(sq, (short) 10);
         // for (Match km : kr.getMatches()) {
@@ -231,8 +234,17 @@
 
         kr = ki.search(sq, (short) 10);
 
+        /*
+          for (Match km : kr.getMatches()) {
+            System.out.println(km.getDocID() + ":" + km.getStartPos() + "," + km.getEndPos()
+                               + " "
+                               + km.getSnippetBrackets());
+        }
+        */
+
         assertEquals(4, kr.getTotalResults());
         assertEquals("doc-1", kr.getMatch(3).getDocID());
+        
         assertEquals(2, kr.getMatch(3).getStartPos());
         assertEquals(4, kr.getMatch(3).getEndPos());
     }
diff --git a/src/test/java/de/ids_mannheim/korap/index/TestRelationIndex.java b/src/test/java/de/ids_mannheim/korap/index/TestRelationIndex.java
index adf97ac..8f50f41 100644
--- a/src/test/java/de/ids_mannheim/korap/index/TestRelationIndex.java
+++ b/src/test/java/de/ids_mannheim/korap/index/TestRelationIndex.java
@@ -22,7 +22,6 @@
 import de.ids_mannheim.korap.query.SpanSegmentQuery;
 import de.ids_mannheim.korap.query.SpanTermWithIdQuery;
 import de.ids_mannheim.korap.query.SpanWithAttributeQuery;
-import de.ids_mannheim.korap.response.Match;
 import de.ids_mannheim.korap.response.Result;
 
 /*
@@ -462,7 +461,7 @@
         rv.setSorted(false);
 
         assertEquals(
-                "focus(1: focus(#[1,2]spanSegment(spanRelation(base:>:child-of), {1: <base:np />})))",
+                "focus(1: focus(#[1,2]spanSegment(spanRelation(base:>:child-of), {1: <base:np />}),sorting),sorting)",
                 rv.toString());
 
         kr = ki.search(rv, (short) 10);
@@ -569,7 +568,7 @@
         rv2.setSorted(false);
 
         assertEquals(
-                "focus(2: focus(#[1,2]spanSegment({2: target:spanRelation(base:>:child-of)}, {1: <base:np />})))",
+                "focus(2: focus(#[1,2]spanSegment({2: target:spanRelation(base:>:child-of)}, {1: <base:np />}),sorting),sorting)",
                 rv2.toString());
 
         kr = ki.search(rv2, (short) 10);
@@ -664,7 +663,7 @@
         rv.setSorted(false);
 
         assertEquals(
-                "focus(2: focus(#[1,2]spanSegment({2: source:spanRelation(base:<:child-of)}, {1: <base:np />})))",
+                "focus(2: focus(#[1,2]spanSegment({2: source:spanRelation(base:<:child-of)}, {1: <base:np />}),sorting),sorting)",
                 rv.toString());
 
         kr = ki.search(rv, (short) 10);
@@ -801,8 +800,8 @@
         sfq2.setSorted(false);
         assertEquals("focus(1: spanSegment(focus(2: spanSegment({1: source:"
                 + "{2: target:spanRelation(base:>:child-of)}}, "
-                + "{1: spanTermWithId(base:pos:ART)})), "
-                + "{2: <base:np />}))", sfq2.toString());
+                + "{1: spanTermWithId(base:pos:ART)}),sorting), "
+                + "{2: <base:np />}),sorting)", sfq2.toString());
 
         kr = ki.search(sfq2, (short) 10);
 
@@ -1009,7 +1008,7 @@
         assertEquals(
                 "focus(#[1,2]spanSegment(spanWithAttribute(spanAttribute(base:@:case=accusative)), "
                         + "focus(#2: spanSegment({1: source:{2: target:spanRelation(base:>:child-of)}}, "
-                        + "spanWithAttribute(spanAttribute(base:@:case=accusative))))))",
+                        + "spanWithAttribute(spanAttribute(base:@:case=accusative))),sorting)),sorting)",
                 srmq.toString());
         kr = ki.search(srmq, (short) 10);
         assertEquals((long) 1, kr.getTotalResults());
diff --git a/src/test/java/de/ids_mannheim/korap/query/TestKrillQuery.java b/src/test/java/de/ids_mannheim/korap/query/TestKrillQuery.java
index af6b568..97cf3f8 100644
--- a/src/test/java/de/ids_mannheim/korap/query/TestKrillQuery.java
+++ b/src/test/java/de/ids_mannheim/korap/query/TestKrillQuery.java
@@ -4,6 +4,7 @@
 import org.apache.lucene.search.spans.SpanQuery;
 import de.ids_mannheim.korap.KrillQuery;
 import de.ids_mannheim.korap.query.QueryBuilder;
+import de.ids_mannheim.korap.query.wrap.SpanQueryWrapper;
 
 import de.ids_mannheim.korap.util.QueryException;
 
@@ -344,6 +345,56 @@
         assertEquals("spanStartsWith(field:test, field:test2)", sq.toString());
     };
 
-    // kq.seg("a").append(kq.ANY).append("b:c");
-    // kq.repeat(kq.seg("a", "b"), 5)
+
+    @Test
+    public void korapMaybeUnsorted () throws QueryException {
+        QueryBuilder kq = new QueryBuilder("field");
+        SpanQueryWrapper sqw = kq.re("a.*");
+        assertFalse(sqw.maybeUnsorted());
+
+        sqw = kq.wc("a?b");
+        assertFalse(sqw.maybeUnsorted());
+
+        sqw = kq.seg("a", "b").with("c");
+        assertFalse(sqw.maybeUnsorted());
+
+        sqw = kq.seg("a", "b").with("c");
+        assertFalse(sqw.maybeUnsorted());
+
+        sqw = kq.seq().append("c").prepend("b");
+        assertFalse(sqw.maybeUnsorted());
+
+        sqw = kq.tag("abc");
+        assertFalse(sqw.maybeUnsorted());
+
+        sqw = kq.within(kq.tag("abc"), kq.seg("a"));
+        assertTrue(sqw.maybeUnsorted());
+
+        sqw = kq.contains(kq.tag("abc"), kq.seg("a"));
+        assertTrue(sqw.maybeUnsorted());
+
+        sqw = kq.startswith(kq.tag("abc"), kq.seg("a"));
+        assertFalse(sqw.maybeUnsorted());
+
+        sqw = kq.endswith(kq.tag("abc"), kq.seg("a"));
+        assertTrue(sqw.maybeUnsorted());
+
+        sqw = kq.overlaps(kq.tag("abc"), kq.seg("a"));
+        assertTrue(sqw.maybeUnsorted());
+
+        sqw = kq.matches(kq.tag("abc"), kq.seg("a"));
+        assertFalse(sqw.maybeUnsorted());
+
+        sqw = kq.matches(kq.within(kq.tag("abc"), kq.seg("a")), kq.seg("a"));
+        assertTrue(sqw.maybeUnsorted());
+        
+        sqw = kq.nr(2, kq.tag("abc"));
+        assertFalse(sqw.maybeUnsorted());
+
+        sqw = kq.repeat(kq.tag("abc"), 4);
+        assertFalse(sqw.maybeUnsorted());
+
+        sqw = kq.repeat(kq.within(kq.tag("abc"), kq.seg("a")), 4);
+        assertTrue(sqw.maybeUnsorted());
+    };
 };
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 f867b5c..6c5adda 100644
--- a/src/test/java/de/ids_mannheim/korap/query/TestKrillQueryJSON.java
+++ b/src/test/java/de/ids_mannheim/korap/query/TestKrillQueryJSON.java
@@ -353,7 +353,7 @@
 
         //     "MORPH(V) #IN(R) #ELEM(S)"
         assertEquals(sqwi.toQuery().toString(),
-                "focus(1: spanEndsWith(<tokens:s />, {1: tokens:p:V}))");
+                "focus(1: spanEndsWith(<tokens:s />, {1: tokens:p:V}),sorting)");
     };
 
 
@@ -386,7 +386,7 @@
 
         // Namen /s1 Leben
         assertEquals(sqwi.toQuery().toString(),
-                "focus(129: spanElementDistance({129: tokens:s:Namen}, {129: tokens:s:Leben}, [(base/s:s[0:1], notOrdered, notExcluded)]))");
+                "focus(129: spanElementDistance({129: tokens:s:Namen}, {129: tokens:s:Leben}, [(base/s:s[0:1], notOrdered, notExcluded)]),sorting)");
     };
 
 
diff --git a/src/test/java/de/ids_mannheim/korap/query/TestSpanReferenceQueryJSON.java b/src/test/java/de/ids_mannheim/korap/query/TestSpanReferenceQueryJSON.java
index 1192296..83bfb60 100644
--- a/src/test/java/de/ids_mannheim/korap/query/TestSpanReferenceQueryJSON.java
+++ b/src/test/java/de/ids_mannheim/korap/query/TestSpanReferenceQueryJSON.java
@@ -30,7 +30,7 @@
                 "spanReference(spanNext({3: tokens:p:P}, "
                         + "focus(2: focus(#[1,2]spanSegment({3: tokens:p:P}, "
                         + "focus(#2: spanSegment(spanRelation(tokens:>:mate/d:HEAD), "
-                        + "focus(1: spanNext({2: tokens:p:V}, {1: <tokens:c:NP />})))))))), 3)",
+                        + "focus(1: spanNext({2: tokens:p:V}, {1: <tokens:c:NP />}))),sorting)),sorting),sorting)), 3)",
                 sq.toString());
     }
 
@@ -50,7 +50,7 @@
         assertEquals(
                 "spanReference(spanNext(focus(2: focus(#[1,2]spanSegment({3: tokens:p:P}, "
                         + "focus(#2: spanSegment(spanRelation(tokens:>:mate/d:HEAD), "
-                        + "focus(1: spanNext({2: tokens:p:V}, {1: <tokens:c:NP />}))))))), "
+                        + "focus(1: spanNext({2: tokens:p:V}, {1: <tokens:c:NP />}))),sorting)),sorting),sorting), "
                         + "{3: tokens:p:P}), 3)",
                 sq.toString());
     }
@@ -70,7 +70,7 @@
                 "spanReference(focus(#[1,2]spanSegment({1: <tokens:c:VP />}, "
                         + "focus(#2: spanSegment(spanRelation(tokens:>:mate/d:HEAD), "
                         + "focus(2: spanReference(spanNext(focus(1: spanNext(focus(2: spanNext({1: <tokens:c:VP />}, "
-                        + "{2: <tokens:c:NP />})), {3: <tokens:c:PP />})), {3: <tokens:c:PP />}), 3)))))), 1)",
+                        + "{2: <tokens:c:NP />})), {3: <tokens:c:PP />})), {3: <tokens:c:PP />}), 3))),sorting)),sorting), 1)",
                 sq.toString());
     }
 
@@ -104,8 +104,8 @@
                 "spanReference(focus(#[1,2]spanSegment({1: <tokens:c:prp />}, "
                         + "focus(#2: spanSegment(spanRelation(tokens:>:stanford/d:tag), "
                         + "focus(2: spanDistance(focus(1: spanDistance(<tokens:c:vb />, "
-                        + "{1: <tokens:c:prp />}, [(w[1:1], notOrdered, notExcluded)])), "
-                        + "{2: <tokens:c:nn />}, [(w[1:3], ordered, notExcluded)])))))), 1)",
+                        + "{1: <tokens:c:prp />}, [(w[1:1], notOrdered, notExcluded)]),sorting), "
+                        + "{2: <tokens:c:nn />}, [(w[1:3], ordered, notExcluded)]))),sorting)),sorting), 1)",
                 sq.toString());
     }
 }
diff --git a/src/test/java/de/ids_mannheim/korap/query/TestSpanRelationQueryJSON.java b/src/test/java/de/ids_mannheim/korap/query/TestSpanRelationQueryJSON.java
index 16f7b33..3a55968 100644
--- a/src/test/java/de/ids_mannheim/korap/query/TestSpanRelationQueryJSON.java
+++ b/src/test/java/de/ids_mannheim/korap/query/TestSpanRelationQueryJSON.java
@@ -29,7 +29,7 @@
         assertEquals(
                 "focus(#[1,2]spanSegment(<tokens:c:vp />, "
                         + "focus(#2: spanSegment(spanRelation(tokens:>:mate/d:HEAD), "
-                        + "spanWithAttribute(spanAttribute(tokens:type:case:accusative))))))",
+                        + "spanWithAttribute(spanAttribute(tokens:type:case:accusative))),sorting)),sorting)",
                 sq.toString());
     }
 
@@ -49,7 +49,7 @@
                 //
                 "focus(#[1,2]spanSegment(spanWithAttribute(spanAttribute(tokens:type:case:accusative)), "
                         + "focus(#2: spanSegment(spanRelation(tokens:>:mate/d:HEAD), "
-                        + "<tokens:c:vp />))))",
+                        + "<tokens:c:vp />),sorting)),sorting)",
                 sq.toString());
 
         // System.out.println(sq.toString());
@@ -70,7 +70,7 @@
                 "focus(#[1,2]spanSegment(<tokens:c:vp />, "
                         + "focus(#2: spanSegment(spanRelation(tokens:>:mate/d:HEAD), "
                         + "spanElementWithAttribute(<tokens:c:np />, "
-                        + "spanAttribute(tokens:type:case:accusative))))))",
+                        + "spanAttribute(tokens:type:case:accusative))),sorting)),sorting)",
                 sq.toString());
     }
 
@@ -89,7 +89,7 @@
                         + "spanAttribute(tokens:type:case:accusative)), "
                         + "focus(#2: spanSegment(spanRelation(tokens:>:mate/d:HEAD), "
                         + "spanElementWithAttribute(<tokens:c: />, "
-                        + "spanAttribute(tokens:type:case:accusative))))))",
+                        + "spanAttribute(tokens:type:case:accusative))),sorting)),sorting)",
                 sq.toString());
     }
 
@@ -102,7 +102,7 @@
         SpanQueryWrapper sqwi = getJsonQuery(filepath);
         SpanQuery sq = sqwi.toQuery();
         assertEquals(
-                "focus(#[1,2]spanSegment(spanRelation(tokens:>:mate/d:HEAD), <tokens:c:s />))",
+                "focus(#[1,2]spanSegment(spanRelation(tokens:>:mate/d:HEAD), <tokens:c:s />),sorting)",
                 sq.toString());
     }
 
@@ -115,7 +115,7 @@
         SpanQueryWrapper sqwi = getJsonQuery(filepath);
         SpanQuery sq = sqwi.toQuery();
         assertEquals(
-                "focus(#[1,2]spanSegment(spanRelation(tokens:>:malt/d:KONJ), tokens:tt/l:um))",
+                "focus(#[1,2]spanSegment(spanRelation(tokens:>:malt/d:KONJ), tokens:tt/l:um),sorting)",
                 sq.toString());
     }
 
@@ -128,7 +128,7 @@
         SpanQueryWrapper sqwi = getJsonQuery(filepath);
         SpanQuery sq = sqwi.toQuery();
         assertEquals(
-                "focus(#[1,2]spanSegment(spanRelation(tokens:<:mate/d:HEAD), <tokens:c:vp />))",
+                "focus(#[1,2]spanSegment(spanRelation(tokens:<:mate/d:HEAD), <tokens:c:vp />),sorting)",
                 sq.toString());
     }
 
@@ -143,7 +143,7 @@
         SpanQuery sq = sqwi.toQuery();
         assertEquals(
                 "focus(#[1,2]spanSegment(<tokens:c:vp />, "
-                        + "focus(#2: spanSegment(spanRelation(tokens:>:mate/d:HEAD), <tokens:c:s />))))",
+                        + "focus(#2: spanSegment(spanRelation(tokens:>:mate/d:HEAD), <tokens:c:s />),sorting)),sorting)",
                 sq.toString());
     }
 
@@ -158,7 +158,7 @@
         SpanQuery sq = sqwi.toQuery();
         assertEquals(
                 "focus(#[1,2]spanSegment(<tokens:c:vp />, focus(#2: spanSegment(spanRelation(tokens:>:mate/d:HEAD), "
-                        + "spanElementWithAttribute(<tokens:c:s />, spanAttribute(tokens:@root))))))",
+                        + "spanElementWithAttribute(<tokens:c:s />, spanAttribute(tokens:@root))),sorting)),sorting)",
                 sq.toString());
     }
 
@@ -173,7 +173,7 @@
         SpanQuery sq = sqwi.toQuery();
         assertEquals(
                 "focus(#[1,2]spanSegment(<tokens:c:vp />, focus(#2: spanSegment(spanRelation(tokens:>:mate/d:HEAD), "
-                        + "spanElementWithAttribute(<tokens:c:s />, spanAttribute(tokens:type:top))))))",
+                        + "spanElementWithAttribute(<tokens:c:s />, spanAttribute(tokens:type:top))),sorting)),sorting)",
                 sq.toString());
     }
 
@@ -185,7 +185,7 @@
                 .getResource("/queries/relation/relation-only.json").getFile();
         SpanQueryWrapper sqwi = getJsonQuery(filepath);
         SpanQuery sq = sqwi.toQuery();
-        assertEquals("focus(#[1,2]spanRelation(tokens:>:mate/d:HEAD))",
+        assertEquals("focus(#[1,2]spanRelation(tokens:>:mate/d:HEAD),sorting)",
                 sq.toString());
     }
 
@@ -198,7 +198,7 @@
         SpanQueryWrapper sqwi = getJsonQuery(filepath);
         SpanQuery sq = sqwi.toQuery();
         assertEquals(
-                "focus(1: focus(#[1,2]spanSegment(spanRelation(tokens:<:mate/d:HEAD), {1: <tokens:c:np />})))",
+                "focus(1: focus(#[1,2]spanSegment(spanRelation(tokens:<:mate/d:HEAD), {1: <tokens:c:np />}),sorting),sorting)",
                 sq.toString());
     }
 
@@ -211,7 +211,7 @@
         SpanQuery sq = sqwi.toQuery();
         assertEquals(
                 "focus(2: focus(#[1,2]spanSegment({2: <tokens:c:np />}, "
-                        + "focus(#2: spanSegment(spanRelation(tokens:>:mate/d:HEAD), {1: <tokens:c:s />})))))",
+                        + "focus(#2: spanSegment(spanRelation(tokens:>:mate/d:HEAD), {1: <tokens:c:s />}),sorting)),sorting),sorting)",
                 sq.toString());
     }
 
@@ -224,7 +224,7 @@
         SpanQueryWrapper sqwi = getJsonQuery(filepath);
         SpanQuery sq = sqwi.toQuery();
         assertEquals(
-                "focus(2: focus(#[1,2]spanSegment({2: target:spanRelation(tokens:>:mate/d:HEAD)}, {1: <tokens:c:s />})))",
+                "focus(2: focus(#[1,2]spanSegment({2: target:spanRelation(tokens:>:mate/d:HEAD)}, {1: <tokens:c:s />}),sorting),sorting)",
                 sq.toString());
     }
 
@@ -237,7 +237,7 @@
         SpanQueryWrapper sqwi = getJsonQuery(filepath);
         SpanQuery sq = sqwi.toQuery();
         assertEquals(
-                "focus(2: focus(#[1,2]{1: source:{2: target:spanRelation(tokens:>:mate/d:HEAD)}}))",
+                "focus(2: focus(#[1,2]{1: source:{2: target:spanRelation(tokens:>:mate/d:HEAD)}},sorting),sorting)",
                 sq.toString());
     }
 
@@ -251,7 +251,7 @@
         SpanQuery sq = sqwi.toQuery();
         assertEquals("focus(#[1,2]spanSegment(<tokens:corenlp/c:NP />, "
                 + "focus(#2: spanSegment(spanRelation(SpanMultiTermQueryWrapper(tokens:/>:malt/d:.*/)), "
-                + "<tokens:corenlp/c:VP />))))", sq.toString());
+                + "<tokens:corenlp/c:VP />),sorting)),sorting)", sq.toString());
     }
 
     // EM: should relation term allow empty key?
@@ -278,7 +278,7 @@
         SpanQueryWrapper sqwi = getJsonQuery(filepath);
         SpanQuery sq = sqwi.toQuery();
 
-        assertEquals("focus(#[1,2]spanRelation(tokens:>:malt/d:PP))",
+        assertEquals("focus(#[1,2]spanRelation(tokens:>:malt/d:PP),sorting)",
                 sq.toString());
     }
 
@@ -295,7 +295,7 @@
         assertEquals(
                 "focus(#[1,2]spanSegment(<tokens:corenlp/c:NP />, "
                         + "focus(#2: spanSegment("
-                        + "spanRelation(tokens:>:malt/d:PP), <tokens:corenlp/c:VP />))))",
+                        + "spanRelation(tokens:>:malt/d:PP), <tokens:corenlp/c:VP />),sorting)),sorting)",
                 sq.toString());
 
     }
@@ -312,7 +312,7 @@
         assertEquals(
                 "focus(#[1,2]spanSegment(tokens:tt/p:VVINF, "
                         + "focus(#2: spanSegment("
-                        + "spanRelation(tokens:>:malt/d:KONJ), tokens:tt/p:KOUI))))",
+                        + "spanRelation(tokens:>:malt/d:KONJ), tokens:tt/p:KOUI),sorting)),sorting)",
                 sq.toString());
 
     }
diff --git a/src/test/java/de/ids_mannheim/korap/query/TestTemporaryQueryLimitations.java b/src/test/java/de/ids_mannheim/korap/query/TestTemporaryQueryLimitations.java
index 20cd49f..98dffee 100644
--- a/src/test/java/de/ids_mannheim/korap/query/TestTemporaryQueryLimitations.java
+++ b/src/test/java/de/ids_mannheim/korap/query/TestTemporaryQueryLimitations.java
@@ -56,7 +56,7 @@
         Krill ks = new Krill(json);
         Result kr = ks.apply(ki);
         assertEquals(kr.getSerialQuery(),
-                "focus(130: {131: spanContain({129: <tokens:s />}, {130: tokens:s:wegen})})");
+                "focus(130: {131: spanContain({129: <tokens:s />}, {130: tokens:s:wegen})},sorting)");
         assertEquals(kr.getTotalResults(), 0);
         assertEquals(kr.getStartIndex(), 0);
 
diff --git a/src/test/java/de/ids_mannheim/korap/search/TestKrill.java b/src/test/java/de/ids_mannheim/korap/search/TestKrill.java
index 7094199..bc12a15 100644
--- a/src/test/java/de/ids_mannheim/korap/search/TestKrill.java
+++ b/src/test/java/de/ids_mannheim/korap/search/TestKrill.java
@@ -744,7 +744,7 @@
 
         Result kr = ks.apply(ki);
         assertEquals(kr.getSerialQuery(),
-                "focus(1: spanContain(<tokens:base/s:s />, {1: tokens:s:Leben}))");
+                "focus(1: spanContain(<tokens:base/s:s />, {1: tokens:s:Leben}),sorting)");
         assertEquals(40, kr.getMatch(0).getStartPos());
         assertEquals(41, kr.getMatch(0).getEndPos());
 
@@ -758,7 +758,7 @@
 
         kr = ks.apply(ki);
         assertEquals(kr.getSerialQuery(),
-                "focus(129: spanContain(<tokens:base/s:s />, {129: tokens:s:Leben}))");
+                "focus(129: spanContain(<tokens:base/s:s />, {129: tokens:s:Leben}),sorting)");
         assertEquals(kr.getMatch(0).getSnippetBrackets(),
                 "... Initiative\" eine neue politische Gruppierung ins "
                         + "[[Leben]] gerufen hatten. Pressemeldungen zufolge haben sich ...");
@@ -767,7 +767,7 @@
         kr = ks.apply(ki);
         assertEquals(kr.getSerialQuery(),
                 "focus(129: spanElementDistance({129: tokens:s:Namen}, "
-                        + "{129: tokens:s:Leben}, [(base/s:s[0:1], notOrdered, notExcluded)]))");
+                        + "{129: tokens:s:Leben}, [(base/s:s[0:1], notOrdered, notExcluded)]),sorting)");
         assertEquals(kr.getMatch(0).getSnippetBrackets(),
                 "... ihren Austritt erklärt und unter dem [[Namen \"Einheitsbewegung "
                         + "der sozialistischen Initiative\" eine neue politische Gruppierung "