Extract Querybuilder methods from KrillQuery
diff --git a/Changes b/Changes
index 2da2650..b679679 100644
--- a/Changes
+++ b/Changes
@@ -1,6 +1,8 @@
-0.50.1 2015-02-25
+0.50.1 2015-02-26
 	- [feature] Deserialization of arbitrary elements with attributes (margaretha)
-	- [cleanup] Extract KrillMeta from Krill (diewald)
+	- [cleanup] Extract KrillMeta from Krill,
+	  rename KorapQuery to KrillQuery,
+	  extract QueryBuilder from KrillQuery (diewald)
 
 0.50 2015-02-23
         - Project name is now "Krill"
diff --git a/src/main/java/de/ids_mannheim/korap/KrillQuery.java b/src/main/java/de/ids_mannheim/korap/KrillQuery.java
index 08edf38..01385c7 100644
--- a/src/main/java/de/ids_mannheim/korap/KrillQuery.java
+++ b/src/main/java/de/ids_mannheim/korap/KrillQuery.java
@@ -4,39 +4,26 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import org.apache.lucene.util.automaton.RegExp;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import org.apache.lucene.util.automaton.RegExp;
+
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
 
 import de.ids_mannheim.korap.query.SpanWithinQuery;
+import de.ids_mannheim.korap.query.QueryBuilder;
 import de.ids_mannheim.korap.query.wrap.*;
 import de.ids_mannheim.korap.response.Notifications;
 import de.ids_mannheim.korap.util.QueryException;
 
 /**
- * KrillQuery implements a simple API for wrapping
- * KorAP Lucene Index specific query classes and provides
- * deserialization of JSON-LD queries.
+ * KrillQuery provides deserialization methods
+ * for KoralQuery query objects.
  *
- * Build complex queries.
  * <blockquote><pre>
- *   KrillQuery kq = new KrillQuery("tokens");
- *   SpanQueryWrapper sqw = (SpanQueryWrapper)
- *     kq.seq(
- *       kq.empty(),
- *       kq.seg(
- *         kq.re("mate/p=N.*"),
- *         kq.re("opennlp/p=N.*")
- *       )
- *     );
- * </pre></blockquote>
- *
- * Deserialize from JSON input.
- * <blockquote><pre>
- *   SpanQueryWrapper = new KrillQuery("tokens").fromJson("{... JsonString ...}");
+ *   SpanQueryWrapper sqw = new KrillQuery("tokens").fromJson("{... JsonString ...}");
  * </pre></blockquote>
  *
  * @author diewald
@@ -58,7 +45,7 @@
 */
 public class KrillQuery extends Notifications {
     private String field;
-    private ObjectMapper mapper;
+    private QueryBuilder builder;
     private JsonNode json;
 
     // Logger
@@ -81,21 +68,15 @@
     private static final int MAX_CLASS_NUM = 255; // 127;
 
     /**
-     * Constructs a new object for query generation.
-     */
-    public KrillQuery () {
-        this.mapper = new ObjectMapper();
-    };
-
-
-    /**
-     * Constructs a new object for query generation.
+     * Constructs a new object for query deserialization
+     * and building. Expects the name of an index field
+     * to apply the query on (this should normally be
+     * a token stream field).
      *
      * @param field The specific index field for the query.
      */
     public KrillQuery (String field) {
         this.field = field;
-        this.mapper = new ObjectMapper();
     };
 
 
@@ -156,7 +137,7 @@
         JsonNode jsonN;
         try {
             // Read Json string
-            jsonN = this.mapper.readValue(json, JsonNode.class);
+            jsonN = new ObjectMapper().readValue(json, JsonNode.class);
         }
 
         // Something went wrong
@@ -292,6 +273,49 @@
     };
 
 
+    /**
+     * Get the associated {@link QueryBuilder} object
+     * for query building.
+     */
+    public QueryBuilder builder () {
+        if (this.builder == null)
+            this.builder = new QueryBuilder(this.field);
+        return this.builder;
+    };
+
+
+    /**
+     * Return the associated KoralQuery query object
+     * as a {@link JsonNode}. This won't work,
+     * if the object was build using a {@link QueryBuilder},
+     * therefore it is limited to mirror a deserialized KoralQuery
+     * object.
+     *
+     * @return The {@link JsonNode} representing the query object
+     *         of a deserialized KoralQuery object.
+     */
+    public JsonNode toJsonNode () {
+        return this.json;
+    };
+
+
+    /**
+     * Return the associated KoralQuery query object
+     * as a JSON string. This won't work,
+     * if the object was build using a {@link QueryBuilder},
+     * therefore it is limited to mirror a deserialized KoralQuery
+     * object.
+     *
+     * @return A JSON string representing the query object
+     *         of a deserialized KoralQuery object.
+     */
+    public String toJsonString () {
+        if (this.json == null)
+            return "{}";
+        return this.json.toString();
+    };
+
+
     // Deserialize koral:group
     private SpanQueryWrapper _groupFromJson (JsonNode json) throws QueryException {
 
@@ -628,7 +652,7 @@
         if (operands.size() == 1)
             return this.fromJson(operands.get(0));
 
-        SpanSequenceQueryWrapper sseqqw = this.seq();
+        SpanSequenceQueryWrapper sseqqw = this.builder().seq();
 
         // Say if the operand order is important
         if (json.has("inOrder"))
@@ -786,7 +810,7 @@
             // Get operands
             JsonNode operands = json.get("operands");
 
-            SpanSegmentQueryWrapper ssegqw = this.seg();
+            SpanSegmentQueryWrapper ssegqw = this.builder().seg();
             
             if (!json.has("relation"))
                 throw new QueryException(743, "Term group expects a relation");
@@ -915,13 +939,15 @@
         // Regular expression or wildcard
         if (isTerm && json.has("type")) {
 
+            QueryBuilder qb = this.builder();
+
             // Branch on type
             switch (json.get("type").asText()) {
             case "type:regex":
-                return this.seg(this.re(value.toString(), isCaseInsensitive));
+                return qb.seg(qb.re(value.toString(), isCaseInsensitive));
 
             case "type:wildcard":
-                return this.seq(this.wc(value.toString(), isCaseInsensitive));
+                return qb.seq(qb.wc(value.toString(), isCaseInsensitive));
 
             case "type:string":
                 break;
@@ -938,11 +964,11 @@
 				match = json.get("match").asText();
 			}
 
-			SpanSegmentQueryWrapper ssqw = seg(value.toString());			
+			SpanSegmentQueryWrapper ssqw = this.builder().seg(value.toString());			
 			if (match.equals("match:ne")) {
 				if (DEBUG) log.trace("Term is negated");
 				ssqw.makeNegative();
-				return this.seg().without(ssqw);
+				return this.builder().seg().without(ssqw);
 			} 
 			else if (match.equals("match:eq")) {
 				return ssqw;
@@ -960,30 +986,33 @@
 			}
 
 			if (value.toString().isEmpty()) {
-				return createElementAttrFromJson(null, json, attrNode);
+				return _createElementAttrFromJson(null, json, attrNode);
 				// this.addWarning(771,
 				// "Arbitraty elements with attributes are currently not supported.");
 			}
 			else{
-				SpanQueryWrapper elementWithIdWrapper = tag(value.toString());
+				SpanQueryWrapper elementWithIdWrapper = this.builder().tag(value.toString());
 				if (elementWithIdWrapper == null){ return null; }
-				return createElementAttrFromJson(elementWithIdWrapper, json,
+				return _createElementAttrFromJson(elementWithIdWrapper, json,
 						attrNode);
 			}
         };
-        return this.tag(value.toString());
+        return this.builder().tag(value.toString());
     };
 
-	private SpanQueryWrapper createElementAttrFromJson(
-			SpanQueryWrapper elementWithIdWrapper, JsonNode json,
-			JsonNode attrNode) throws QueryException {
+
+    // Deserialize elements with attributes
+	private SpanQueryWrapper _createElementAttrFromJson (
+                SpanQueryWrapper elementWithIdWrapper,
+                JsonNode json,
+                JsonNode attrNode) throws QueryException {
 
 		if (attrNode.get("@type").asText().equals("koral:term")) {
 			SpanQueryWrapper attrWrapper = _attrFromJson(json.get("attr"));
 			if (attrWrapper != null) {
 				if (elementWithIdWrapper != null){
 					return new SpanWithAttributeQueryWrapper(elementWithIdWrapper,
-						attrWrapper);
+                                                             attrWrapper);
 				}
 				else {
 					return new SpanWithAttributeQueryWrapper(attrWrapper);
@@ -993,18 +1022,20 @@
 				throw new QueryException(747, "Attribute is null");
 			}
 		} 
- else if (attrNode.get("@type").asText().equals("koral:termGroup")) {
-			return handleAttrGroup(elementWithIdWrapper, attrNode);
+        else if (attrNode.get("@type").asText().equals("koral:termGroup")) {
+			return _handleAttrGroup(elementWithIdWrapper, attrNode);
 		}
 		else {
 			this.addWarning(715, "Attribute type is not supported");
 		}
 		return elementWithIdWrapper;
 	}
-	
-	private SpanQueryWrapper handleAttrGroup(
-			SpanQueryWrapper elementWithIdWrapper, JsonNode attrNode)
-			throws QueryException {
+
+
+    // Deserialize attribute groups
+	private SpanQueryWrapper _handleAttrGroup (
+                SpanQueryWrapper elementWithIdWrapper,
+                JsonNode attrNode) throws QueryException {
 		if (!attrNode.has("relation")) {
 			throw new QueryException(743, "Term group expects a relation");
 		}
@@ -1028,7 +1059,7 @@
 
 			if (elementWithIdWrapper != null){
 				return new SpanWithAttributeQueryWrapper(elementWithIdWrapper,
-					wrapperList);
+                                                         wrapperList);
 			}
 			else {
 				return new SpanWithAttributeQueryWrapper(wrapperList);
@@ -1044,7 +1075,9 @@
 				}
 				if (elementWithIdWrapper != null) {
 					saqw = new SpanWithAttributeQueryWrapper(
-							elementWithIdWrapper, attrWrapper);
+                        elementWithIdWrapper,
+                        attrWrapper
+                    );
 				} else {
 					saqw = new SpanWithAttributeQueryWrapper(attrWrapper);
 				}
@@ -1080,361 +1113,4 @@
         }
 		return null;
     };
-
-    public JsonNode toJsonNode () {
-        return this.json;
-    };
-
-    public String toJsonString () {
-        if (this.json == null)
-            return "{}";
-        return this.json.toString();
-    };
-
-
-    /*
-     * Following are builder methods that will probably move
-     * to a separated class in the future
-     */
-
-
-    /**
-     * Create a query object based on a regular expression.
-     *
-     * <blockquote><pre>
-     *   KrillQuery kq = new KrillQuery("tokens");
-     *   SpanRegexQueryWrapper re = kq.re(".+?");
-     * </pre></blockquote>
-     *
-     * @param re The regular expession as a string.
-     * @return A {@link SpanRegexQueryWrapper} object.
-     */
-    public SpanRegexQueryWrapper re (String re) {
-        return new SpanRegexQueryWrapper(this.field, re, RegExp.ALL, false);
-    };
-
-
-    /**
-     * Create a query object based on a regular expression.
-     *
-     * Supports flags as defined in {@link org.apache.lucene.util.automaton.RegExp}:
-     * <ul>
-     *   <li><tt>RegExp.ALL</tt> - enables all optional regexp syntax</li>
-     *   <li><tt>RegExp.ANYSTRING</tt> - enables anystring (@)</li>
-     *   <li><tt>RegExp.AUTOMATON</tt> - enables named automata (&lt;identifier&gt;)</li>
-     *   <li><tt>RegExp.COMPLEMENT</tt> - enables complement (~)</li>
-     *   <li><tt>RegExp.EMPTY</tt> - enables empty language (#)</li>
-     *   <li><tt>RegExp.INTERSECTION</tt> - enables intersection (&amp;)</li>
-     *   <li><tt>RegExp.INTERVAL</tt> - enables numerical intervals (&lt;n-m&gt;)</li>
-     *   <li><tt>RegExp.NONE</tt> - enables no optional regexp syntax</li>
-     * </ul>
-     *
-     * <blockquote><pre>
-     *   KrillQuery kq = new KrillQuery("tokens");
-     *   SpanRegexQueryWrapper re = kq.re("[Aa]lternatives?", RegExp.NONE);
-     * </pre></blockquote>
-     *
-     * @param re The regular expession as a string.
-     * @param flags The flag for the regular expression.
-     * @return A {@link SpanRegexQueryWrapper} object.
-     */
-    public SpanRegexQueryWrapper re (String re, int flags) {
-        return new SpanRegexQueryWrapper(this.field, re, flags, false);
-    };
-
-
-    /**
-     * Create a query object based on a regular expression.
-     *
-     * Supports flags (see above) and case insensitivity.
-     *
-     * <blockquote><pre>
-     *   KrillQuery kq = new KrillQuery("tokens");
-     *   SpanRegexQueryWrapper re = kq.re("alternatives?", RegExp.NONE, true);
-     * </pre></blockquote>
-     *
-     * @param re The regular expession as a string.
-     * @param flags The flag for the regular expression.
-     * @param caseinsensitive A boolean value indicating case insensitivity.
-     * @return A {@link SpanRegexQueryWrapper} object.
-     */
-    public SpanRegexQueryWrapper re (String re, int flags, boolean caseinsensitive) {
-        return new SpanRegexQueryWrapper(this.field, re, flags, caseinsensitive);
-    };
-
-
-    /**
-     * Create a query object based on a regular expression.
-     *
-     * Supports case insensitivity.
-     *
-     * <blockquote><pre>
-     *   KrillQuery kq = new KrillQuery("tokens");
-     *   SpanRegexQueryWrapper re = kq.re("alternatives?", true);
-     * </pre></blockquote>
-     *
-     * @param re The regular expession as a string.
-     * @param flags The flag for the regular expression.
-     * @return A {@link SpanRegexQueryWrapper} object.
-     */
-    public SpanRegexQueryWrapper re (String re, boolean caseinsensitive) {
-        return new SpanRegexQueryWrapper(this.field, re, RegExp.ALL, caseinsensitive);
-    };
-
-    /**
-     * Create a query object based on a wildcard term.
-     * <tt>*</tt> indicates an optional sequence of arbitrary characters,
-     * <tt>?</tt> indicates a single character,
-     * <tt>\</tt> can be used for escaping.
-     *
-     * @param wc The wildcard term as a string.
-     * @return A {@link SpanWildcardQueryWrapper} object.
-     */
-    public SpanWildcardQueryWrapper wc (String wc) {
-        return new SpanWildcardQueryWrapper(this.field, wc, false);
-    };
-
-    /**
-     * Create a query object based on a wildcard term.
-     * <tt>*</tt> indicates an optional sequence of arbitrary characters,
-     * <tt>?</tt> indicates a single character,
-     * <tt>\</tt> can be used for escaping.
-     *
-     * Supports case insensitivity.
-     *
-     * <blockquote><pre>
-     *   KrillQuery kq = new KrillQuery("tokens");
-     *   SpanWildcardQueryWrapper wc = kq.wc("wall*", true);
-     * </pre></blockquote>
-     *
-     * @param wc The wildcard term as a string.
-     * @param caseinsensitive A boolean value indicating case insensitivity.
-     * @return A {@link SpanWildcardQueryWrapper} object.
-     */
-    public SpanWildcardQueryWrapper wc (String wc, boolean caseinsensitive) {
-        return new SpanWildcardQueryWrapper(this.field, wc, caseinsensitive);
-    };
-
-
-    /**
-     * Create a segment query object.
-     *
-     * <blockquote><pre>
-     *   KrillQuery kq = new KrillQuery("tokens");
-     *   SpanSegmentQueryWrapper seg = kq.seg();
-     * </pre></blockquote>
-     *
-     * @return A {@link SpanSegmentQueryWrapper} object.
-     */
-    public SpanSegmentQueryWrapper seg () {
-        return new SpanSegmentQueryWrapper(this.field);
-    };
-
-
-    /**
-     * Create a segment query object.
-     * Supports sequences of strings or {@link SpanRegexQueryWrapper},
-     * and {@link SpanAlterQueryWrapper} objects.
-     *
-     * <blockquote><pre>
-     *   KrillQuery kq = new KrillQuery("tokens");
-     *   SpanSegmentQueryWrapper seg = kq.seg(
-     *       kq.re("mate/p=.*?"),
-     *       kq.re("opennlp/p=.*?")
-     *   );
-     * </pre></blockquote>
-     *
-     * @param terms[] An array of terms, the segment consists of.
-     * @return A {@link SpanSegmentQueryWrapper} object.
-     */
-    // Sequence of regular expression queries
-    public SpanSegmentQueryWrapper seg (SpanRegexQueryWrapper ... terms) {
-        SpanSegmentQueryWrapper ssq = new SpanSegmentQueryWrapper(this.field);
-        for (SpanRegexQueryWrapper t : terms)
-            ssq.with(t);
-        return ssq;
-    };
-
-    // Sequence of alternative queries
-    public SpanSegmentQueryWrapper seg (SpanAlterQueryWrapper ... terms) {
-        SpanSegmentQueryWrapper ssq = new SpanSegmentQueryWrapper(this.field);
-        for (SpanAlterQueryWrapper t : terms)
-            ssq.with(t);
-        return ssq;
-    };
-
-    // Sequence of alternative queries
-    public SpanSegmentQueryWrapper seg (String ... terms) {
-        SpanSegmentQueryWrapper ssq = new SpanSegmentQueryWrapper(this.field);
-        for (String t : terms)
-            ssq.with(t);
-        return ssq;
-    };
-
-    /**
-     * Create an empty query segment.
-     *
-     * <blockquote><pre>
-     *   KrillQuery kq = new KrillQuery("tokens");
-     *   SpanRepetitionQueryWrapper seg = kq.empty();
-     * </pre></blockquote>
-     */
-    public SpanRepetitionQueryWrapper empty () {
-        return new SpanRepetitionQueryWrapper();
-    };
-
-
-    // TODO: Further JavaDocs
-
-
-    /**
-     * Create a segment alternation query object.
-     * @param terms[] An array of alternative terms.
-     */
-    public SpanAlterQueryWrapper or (SpanQueryWrapper ... terms) {
-        SpanAlterQueryWrapper ssaq = new SpanAlterQueryWrapper(this.field);
-        for (SpanQueryWrapper t : terms)
-            ssaq.or(t);
-        return ssaq;
-    };
-
-
-    public SpanAlterQueryWrapper or (String ... terms) {
-        SpanAlterQueryWrapper ssaq = new SpanAlterQueryWrapper(this.field);
-        for (String t : terms)
-            ssaq.or(t);
-        return ssaq;
-    };
-
-
-    // SpanSegmentSequenceQueries
-    /**
-     * Create a sequence of segments query object.
-     */
-    public SpanSequenceQueryWrapper seq () {
-        return new SpanSequenceQueryWrapper(this.field);
-    };
-
-
-    /**
-     * Create a sequence of segments query object.
-     * @param terms[] An array of segment defining terms.
-     */
-    public SpanSequenceQueryWrapper seq (SpanQueryWrapper ... terms) {
-        SpanSequenceQueryWrapper sssq = new SpanSequenceQueryWrapper(this.field);
-        for (SpanQueryWrapper t : terms)
-            sssq.append(t);
-        return sssq;
-    };
-
-
-    /**
-     * Create a sequence of segments query object.
-     * @param re A SpanSegmentRegexQuery, starting the sequence.
-     */
-    public SpanSequenceQueryWrapper seq (SpanRegexQueryWrapper re) {
-        return new SpanSequenceQueryWrapper(this.field, re);
-    };
-
-
-    public SpanSequenceQueryWrapper seq (Object ... terms) {
-        SpanSequenceQueryWrapper ssq = new SpanSequenceQueryWrapper(this.field);
-        for (Object t : terms) {
-            if (t instanceof SpanQueryWrapper) {
-                ssq.append((SpanQueryWrapper) t);
-            }
-            else if (t instanceof SpanRegexQueryWrapper) {
-                ssq.append((SpanRegexQueryWrapper) t);
-            }
-            else {
-                log.error("{} is not an acceptable parameter for seq()", t.getClass());
-                return ssq;
-            };
-        };
-        return ssq;
-    };
-
-
-    public SpanElementQueryWrapper tag (String element) {
-        return new SpanElementQueryWrapper(this.field, element);
-    };
-
-    /**
-     * Create a wrapping within query object.
-     * @param element A SpanQuery.
-     * @param embedded A SpanQuery that is wrapped in the element.
-     */
-    @Deprecated
-    public SpanWithinQueryWrapper within (SpanQueryWrapper element,
-                                          SpanQueryWrapper embedded) {
-        return new SpanWithinQueryWrapper(element, embedded);
-    };
-    
-    public SpanWithinQueryWrapper contains (SpanQueryWrapper element,
-                                            SpanQueryWrapper embedded) {
-        return new SpanWithinQueryWrapper(element, embedded, WITHIN);
-    };
-
-    public SpanWithinQueryWrapper startswith (SpanQueryWrapper element,
-                                              SpanQueryWrapper embedded) {
-        return new SpanWithinQueryWrapper(element, embedded, STARTSWITH);
-    };
-
-    public SpanWithinQueryWrapper endswith (SpanQueryWrapper element,
-                                            SpanQueryWrapper embedded) {
-        return new SpanWithinQueryWrapper(element, embedded, ENDSWITH);
-    };
-
-    public SpanWithinQueryWrapper overlaps (SpanQueryWrapper element,
-                                            SpanQueryWrapper embedded) {
-        return new SpanWithinQueryWrapper(element, embedded, OVERLAP);
-    }; 
-
-    public SpanWithinQueryWrapper matches (SpanQueryWrapper element,
-                                           SpanQueryWrapper embedded) {
-        return new SpanWithinQueryWrapper(element, embedded, MATCH);
-    }; 
-
-    // Class
-    public SpanClassQueryWrapper _ (byte number, SpanQueryWrapper element) {
-        return new SpanClassQueryWrapper(element, number);
-    };
-
-    public SpanClassQueryWrapper _ (int number, SpanQueryWrapper element) {
-        return new SpanClassQueryWrapper(element, number);
-    };
-
-    public SpanClassQueryWrapper _ (short number, SpanQueryWrapper element) {
-        return new SpanClassQueryWrapper(element, number);
-    };
-
-    public SpanClassQueryWrapper _ (SpanQueryWrapper element) {
-        return new SpanClassQueryWrapper(element);
-    };
-
-    // Focus
-    public SpanFocusQueryWrapper focus (byte number, SpanQueryWrapper element) {
-        return new SpanFocusQueryWrapper(element, number);
-    };
-
-    public SpanFocusQueryWrapper focus (int number, SpanQueryWrapper element) {
-        return new SpanFocusQueryWrapper(element, number);
-    };
-
-    public SpanFocusQueryWrapper focus (short number, SpanQueryWrapper element) {
-        return new SpanFocusQueryWrapper(element, number);
-    };
-
-    public SpanFocusQueryWrapper focus (SpanQueryWrapper element) {
-        return new SpanFocusQueryWrapper(element);
-    };
-
-    // Repetition
-    public SpanRepetitionQueryWrapper repeat (SpanQueryWrapper element, int exact) {
-        return new SpanRepetitionQueryWrapper(element, exact);
-    };
-
-    public SpanRepetitionQueryWrapper repeat (SpanQueryWrapper element, int min, int max) {
-        return new SpanRepetitionQueryWrapper(element, min, max);
-    };
 };
diff --git a/src/main/java/de/ids_mannheim/korap/response/KorapResponse.java b/src/main/java/de/ids_mannheim/korap/response/KorapResponse.java
index 738e32a..88b73bc 100644
--- a/src/main/java/de/ids_mannheim/korap/response/KorapResponse.java
+++ b/src/main/java/de/ids_mannheim/korap/response/KorapResponse.java
@@ -30,6 +30,7 @@
  * @author diewald
  * @see Notifications
  */
+// Todo: Use configuration file to get default token field "tokens"
 @JsonInclude(Include.NON_NULL)
 @JsonIgnoreProperties(ignoreUnknown = true)
 public class KorapResponse extends Notifications {
@@ -328,10 +329,11 @@
      * @return The {@link KrillQuery} object,
      *         representing the KoralQuery query object.
      */
+    // TODO: "tokens" shouldn't be fixed.
     @JsonIgnore
     public KrillQuery getQuery () {
         if (this.query == null)
-            this.query = new KrillQuery();
+            this.query = new KrillQuery("tokens");
         return this.query;
     };
 
diff --git a/src/test/java/de/ids_mannheim/korap/TestSimple.java b/src/test/java/de/ids_mannheim/korap/TestSimple.java
index 1b1fe24..ec741fd 100644
--- a/src/test/java/de/ids_mannheim/korap/TestSimple.java
+++ b/src/test/java/de/ids_mannheim/korap/TestSimple.java
@@ -6,6 +6,7 @@
 import static org.junit.Assert.*;
 
 import de.ids_mannheim.korap.KrillQuery;
+import de.ids_mannheim.korap.query.QueryBuilder;
 import de.ids_mannheim.korap.model.*;
 import de.ids_mannheim.korap.query.wrap.SpanQueryWrapper;
 import de.ids_mannheim.korap.util.QueryException;
@@ -99,7 +100,7 @@
         }
         catch (QueryException e) {
             fail(e.getMessage());
-            sqwi = new KrillQuery("tokens").seg("???");
+            sqwi = new QueryBuilder("tokens").seg("???");
         };
         return sqwi;
     };
diff --git a/src/test/java/de/ids_mannheim/korap/benchmark/TestBenchmarkSpans.java b/src/test/java/de/ids_mannheim/korap/benchmark/TestBenchmarkSpans.java
index badae2d..06dc685 100644
--- a/src/test/java/de/ids_mannheim/korap/benchmark/TestBenchmarkSpans.java
+++ b/src/test/java/de/ids_mannheim/korap/benchmark/TestBenchmarkSpans.java
@@ -9,6 +9,7 @@
 import de.ids_mannheim.korap.Krill;
 import de.ids_mannheim.korap.KorapResult;
 import de.ids_mannheim.korap.KrillQuery;
+import de.ids_mannheim.korap.query.QueryBuilder;
 import org.apache.lucene.store.MMapDirectory;
 import de.ids_mannheim.korap.collection.BooleanFilter;
 import org.apache.lucene.search.spans.SpanQuery;
@@ -371,7 +372,7 @@
         }
         catch (QueryException e) {
             fail(e.getMessage());
-            sqwi = new KrillQuery("tokens").seg("???");
+            sqwi = new QueryBuilder("tokens").seg("???");
         };
         return sqwi;
     };
diff --git a/src/test/java/de/ids_mannheim/korap/collection/TestKorapCollectionLegacy.java b/src/test/java/de/ids_mannheim/korap/collection/TestKorapCollectionLegacy.java
index 7183de6..97bbffd 100644
--- a/src/test/java/de/ids_mannheim/korap/collection/TestKorapCollectionLegacy.java
+++ b/src/test/java/de/ids_mannheim/korap/collection/TestKorapCollectionLegacy.java
@@ -7,6 +7,7 @@
 import de.ids_mannheim.korap.KorapCollection;
 import de.ids_mannheim.korap.KorapResult;
 import de.ids_mannheim.korap.KrillQuery;
+import de.ids_mannheim.korap.query.QueryBuilder;
 import de.ids_mannheim.korap.collection.BooleanFilter;
 
 import org.apache.lucene.index.Term;
@@ -78,7 +79,7 @@
 	assertEquals("Paragraphs", 48, kc.numberOf("paragraphs"));
 
 	// Create a query
-	KrillQuery kq = new KrillQuery("tokens");
+	QueryBuilder kq = new QueryBuilder("tokens");
 	SpanQuery query = kq.seg("opennlp/p:NN").with("tt/p:NN").toQuery();
 
 	KorapResult kr = kc.search(query);
@@ -155,7 +156,7 @@
 	assertEquals("Paragraphs", 48, kc.numberOf("paragraphs"));
 
 	// Create a query
-	KrillQuery kq = new KrillQuery("tokens");
+	QueryBuilder kq = new QueryBuilder("tokens");
 	SpanQuery query = kq.seg("opennlp/p:NN").with("tt/p:NN").toQuery();
 
 	KorapResult kr = kc.search(query);
@@ -208,7 +209,7 @@
 	assertEquals("Paragraphs", 139, kc.numberOf("paragraphs"));
 
 	// Create a query
-	KrillQuery kq = new KrillQuery("tokens");
+	QueryBuilder kq = new QueryBuilder("tokens");
 	SpanQuery query = kq.seg("opennlp/p:NN").with("tt/p:NN").toQuery();
 
 	KorapResult kr = kc.search(query);
diff --git a/src/test/java/de/ids_mannheim/korap/highlight/TestHighlight.java b/src/test/java/de/ids_mannheim/korap/highlight/TestHighlight.java
index 0a154dc..79d49b0 100644
--- a/src/test/java/de/ids_mannheim/korap/highlight/TestHighlight.java
+++ b/src/test/java/de/ids_mannheim/korap/highlight/TestHighlight.java
@@ -7,6 +7,7 @@
 
 import de.ids_mannheim.korap.KorapIndex;
 import de.ids_mannheim.korap.KrillQuery;
+import de.ids_mannheim.korap.query.QueryBuilder;
 import de.ids_mannheim.korap.KorapResult;
 import de.ids_mannheim.korap.Krill;
 import de.ids_mannheim.korap.KorapMatch;
@@ -50,7 +51,7 @@
         ki.commit();
 
 
-        KrillQuery kq = new KrillQuery("tokens");
+        QueryBuilder kq = new QueryBuilder("tokens");
         KorapResult kr = ki.search(
             (SpanQuery) kq.seq(kq._(1, kq.seg("s:b"))).toQuery()
         );
@@ -120,7 +121,7 @@
         FieldDocument fd = ki.addDoc(json);
         ki.commit();
 
-        KrillQuery kq = new KrillQuery("tokens");
+        QueryBuilder kq = new QueryBuilder("tokens");
 
         KorapResult kr = ki.search((SpanQuery) kq.seq(kq.seg("s:a")).append(kq.seg("s:b")).append(kq.seg("s:c")).toQuery());
         KorapMatch km = kr.getMatch(0);
@@ -187,7 +188,7 @@
         // Commit!
         ki.commit();
 
-        KrillQuery kq = new KrillQuery("base");
+        QueryBuilder kq = new QueryBuilder("base");
         SpanQuery q = (SpanQuery) kq.or(kq._(1, kq.seg("s:a"))).or(kq._(2, kq.seg("s:b"))).toQuery();
         KorapResult kr = ki.search(q);
         assertEquals((long) 14, kr.getTotalResults());
@@ -209,7 +210,7 @@
         assertEquals("a[{2:b}]a", kr.getMatch(12).getSnippetBrackets());
         assertEquals("ab[{1:a}]", kr.getMatch(13).getSnippetBrackets());
 
-        kq = new KrillQuery("base");
+        kq = new QueryBuilder("base");
         q = (SpanQuery) kq.or(kq._(1, kq.seg("i:a"))).or(kq._(2, kq.seg("i:c"))).toQuery();
         Krill qs = new Krill(q);
         qs.getMeta().getContext().left.setToken(true).setLength((short) 1);
diff --git a/src/test/java/de/ids_mannheim/korap/index/TestElementDistanceIndex.java b/src/test/java/de/ids_mannheim/korap/index/TestElementDistanceIndex.java
index 735674a..bebd2a9 100644
--- a/src/test/java/de/ids_mannheim/korap/index/TestElementDistanceIndex.java
+++ b/src/test/java/de/ids_mannheim/korap/index/TestElementDistanceIndex.java
@@ -19,6 +19,7 @@
 import de.ids_mannheim.korap.KorapMatch;
 import de.ids_mannheim.korap.KrillQuery;
 import de.ids_mannheim.korap.KorapResult;
+import de.ids_mannheim.korap.query.QueryBuilder;
 import de.ids_mannheim.korap.query.DistanceConstraint;
 import de.ids_mannheim.korap.query.SpanDistanceQuery;
 import de.ids_mannheim.korap.query.SpanElementQuery;
@@ -215,7 +216,7 @@
     	}
     	catch (QueryException e) {
     	    fail(e.getMessage());
-    	    sqwi = new KrillQuery("tokens").seg("???");
+    	    sqwi = new QueryBuilder("tokens").seg("???");
     	};        
     	
         
diff --git a/src/test/java/de/ids_mannheim/korap/index/TestFieldDocument.java b/src/test/java/de/ids_mannheim/korap/index/TestFieldDocument.java
index e376e7f..faf7b1b 100644
--- a/src/test/java/de/ids_mannheim/korap/index/TestFieldDocument.java
+++ b/src/test/java/de/ids_mannheim/korap/index/TestFieldDocument.java
@@ -25,6 +25,7 @@
 import de.ids_mannheim.korap.KorapDocument;
 import de.ids_mannheim.korap.query.SpanNextQuery;
 import de.ids_mannheim.korap.query.SpanClassQuery;
+import de.ids_mannheim.korap.query.QueryBuilder;
 import de.ids_mannheim.korap.index.FieldDocument;
 import de.ids_mannheim.korap.model.MultiTermTokenStream;
 
@@ -135,7 +136,7 @@
 	assertEquals(fd.getPubPlace(),"Bochum");
 	assertEquals(fd.getPubDate().toDisplay(),"2013-06-17");
 
-	KrillQuery kq = new KrillQuery("tokens");
+	QueryBuilder kq = new QueryBuilder("tokens");
 	KorapResult kr = ki.search((SpanQuery) kq.seq(kq._(3, kq.seg("s:b"))).toQuery());
 
 	KorapMatch km = kr.getMatch(0);
@@ -174,7 +175,7 @@
 	};
 	ki.commit();
 
-	KrillQuery kq = new KrillQuery("tokens");
+	QueryBuilder kq = new QueryBuilder("tokens");
 
 	Krill ks;
 	KorapResult kr;
@@ -247,16 +248,16 @@
     };
 
     public static SpanQueryWrapper jsonQuery (String jsonFile) {
-	SpanQueryWrapper sqwi;
+        SpanQueryWrapper sqwi;
 	
-	try {
-	    String json = getString(jsonFile);
-	    sqwi = new KrillQuery("tokens").fromJson(json);
-	}
-	catch (QueryException e) {
-	    fail(e.getMessage());
-	    sqwi = new KrillQuery("tokens").seg("???");
-	};
-	return sqwi;
+        try {
+            String json = getString(jsonFile);
+            sqwi = new KrillQuery("tokens").fromJson(json);
+        }
+        catch (QueryException e) {
+            fail(e.getMessage());
+            sqwi = new QueryBuilder("tokens").seg("???");
+        };
+        return sqwi;
     };
 };
diff --git a/src/test/java/de/ids_mannheim/korap/index/TestMatchIdentifier.java b/src/test/java/de/ids_mannheim/korap/index/TestMatchIdentifier.java
index ea51476..65f6679 100644
--- a/src/test/java/de/ids_mannheim/korap/index/TestMatchIdentifier.java
+++ b/src/test/java/de/ids_mannheim/korap/index/TestMatchIdentifier.java
@@ -15,6 +15,7 @@
 import de.ids_mannheim.korap.KorapIndex;
 import de.ids_mannheim.korap.KrillQuery;
 import de.ids_mannheim.korap.Krill;
+import de.ids_mannheim.korap.query.QueryBuilder;
 import de.ids_mannheim.korap.KorapResult;
 import de.ids_mannheim.korap.KorapMatch;
 import de.ids_mannheim.korap.util.QueryException;
@@ -91,7 +92,7 @@
 	ki.addDoc(createSimpleFieldDoc());
 	ki.commit();
 
-	KrillQuery kq = new KrillQuery("tokens");
+	QueryBuilder kq = new QueryBuilder("tokens");
 	Krill ks = new Krill(
 	    kq._(2,kq.seq(kq.seg("s:b")).append(kq._(kq.seg("s:a"))))
         );
diff --git a/src/test/java/de/ids_mannheim/korap/index/TestMatchIndex.java b/src/test/java/de/ids_mannheim/korap/index/TestMatchIndex.java
index 39371c1..c1caa4a 100644
--- a/src/test/java/de/ids_mannheim/korap/index/TestMatchIndex.java
+++ b/src/test/java/de/ids_mannheim/korap/index/TestMatchIndex.java
@@ -287,7 +287,7 @@
 
         KorapResult kr;
 
-        KrillQuery kq = new KrillQuery("base");
+        QueryBuilder kq = new QueryBuilder("base");
 
         SpanQuery sq = kq._(1,kq.seq(kq.seg("s:b")).append(kq.seg("s:a")).append(kq._(2,kq.seg("s:c")))).toQuery();
         
diff --git a/src/test/java/de/ids_mannheim/korap/index/TestRealIndex.java b/src/test/java/de/ids_mannheim/korap/index/TestRealIndex.java
index e2b52fc..6c589ff 100644
--- a/src/test/java/de/ids_mannheim/korap/index/TestRealIndex.java
+++ b/src/test/java/de/ids_mannheim/korap/index/TestRealIndex.java
@@ -14,13 +14,13 @@
 import org.junit.Test;
 
 import de.ids_mannheim.korap.*;
+import de.ids_mannheim.korap.query.QueryBuilder;
 import de.ids_mannheim.korap.util.QueryException;
 
 public class TestRealIndex {
     KorapIndex ki;
     KorapResult kr;
     Krill ks;
-    KrillQuery kq;
 	
     public TestRealIndex() throws IOException {
         InputStream is = getClass().getResourceAsStream("/server.properties");
@@ -35,7 +35,7 @@
 
     @Test
     public void testCase1() throws IOException, QueryException {
-        KrillQuery kq = new KrillQuery("tokens");
+        QueryBuilder kq = new QueryBuilder("tokens");
         ks = new Krill(kq.within(kq.tag("base/s:s"), kq.seq(kq.re("s:.*")).append(kq._(kq.re("s:.*")))).toQuery());
         ks.getMeta().setTimeOut(10000);
         kr = ks.apply(ki);
diff --git a/src/test/java/de/ids_mannheim/korap/index/TestRegexWildcardIndex.java b/src/test/java/de/ids_mannheim/korap/index/TestRegexWildcardIndex.java
index 5fb5afa..5dffbee 100644
--- a/src/test/java/de/ids_mannheim/korap/index/TestRegexWildcardIndex.java
+++ b/src/test/java/de/ids_mannheim/korap/index/TestRegexWildcardIndex.java
@@ -17,6 +17,7 @@
 import de.ids_mannheim.korap.KrillQuery;
 import de.ids_mannheim.korap.KorapResult;
 import de.ids_mannheim.korap.Krill;
+import de.ids_mannheim.korap.query.QueryBuilder;
 import de.ids_mannheim.korap.index.FieldDocument;
 import de.ids_mannheim.korap.model.MultiTermTokenStream;
 import org.apache.lucene.search.Query;
@@ -48,7 +49,7 @@
 
 	ki.commit();
 
-	KrillQuery kq = new KrillQuery("base");
+	QueryBuilder kq = new QueryBuilder("base");
 	SpanQuery sq = kq.re("s:af*e").toQuery();
 	assertEquals("SpanMultiTermQueryWrapper(base:/s:af*e/)", sq.toString());
 			
@@ -61,22 +62,22 @@
 	assertEquals("[affe] afffe ...", kr.getMatch(0).getSnippetBrackets());
 	assertEquals("affe [afffe] baum ...", kr.getMatch(1).getSnippetBrackets());
 
-	kr = ki.search(ks.setSpanQuery(new KrillQuery("base").re("s:baum.*").toQuery()));
+	kr = ki.search(ks.setSpanQuery(new QueryBuilder("base").re("s:baum.*").toQuery()));
 	assertEquals((long) 2, kr.getTotalResults());
 	assertEquals("... afffe [baum] baumgarten ...", kr.getMatch(0).getSnippetBrackets());
 	assertEquals("... baum [baumgarten] steingarten ...", kr.getMatch(1).getSnippetBrackets());
 
-	kr = ki.search(ks.setSpanQuery(new KrillQuery("base").re("s:.....?garten").toQuery()));
+	kr = ki.search(ks.setSpanQuery(new QueryBuilder("base").re("s:.....?garten").toQuery()));
 	assertEquals((long) 2, kr.getTotalResults());
 	assertEquals("... baum [baumgarten] steingarten ...", kr.getMatch(0).getSnippetBrackets());
 	assertEquals("... baumgarten [steingarten] franz ...", kr.getMatch(1).getSnippetBrackets());
 
-	kr = ki.search(ks.setSpanQuery(new KrillQuery("base").re("s:ha.s").toQuery()));
+	kr = ki.search(ks.setSpanQuery(new QueryBuilder("base").re("s:ha.s").toQuery()));
 	assertEquals((long) 2, kr.getTotalResults());
 	assertEquals("... franz [hans] haus ...", kr.getMatch(0).getSnippetBrackets());
 	assertEquals("... hans [haus] efeu ...", kr.getMatch(1).getSnippetBrackets());
 
-	kr = ki.search(ks.setSpanQuery(new KrillQuery("base").re("s:.*ff.*").toQuery()));
+	kr = ki.search(ks.setSpanQuery(new QueryBuilder("base").re("s:.*ff.*").toQuery()));
 	assertEquals((long) 3, kr.getTotalResults());
 	assertEquals("[affe] afffe ...", kr.getMatch(0).getSnippetBrackets());
 	assertEquals("affe [afffe] baum ...", kr.getMatch(1).getSnippetBrackets());
@@ -105,7 +106,7 @@
 
 	ki.commit();
 
-	KrillQuery kq = new KrillQuery("base");
+	QueryBuilder kq = new QueryBuilder("base");
 	SpanQuery sq = kq.wc("s:af*e").toQuery();
 	assertEquals("SpanMultiTermQueryWrapper(base:s:af*e)", sq.toString());
 
@@ -118,25 +119,25 @@
 	assertEquals("[affe] afffe ...", kr.getMatch(0).getSnippetBrackets());
 	assertEquals("affe [afffe] baum ...", kr.getMatch(1).getSnippetBrackets());
 
-	kr = ki.search(ks.setSpanQuery(new KrillQuery("base").wc("s:baum.*").toQuery()));
+	kr = ki.search(ks.setSpanQuery(new QueryBuilder("base").wc("s:baum.*").toQuery()));
 	assertEquals((long) 0, kr.getTotalResults());
 
-	kr = ki.search(ks.setSpanQuery(new KrillQuery("base").wc("s:baum*").toQuery()));
+	kr = ki.search(ks.setSpanQuery(new QueryBuilder("base").wc("s:baum*").toQuery()));
 	assertEquals((long) 2, kr.getTotalResults());
 	assertEquals("... afffe [baum] baumgarten ...", kr.getMatch(0).getSnippetBrackets());
 	assertEquals("... baum [baumgarten] steingarten ...", kr.getMatch(1).getSnippetBrackets());
 
-	kr = ki.search(ks.setSpanQuery(new KrillQuery("base").wc("s:*garten").toQuery()));
+	kr = ki.search(ks.setSpanQuery(new QueryBuilder("base").wc("s:*garten").toQuery()));
 	assertEquals((long) 2, kr.getTotalResults());
 	assertEquals("... baum [baumgarten] steingarten ...", kr.getMatch(0).getSnippetBrackets());
 	assertEquals("... baumgarten [steingarten] franz ...", kr.getMatch(1).getSnippetBrackets());
 
-	kr = ki.search(ks.setSpanQuery(new KrillQuery("base").wc("s:ha?s").toQuery()));
+	kr = ki.search(ks.setSpanQuery(new QueryBuilder("base").wc("s:ha?s").toQuery()));
 	assertEquals((long) 2, kr.getTotalResults());
 	assertEquals("... franz [hans] haus ...", kr.getMatch(0).getSnippetBrackets());
 	assertEquals("... hans [haus] efeu ...", kr.getMatch(1).getSnippetBrackets());
 
-	kr = ki.search(ks.setSpanQuery(new KrillQuery("base").wc("s:?ff?").toQuery()));
+	kr = ki.search(ks.setSpanQuery(new QueryBuilder("base").wc("s:?ff?").toQuery()));
 	assertEquals((long) 2, kr.getTotalResults());
 	assertEquals("[affe] afffe ...", kr.getMatch(0).getSnippetBrackets());
 	assertEquals("... efeu [effe]", kr.getMatch(1).getSnippetBrackets());
@@ -164,7 +165,7 @@
 
 	ki.commit();
 
-	KrillQuery kq = new KrillQuery("base");
+	QueryBuilder kq = new QueryBuilder("base");
 	SpanQuery sq = kq.re("s:Af*e", true).toQuery();
 	assertEquals("SpanMultiTermQueryWrapper(base:/i:af*e/)", sq.toString());
 
@@ -177,30 +178,30 @@
 	assertEquals("[AfFe] aFfFE ...", kr.getMatch(0).getSnippetBrackets());
 	assertEquals("AfFe [aFfFE] Baum ...", kr.getMatch(1).getSnippetBrackets());
 
-	kr = ki.search(ks.setSpanQuery(new KrillQuery("base").re("s:Af.*e").toQuery()));
+	kr = ki.search(ks.setSpanQuery(new QueryBuilder("base").re("s:Af.*e").toQuery()));
 	assertEquals((long) 1, kr.getTotalResults());
 	assertEquals("[AfFe] aFfFE ...", kr.getMatch(0).getSnippetBrackets());
 
-	kr = ki.search(ks.setSpanQuery(new KrillQuery("base").re("s:baum.*", true).toQuery()));
+	kr = ki.search(ks.setSpanQuery(new QueryBuilder("base").re("s:baum.*", true).toQuery()));
 	assertEquals((long) 2, kr.getTotalResults());
 	assertEquals("... aFfFE [Baum] Baumgarten ...", kr.getMatch(0).getSnippetBrackets());
 	assertEquals("... Baum [Baumgarten] SteinGarten ...", kr.getMatch(1).getSnippetBrackets());
 
-	kr = ki.search(ks.setSpanQuery(new KrillQuery("base").re("s:.*garten", true).toQuery()));
+	kr = ki.search(ks.setSpanQuery(new QueryBuilder("base").re("s:.*garten", true).toQuery()));
 	assertEquals((long) 2, kr.getTotalResults());
 	assertEquals("... Baum [Baumgarten] SteinGarten ...", kr.getMatch(0).getSnippetBrackets());
 	assertEquals("... Baumgarten [SteinGarten] franZ ...", kr.getMatch(1).getSnippetBrackets());
 
-	kr = ki.search(ks.setSpanQuery(new KrillQuery("base").re("s:.*garten", false).toQuery()));
+	kr = ki.search(ks.setSpanQuery(new QueryBuilder("base").re("s:.*garten", false).toQuery()));
 	assertEquals((long) 1, kr.getTotalResults());
 	assertEquals("... Baum [Baumgarten] SteinGarten ...", kr.getMatch(0).getSnippetBrackets());
 
-	kr = ki.search(ks.setSpanQuery(new KrillQuery("base").re("s:ha.s", true).toQuery()));
+	kr = ki.search(ks.setSpanQuery(new QueryBuilder("base").re("s:ha.s", true).toQuery()));
 	assertEquals((long) 2, kr.getTotalResults());
 	assertEquals("... franZ [HaNs] Haus ...", kr.getMatch(0).getSnippetBrackets());
 	assertEquals("... HaNs [Haus] Efeu ...", kr.getMatch(1).getSnippetBrackets());
 
-	kr = ki.search(ks.setSpanQuery(new KrillQuery("base").re("s:.*f*e", true).toQuery()));
+	kr = ki.search(ks.setSpanQuery(new QueryBuilder("base").re("s:.*f*e", true).toQuery()));
 	assertEquals((long) 3, kr.getTotalResults());
 	assertEquals("[AfFe] aFfFE ...", kr.getMatch(0).getSnippetBrackets());
 	assertEquals("AfFe [aFfFE] Baum ...", kr.getMatch(1).getSnippetBrackets());
@@ -229,7 +230,7 @@
 
 	ki.commit();
 
-	KrillQuery kq = new KrillQuery("base");
+	QueryBuilder kq = new QueryBuilder("base");
 	SpanQuery sq = kq.seq(kq.seg("s:affe")).append(kq.re("s:af*e")).toQuery();
 	assertEquals("spanNext(base:s:affe, SpanMultiTermQueryWrapper(base:/s:af*e/))", sq.toString());
 
@@ -265,7 +266,7 @@
 
 	ki.commit();
 
-	KrillQuery kq = new KrillQuery("base");
+	QueryBuilder kq = new QueryBuilder("base");
 	SpanQuery sq = kq.contains(
 				   kq.seq(
 					  kq.re("s:a.*e")
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 a6b7074..96a473c 100644
--- a/src/test/java/de/ids_mannheim/korap/query/TestKrillQuery.java
+++ b/src/test/java/de/ids_mannheim/korap/query/TestKrillQuery.java
@@ -3,6 +3,7 @@
 import java.util.*;
 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.util.QueryException;
 
@@ -21,35 +22,35 @@
 
     @Test
     public void korapQuerySegment () throws QueryException {
-        SpanQuery sq = new KrillQuery("field1").seg("a").with("b").toQuery();
+        SpanQuery sq = new QueryBuilder("field1").seg("a").with("b").toQuery();
         assertEquals("spanSegment(field1:a, field1:b)", sq.toString());
         
-        sq = new KrillQuery("field2").seg("a", "b").with("c").toQuery();
+        sq = new QueryBuilder("field2").seg("a", "b").with("c").toQuery();
         assertEquals("spanSegment(spanSegment(field2:a, field2:b), field2:c)", sq.toString());
     };
 
     @Test
     public void korapQueryRegexSegment () throws QueryException {
-        KrillQuery kq = new KrillQuery("field1");
+        QueryBuilder kq = new QueryBuilder("field1");
         SpanQuery sq = kq.seg("a").with(kq.re("b.*c")).toQuery();
         assertEquals("spanSegment(field1:a, SpanMultiTermQueryWrapper(field1:/b.*c/))", sq.toString());
 
-        kq = new KrillQuery("field2");
+        kq = new QueryBuilder("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 {
-        KrillQuery kq = new KrillQuery("field");
+        QueryBuilder kq = new QueryBuilder("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 KrillQuery("field");
+        kq = new QueryBuilder("field");
         sq = kq.seg("a").with(kq.or("b", "c")).toQuery();
         assertEquals("spanSegment(field:a, spanOr([field:b, field:c]))", sq.toString());
 
-        kq = new KrillQuery("field");
+        kq = new QueryBuilder("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());
@@ -57,49 +58,49 @@
 
     @Test
     public void korapQuerySequenceSegment () throws QueryException {
-        KrillQuery kq = new KrillQuery("field");
+        QueryBuilder kq = new QueryBuilder("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 {
-        KrillQuery kq = new KrillQuery("field");
+        QueryBuilder kq = new QueryBuilder("field");
         SpanQuery sq = kq.tag("np").toQuery();
         assertEquals("<field:np />", sq.toString());
     };
 
     @Test
     public void KorapTagQuery2 () throws QueryException {
-        KrillQuery kq = new KrillQuery("field");
+        QueryBuilder kq = new QueryBuilder("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 {
-        KrillQuery kq = new KrillQuery("field");
+        QueryBuilder kq = new QueryBuilder("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 {
-        KrillQuery kq = new KrillQuery("field");
+        QueryBuilder kq = new QueryBuilder("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 {
-        KrillQuery kq = new KrillQuery("field");
+        QueryBuilder kq = new QueryBuilder("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 {
-        KrillQuery kq = new KrillQuery("field");
+        QueryBuilder kq = new QueryBuilder("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());
     };
@@ -107,133 +108,133 @@
 
     @Test
     public void KorapClassQuery () throws QueryException {
-        KrillQuery kq = new KrillQuery("field");
+        QueryBuilder kq = new QueryBuilder("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 {
-        KrillQuery kq = new KrillQuery("field");
+        QueryBuilder kq = new QueryBuilder("field");
         SpanQuery sq = kq._(kq.seg("base:test")).toQuery();
         assertEquals("{1: field:base:test}", sq.toString());
     };
 
     @Test
     public void KorapClassQuery3 () throws QueryException {
-        KrillQuery kq = new KrillQuery("field");
+        QueryBuilder kq = new QueryBuilder("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 {
-        KrillQuery kq = new KrillQuery("field");
+        QueryBuilder kq = new QueryBuilder("field");
         SpanQuery sq = kq.focus(kq.tag("np")).toQuery();
         assertEquals("focus(1: <field:np />)", sq.toString());
     };
 
     @Test
     public void KorapShrinkQuery1 () throws QueryException {
-        KrillQuery kq = new KrillQuery("field");
+        QueryBuilder kq = new QueryBuilder("field");
         SpanQuery sq = kq.focus(1, kq.tag("np")).toQuery();
         assertEquals("focus(1: <field:np />)", sq.toString());
     };
 
     @Test
     public void KorapShrinkQuery2 () throws QueryException {
-        KrillQuery kq = new KrillQuery("field");
+        QueryBuilder kq = new QueryBuilder("field");
         SpanQuery sq = kq.focus(1, kq._(1, kq.tag("np"))).toQuery();
         assertEquals("focus(1: {1: <field:np />})", sq.toString());
     };
 
     @Test
     public void KorapShrinkQuery3 () throws QueryException {
-        KrillQuery kq = new KrillQuery("field");
+        QueryBuilder kq = new QueryBuilder("field");
         SpanQuery sq = kq.focus(1, kq._(1, kq.seq(kq.tag("np"), kq._(kq.seg("test").without("no"))))).toQuery();
         assertEquals("focus(1: {1: spanNext(<field:np />, {1: spanNot(field:test, field:no, 0, 0)})})", sq.toString());
     };
 
     @Test
     public void KorapShrinkQuery4 () throws QueryException {
-        KrillQuery kq = new KrillQuery("field");
+        QueryBuilder kq = new QueryBuilder("field");
         SpanQuery sq = kq.seq(kq.seg("try1"), kq.focus(1, kq._(1, kq.seg("try2"))), kq.seg("try3")).toQuery();
         assertEquals("spanNext(spanNext(field:try1, focus(1: {1: field:try2})), field:try3)", sq.toString());
     };
 
     @Test
     public void KorapSequenceQuery1 () throws QueryException {
-        KrillQuery kq = new KrillQuery("field");
+        QueryBuilder kq = new QueryBuilder("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 {
-        KrillQuery kq = new KrillQuery("field");
+        QueryBuilder kq = new QueryBuilder("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 {
-        KrillQuery kq = new KrillQuery("field");
+        QueryBuilder kq = new QueryBuilder("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 {
-        KrillQuery kq = new KrillQuery("field");
+        QueryBuilder kq = new QueryBuilder("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 {
-        KrillQuery kq = new KrillQuery("field");
+        QueryBuilder kq = new QueryBuilder("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 {
-        KrillQuery kq = new KrillQuery("field");
+        QueryBuilder kq = new QueryBuilder("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 {
-        KrillQuery kq = new KrillQuery("field");
+        QueryBuilder kq = new QueryBuilder("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 {
-        KrillQuery kq = new KrillQuery("field");
+        QueryBuilder kq = new QueryBuilder("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 {
-        KrillQuery kq = new KrillQuery("field");
+        QueryBuilder kq = new QueryBuilder("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 {
-        KrillQuery kq = new KrillQuery("field");
+        QueryBuilder kq = new QueryBuilder("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 {
-        KrillQuery kq = new KrillQuery("field");
+        QueryBuilder kq = new QueryBuilder("field");
         SpanQuery sq = kq.startswith(kq.seg("test"), kq.seg("test2")).toQuery();
         assertEquals("spanStartsWith(field:test, field:test2)", sq.toString());
     };
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 6277449..2613a20 100644
--- a/src/test/java/de/ids_mannheim/korap/query/TestKrillQueryJSON.java
+++ b/src/test/java/de/ids_mannheim/korap/query/TestKrillQueryJSON.java
@@ -7,6 +7,7 @@
 import de.ids_mannheim.korap.query.wrap.SpanQueryWrapper;
 
 import de.ids_mannheim.korap.KrillQuery;
+import de.ids_mannheim.korap.query.QueryBuilder;
 import de.ids_mannheim.korap.util.QueryException;
 
 import static org.junit.Assert.*;
@@ -361,7 +362,7 @@
 	}
 	catch (QueryException e) {
 	    fail(e.getMessage());
-	    sqwi = new KrillQuery("tokens").seg("???");
+	    sqwi = new QueryBuilder("tokens").seg("???");
 	};
 	return sqwi;
     };
diff --git a/src/test/java/de/ids_mannheim/korap/search/TestKorapResult.java b/src/test/java/de/ids_mannheim/korap/search/TestKorapResult.java
index 7786e3e..b84d5f2 100644
--- a/src/test/java/de/ids_mannheim/korap/search/TestKorapResult.java
+++ b/src/test/java/de/ids_mannheim/korap/search/TestKorapResult.java
@@ -1,3 +1,4 @@
+
 package de.ids_mannheim.korap.search;
 
 import java.util.*;
@@ -10,6 +11,7 @@
 import de.ids_mannheim.korap.KorapResult;
 import de.ids_mannheim.korap.Krill;
 import de.ids_mannheim.korap.KorapMatch;
+import de.ids_mannheim.korap.query.QueryBuilder;
 import de.ids_mannheim.korap.index.FieldDocument;
 
 import de.ids_mannheim.korap.util.QueryException;
@@ -54,7 +56,7 @@
         // Commit!
         ki.commit();
 
-        KrillQuery kq = new KrillQuery("base");
+        QueryBuilder kq = new QueryBuilder("base");
         SpanQuery q = (SpanQuery) kq.or(
             kq._(1, kq.seg("s:a"))).or(kq._(2, kq.seg("s:b"))
         ).toQuery();
@@ -221,7 +223,7 @@
         // Commit!
         ki.commit();
 
-        KrillQuery kq = new KrillQuery("base");
+        QueryBuilder kq = new QueryBuilder("base");
         SpanQuery q = (SpanQuery) kq.seq(kq.seg("s:a")).append(kq.seg("s:b")).toQuery();
         KorapResult kr = ki.search(q);
 
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 f4472fe..b22bd7a 100644
--- a/src/test/java/de/ids_mannheim/korap/search/TestKrill.java
+++ b/src/test/java/de/ids_mannheim/korap/search/TestKrill.java
@@ -10,6 +10,7 @@
 import de.ids_mannheim.korap.KorapCollection;
 import de.ids_mannheim.korap.KrillQuery;
 import de.ids_mannheim.korap.KorapIndex;
+import de.ids_mannheim.korap.query.QueryBuilder;
 import de.ids_mannheim.korap.index.FieldDocument;
 import de.ids_mannheim.korap.meta.SearchContext;
 import de.ids_mannheim.korap.collection.CollectionBuilder;
@@ -34,7 +35,7 @@
     @Test
     public void searchCount () {
         Krill k = new Krill(
-          new KrillQuery("field1").seg("a").with("b")
+          new QueryBuilder("field1").seg("a").with("b")
         );
 
         KrillMeta meta = k.getMeta();
@@ -53,7 +54,7 @@
     @Test
     public void searchStartIndex () {
         Krill k = new Krill(
-            new KrillQuery("field1").seg("a").with("b")
+            new QueryBuilder("field1").seg("a").with("b")
         );
 
         KrillMeta meta = k.getMeta();
@@ -74,7 +75,7 @@
     @Test
     public void searchQuery () {
         Krill ks = new Krill(
-            new KrillQuery("field1").seg("a").with("b")
+            new QueryBuilder("field1").seg("a").with("b")
         );
         // query
         assertEquals(ks.getSpanQuery().toString(), "spanSegment(field1:a, field1:b)");
@@ -101,7 +102,7 @@
         ki.commit();
 
         Krill ks = new Krill(
-	        new KrillQuery("tokens").seg("s:Buchstaben")
+	        new QueryBuilder("tokens").seg("s:Buchstaben")
         );
 
         // Todo: This is not an acceptable collection, but sigh
@@ -623,7 +624,7 @@
         assertNull(fd.getDocAuthor());
 
         Krill ks = new Krill(
-            new KrillQuery("tokens").
+            new QueryBuilder("tokens").
             seg("mate/m:case:nom").
             with("mate/m:number:pl")
         );
@@ -714,7 +715,7 @@
         assertNull(fd.getDocAuthor());
         
         Krill ks = new Krill(
-            new KrillQuery("tokens").
+            new QueryBuilder("tokens").
             seg("mate/m:case:nom").
             with("mate/m:number:sg")
         );
@@ -746,7 +747,7 @@
             getFile()
         );
 
-        KrillQuery kq = new KrillQuery("tokens");
+        QueryBuilder kq = new QueryBuilder("tokens");
         Krill ks = new Krill(
             kq.focus(
                 1,